Programming Language Theory - Keio...

44
Programming Language Theory Takashi Hattori January 18, 2018 1 Introduction 1.1 About this course Syllabus 1 Advanced subjects—Series of Environmental And Information Studies Theoretical understanding of programming languages Prerequisite: knowledge about two or more programming languages 1.1.1 Evaluation Mid-term paper and presentation in class: 40points End-of-term exam: 40points Weelky assignments: 20points 90- S 80–89 A 70–79 B 60–69 C -59 D 1.2 Questions Why do we have so many programming languages? Why do you study the theory of programming languages? 1.3 Definition of a language It is important to define a new language in a rigorous and understandable way. Scheme gives a mathematically precise definition 2 , which is hard to understand. Languages such as BASIC and C did not give rigid definitions at first. As a result, we had several slightly different language processors. (cf. Announcing a specification for PHP 3 ) We need two things to define a language. Syntax—how you write a program Semantics—what will happen when executing a program 1 https://vu.sfc.keio.ac.jp/course2014/summary/syll_view_c.cgi?yc=2017_25442&ks=C2101&key=513a1f47290b0dfb628caec9225274e9&lang= 2 http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-10.html#%_chap_7 3 http://hhvm.com/blog/5723/announcing-a-specification-for-php 1

Transcript of Programming Language Theory - Keio...

  • Programming Language Theory

    Takashi Hattori

    January 18, 2018

    1 Introduction

    1.1 About this courseSyllabus1

    Advanced subjectsSeries of Environmental And Information Studies

    Theoretical understanding of programming languages

    Prerequisite: knowledge about two or more programming languages

    1.1.1 Evaluation

    Mid-term paper and presentation in class: 40points

    End-of-term exam: 40points

    Weelky assignments: 20points

    90- S8089 A7079 B6069 C-59 D

    1.2 Questions Why do we have so many programming languages?

    Why do you study the theory of programming languages?

    1.3 Definition of a languageIt is important to define a new language in a rigorous and understandable way.

    Scheme gives a mathematically precise definition2, which is hard to understand.

    Languages such as BASIC and C did not give rigid definitions at first. As a result, we had severalslightly different language processors. (cf. Announcing a specification for PHP3)

    We need two things to define a language.

    Syntaxhow you write a program

    Semanticswhat will happen when executing a program1https://vu.sfc.keio.ac.jp/course2014/summary/syll_view_c.cgi?yc=2017_25442&ks=C2101&key=513a1f47290b0dfb628caec9225274e9&lang=en2http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-10.html#%_chap_73http://hhvm.com/blog/5723/announcing-a-specification-for-php

    1

    https://vu.sfc.keio.ac.jp/course2014/summary/syll_view_c.cgi?yc=2017_25442&ks=C2101&key=513a1f47290b0dfb628caec9225274e9&lang=enhttp://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-10.html#%_chap_7http://hhvm.com/blog/5723/announcing-a-specification-for-php

  • 1.4 Differences among languages1.4.1 Character

    Unique symbols (cf. APL4)

    Japanese characters (cf. Mind5, Kotodama6, Nadesiko7)

    Graphics (cf. Marten8, ToonTalk9)

    1.4.2 Grammar

    Example: Esoteric languages

    whitespace10

    Befunge11

    Example: Various syntax for iteration

    Old Fortran

    DO 10 I = 1,100...

    10 CONTINUE

    Pascal

    for i := 1 to 100 dobegin ... end;

    C

    for (i = 1, i

  • 1.4.3 Paradigm

    Philosophically speaking, programming paradigm means What is computation?.

    Imperative(Procedural)

    Computation is a sequence of changing state.

    Functional

    Computation is a reduction of expression.

    Logical

    Computation is a proof of proposition.

    There are other kinds of paradigms. For example, object oriented paradigm covers other steps of thesoftware development process such as requirements specification as well as implementation.

    1.5 Definition of good programming language readability / writability

    simple

    expressive

    high abstarction level

    performance

    fast execution

    small memory usage

    fast compilation

    efficient in development process

    easy to find bugs

    low learning cost (time and effort)

    low development cost of compiler or interpreter

    1.6 History of programming languagesevolution diagram12

    machine language / assembly language (example13)

    craftsmanship

    high level language

    performance deterioration in some extent

    dramatic improvement of efficiency in development process

    very good readability and portability

    structured programming language

    12http://merd.sourceforge.net/pixel/language-study/diagram.html13http://www.eecs.umich.edu/courses/eecs284/example1.htm

    3

    http://merd.sourceforge.net/pixel/language-study/diagram.htmlhttp://www.eecs.umich.edu/courses/eecs284/example1.htm

  • maintenance of a large program is problematic

    goto statement considered harmful by Dijkstra

    object oriented language

    everything is an object

    lightweight language / dynamic language

    handy tool for programming

    1.7 Reasons to study the theory of programming language You can select a language suitable for a task in your hand.

    You can learn a new language easily.

    You can understand the background of software better

    Different languages may well introduce different ideas and solutions.

    It is an important base of the computer science.

    2 Syntax and Semantics

    2.1 Brief introduction to the formal language theory2.1.1 Definition of formal languages

    Alphabet

    a set of characters

    Sentence

    a sequence of characters

    Grammar

    a set of rules to determine if a sentence is correct or not

    Language

    a set of correct sentences

    We often use tokens instead of alphabets because of simplicity. A token is something like a word composedof several letters.

    Example: An example of tokens

    Sentence total = total + x; can be decomposed into a sequence of characters t, o, t, a, l, *space*,=, *space*, t, o, ..., which is cumbersome. Instead, we usually use a sequence of tokens total, =,total, +, x, ;.

    Generative Grammar14 defines a language by generating correct sentences in some manner.

    Terminal symbols

    Tokens used in languages

    14http://en.wikipedia.org/wiki/Generative_grammar

    4

    http://en.wikipedia.org/wiki/Generative_grammar

  • Non-terminal symbolsSymbols representing structures of sentences. One of them is designated as the initial symbol.

    Production rulesRules to rewrite some non-terminal symbols to other symbols. Starting from the initial symbol, wecan generate a correct sentence by repeatedly applying rules.

    Example: Simple grammar

    Terminal: I, you, love

    Non-terminal: S, N, V

    Initial symbol: S

    Rule: S->NVN, N->I, N->you, V->love

    There are several classes of grammars such as context-free grammar and regular grammar. Most ofprogramming languages can be defined using context-free grammar15.

    2.1.2 BNF notation

    BNF (Backus-Naur Form) is a convenient notation to write a context-free grammar for practicaluse.

    Terminal symbols are written as they are.

    Non-terminal symbols are enclosed by < >.

    Production rules are in the form non-terminal ::= symbols where we can write multiple alternativesby separating with | in the right side.

    Example: Simple arithmetic expression

    ::= A | B | C ::= | ( ) ::= | + | *

    2.1.3 Parse tree

    To parse is to find how a sentence is generated by production rules. A parse tree is a tree structure thatrepresents the result of parsing.

    Example: Parse tree of A*(B+C)

    Exercise 1Draw a parse tree of A+B*C with the grammar shown above.

    Exercise 2In the grammar shown above, there is no precedence between + (add) and * (multiply). Change the

    grammar so that * takes precedence over + ?15http://en.wikipedia.org/wiki/Formal_grammar

    5

    http://en.wikipedia.org/wiki/Formal_grammar

  • 2.1.4 Ambiguous grammar

    We say a grammar is ambiguous if more than one parsing is possible for one sentence.

    Example: An example of ambiguous grammar

    We have two different parse trees for A*B+C with the following grammar.

    ::= A | B | C ::= | + | *

    Example: Dangling else

    Languages such as C and Java have dangling-else problem since else is optional in if statements.

    6

  • ::= if ( ) |if ( ) else

    Exercise 3Explain dangling-else problem in case of the following statement.

    if ( x > 0) if ( y > 0 ) z = 1; else z = 2;

    Exercise 4Explain that the following grammar is ambiguous.

    ::= ::= | A | B | C

    2.2 Glance at the semantics theoryIt is very difficult to define semantics of languages precisely. In C and Java, we usually say the meaning of++ operator is first evaluate the variable, then increment it. However, we cannot figure out the result of x= 1; x = x++; with this definition. As long as we use a natural language, ambiguity is inevitable.

    Exercise 0Write a program to show the value of x after x = 1; x = x++; in C and Java. What are the results?There are several formal semantics theories that can give rigorous definition of languages.

    2.2.1 Operational semantics

    The operational semantics16 describes how a program is executed as a sequence of computational steps.

    A computational step is a change of state in the computer.

    The state in the computer is, for example, a mapping from variables to values (a model of the memorydevice).

    By logical inference rules, we can define what kind of computational steps are possible.

    2.2.2 Axiomatic semantics

    The axiomatic sematnics is based on Hoare logic17. The meaning of a sentence is determined by a pair ofprecondition (which is true before the execution of the statement) and postcondition (which is true after theexecution).

    It is closely related to verification of a program.

    2.2.3 Denotational semantics

    The denotational semantics18 is based on recursive functions and domain theory. It constructs mathematicalobjects that describes the meaning of a program. Unfortunately, the result is often very hard to read19.

    16http://en.wikipedia.org/wiki/Operational_semantics17http://en.wikipedia.org/wiki/Hoare_logic18http://en.wikipedia.org/wiki/Denotational_semantics19http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-10.html#%_sec_7.2

    7

    http://en.wikipedia.org/wiki/Operational_semanticshttp://en.wikipedia.org/wiki/Hoare_logichttp://en.wikipedia.org/wiki/Denotational_semanticshttp://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-10.html#%_sec_7.2

  • 3 Names and Bindings

    3.1 Names in a programWe need names (or identifiers ) in order to denote various entities in a program.

    Syntax of names differs depending on the language. In most languages, a name is a sequence ofalphabets, numbers and some symbols.

    In some languages, there is a limit on the length of names.

    There are case-sensitive languages and case-insensitive languages.

    A Keyword is a name which plays some designated role in syntax. A reserved word is a keyword whichcannot be used with other meaning.

    Example: Fortran has no reserved word

    The following Fortran program is syntactically correct.

    INTEGER REALREAL INTEGERREAL = 3INTEGER = 1.2

    3.2 NamespaceWe need long names to avoid conflict when we use many names. It is not convenient, however, to read andwrite long names. A namespace is a name given to a set of names, which allows us to make the hierarchy ofnames, in other words, to use concatenated short names instead of a single long name.

    Example: Namespace in C++

    :: is the operator to concatenate names.

    #include

    main() {std::cout

  • import foox = foo.bar()

    from foo import barx = bar()

    3.3 Bindings3.3.1 Definition of bindings

    Binding

    a link between a name (more precisely, an occurence of a name) and a certain semantic entity.

    Environment

    a set of bindings currently used during execution.

    We call a binding static when it can be determined before execution (usually compile-time). Otherwise,we call it dynamic.

    Example: TinyBASIC

    TinyBASIC (very small BASIC interpreter) has only 26 variables: A to Z. In this case, we always usethe same environment.

    Example: Variable declaration in Java

    In Java, a variable declaration int i; means we will bind a name i to a newly created integer variable.

    Exercise 5There are two types of languages as to varibale declarations. Languages such as C and Java require

    declarations before variables are used, while languages such as Perl and Ruby do not. What are merits anddemerits of these two types?

    3.3.2 Anonymous and alias

    Bindings are not necessarily one-to-one association.We call an entity (e.g. variable, function, etc.) anonymous if it is not bind to any name.

    Example: Anonymous function in JavaScript

    function(x) { return x+1; }

    Example: Anonymous function in Lisp

    (lambda (x) (+ x 1))

    9

  • On the contrary, one entity can be bound to more than one names. In such case, names which bound tothe same entity are called alias of each other.

    Example: Alias statement in Ruby

    alias $b $a$a = 2puts $b

    Example: EQUIVALENCE statement in Fortran

    DIMENSION A(10), B(5)EQUIVALENCE(A(6), B(1))

    3.4 ScopeA scope is a part of program where a binding is used (in other words, we can see an entity through its name).

    3.4.1 Static scoping

    In Algol-based languages, the scope of a name is a block in which the name is declared. If the same name isdeclared more than once, the most inner one takes precedence over outer ones. This type of scoping is alsocalled lexical scoping because it is determined by the lexical stuructres.

    Example: Static scoping in Pascal

    procedure main;var x : integer; { declaration 1 }

    procedure sub1;begin

    ... x ...end;

    procedure sub2;var x : integer; { declaration 2 }begin

    ... x ...end;

    { body of main }begin

    ... x ...end;

    10

  • 3.4.2 Dynamic scoping

    In ancient Lisp and APL, if a name is declared in a function A, its scope extends to other functions calledfrom A. If the same name is declared more than once, the most recent one takes precedence over older one.

    Example: Dynamic scoping in pseudo code

    procedure main;var x : integer; { declaration 1 }

    procedure sub1;begin

    ... x ...end;

    procedure sub2;var x : integer; { declaration 2 }begin

    sub1end;

    { body of main }begin

    sub1;sub2

    end;

    3.4.3 Closure

    In languages such as Lisp, Ruby, JavaScript, etc., a function is a first-class object (i.e. it can be assignedinto a variable, passed as a parameter, etc.). Suppose we have a function stored in a variable. When thefunction is called, the scope of names are determined in the place the function is defined (not the place thefunction is called). In other words, the stored function remembers the environment at the place of definition.This feature is called a closure.

    Example: Closure in Ruby

    def foox = 1proc { x += 1 }

    end

    bar = foo()x = 100puts bar.callputs bar.callputs bar.call

    proc { x += 1 } produces a closure that increments the variable x. It is returned by the function fooand then assigned into the variable bar. Even if the closure is called outside the scope of x, it increments xdefined in foo.

    11

  • Example: Closure in JavaScript

    function foo() {var x = 1;return function() { return x += 1; };

    }

    var bar = foo();var x = 100;console.log(bar());console.log(bar());console.log(bar());

    Exercise 6Suppose we want to create 10 buttons in a web page20, each of which will show its id number when

    clicked. But the following JavaScript code does not work. Explain why.

    for (i = 0; i fly() // falsex = y;x->fly() // true

    }20exercise6.html

    12

    exercise6.html

  • We need virtual functions if we want to use late bindings.

    class Bird {public:

    virtual bool fly() { return true; }};

    class Penguin : public Bird {public:

    virtual bool fly() { return false; }};

    int main() {Bird *x;Penguin *y;

    y = new Penguin();y->fly() // falsex = y;x->fly() // false

    }

    4 Variables

    4.1 What is a variable?A variable in mathematics represents a possibility of a value. If a range is designated to a variable, thevariable may take one of values in the range. The selection of the value must be consistent throughout aproof.

    A variable in functional and logical programming languages is similar to that in mathematics. A variablename is bound to a value. Once bound, it never changes. Note that the same name may be bound to adifferent value in the different environment.

    A variable in imperative (procedural) programming languages is a named box to store a value. A variablename is bound to a certain memory area. The value in the memory area may change during execution ofthe program.

    In the remaining part of this section, we mainly deal with variables in imperative (procedural) languages.

    4.2 TypeMany languages such as Fortran, Pascal, C and Java have a type as a property of a variable. In theselanguages, a type must be declared for a variable before its use, and the variable can only store values ofthat type.

    On the other hand, languages such as Lisp, JavaScript, Python, PHP and Ruby have no types. A variablecan store any value.

    We will learn about types 5.

    4.3 Left valueA memory area is the essential part of a variable. A value is stored there during program execution.

    If a variable name occurs in a program, it is evaluated as follows:

    1. Get an address of a memory area which is bound to the name.

    13

  • 2. Get a value from the memory area.

    If a variable name occurs in the left side of an assignment statement, however, the result of evaluationshould be an address to store a new value. Sometimes we call an address as a left value.

    4.4 Memory managementCompilers (or interpreters) need to allocate some memory area for each of the variables. There are severalmemory management methods as described below.

    4.4.1 Static data area

    A static variable is a variable that exists across the entire execution of the program. It is usually allocatedin the static data area at compile time.

    One of the merits of type declaration is that the required amount of memory can be calculated at compiletime based on the type declared. If we have no type declaration, the memory area for a variable usuallycontains a pointer that refers to a 4.4.3 where we can allocate required amount of memory at run time.

    4.4.2 Stack

    A stack is a first-in-last-out data structure. It is often used for the area to allocate local variables. When afuction is called, parameters and local variables are allocated at the top of the stack. When that functionreturns, the allocated area is discarded.

    Recursive call can be easily implemented.

    When using dynamic scoping, we can find the valid bindings by searching downwards from the top ofthe stack. It is easier to implement than static scoping.

    A variable which occurs in a closure should not be allocated in the stack because the variable will beused when the closure is called afterwards (see 4.5).

    4.4.3 Heap

    A heap is a data structure in which we can allocate some amount of memory when required and release itwhen not necessary any more. The released area will be reused for other purposes.

    Some languages require the programmers to write a code for releasing unnecessary area. They often(very often) forget to write the code, resulting a situation where we have no new area to allocate even if theactually used area is small. We call this situation as a memory leak.

    In order to avoid the memory leak, some languages provide garbage collection which automatically releasesunnecessary area. We can determine a certain area is unnecessary if there is no refrence to the area.

    Followings are the typical garbage collection methods:

    Reference count

    A counter is attached to each memory area. When someone starts to refer the area, increment thecounter. When stopping to refer, decrement it. If the counter becomes 0, release that area.

    Mark and sweep

    First, we put a mark on every area reachable by following references from areas obviously necessary(e.g. an area bound to a variable name). Next, we sweep the entire heap from end to end, and releaseareas that are not marked.

    Copying

    We divide the heap into two, and use only half. When there is no available area to allocate, we copythe necessary area to the other half by following references starting from obviously necessary areas.This method achieves compaction as well as garbage collection.

    14

  • Garbage collection usually requires to stop the execution of the program during it takes place. Since it isinconvenient for real-time systems, there are devised garbage collection methods that can be done in parallelwith the execution of the program.

    Exercise 7Suppose we use reference count garbage collection. In some cases, the counter of unnecessary area will

    not become 0. Give an example.

    Exercise 8Explain why we should stop the execution of the program when using mark-and-sweep garbage collection.

    4.5 ExtentAn extent is a time period during which a variable holds its value. Note that a scope and an extent aredifferent in general.

    Example: Static local variables

    In languages such as C and PHP, a local variable declared as static has a scope of that function, butits extent is the entire execution of the program.

    function foo(){

    static $a = 0;echo $a;$a++;

    }

    Example: Variables in a closure

    In the 3.4.3, we need the value of x after the function foo returns.

    function foo() {var x = 1;return function() { return x += 1; };

    }

    Exercise 9What are the scope and extent of the variable x in the above example?

    5 Types

    5.1 What is a type?A type consists of a set of values and designated operations on the values. A type system is a set of rulesthat associates syntactic entities such as expressions and variables with their types.

    15

  • 5.1.1 Why use types?

    Some languages provide sophisticated type systems while others do not use types at all. Major reasons whywe use types are as follows:

    More informative for human readers.

    Compilers can detect errors when types mismatch.

    Compilers can generate more efficient code.

    Exercise 10An integer is used for conditional branch (0 is false, otherwise true) in C, while boolean and int are

    different types in Java. What are merits and demerits of these two methods.

    5.1.2 Type systems

    Dynamic typing: Syntactic entities (variables, functions) have no types whereas semantic entities (data)have types. Any value can be assigned to any variable.

    Static typing: Types of syntactic entities are determined before execution based on type declarations.In many languages, variables and functions (parameters and return values) need type declarations.

    5.2 Various typesPrimitive types

    Hardware-defined or indecomposable types. (e.g. integer, floating point, character)

    Structured types

    Types composed of some other types. Many languages allow programmers to define new types.

    5.2.1 Enumerated type

    We can define a new enumerated type by writing all the possible values for that type.

    More readable.

    Usually implemented by integer, but only comparison is allowed.

    Example: Colors

    In Pascal, we can define a type representing colors whose value is one of red, blue, green.

    type colortype = (red, blue, green);var x : colortype;begin

    ...x = blue;case x of

    red : ...blue : ...green : ...

    end;end;

    In Pascal, red < blue is syntactically correct while red + blue is not.

    16

  • 5.2.2 Subrange type

    A subrange type is an extraction of a certain ordinal type by specifying its highest and lowest values.

    Same operations are allowed as the original type.

    We can detect errors when values are out of range.

    Example: Upper case letters

    In Pascal, we can define a new uppercase type from the char type.

    type uppercase = A .. Z;

    Example: Range of an array

    In Pascal, we can use any ordinal type as an index of an array. Usually a subrange of integer is used.

    var x : array [1..100] of char;

    5.2.3 Union type

    A union type is a type whose value may be one of several different types.In C, union allows programmers to access the same memory location with more than one types.

    It is up to programmers which type is used to read and write.

    Some programmers intentionally use it for evil purposes.

    In Pascal, record with variant parts provides more sophisticated way.

    A tag field indicates the type currently stored in a variant part.

    An error occurs when an operation mismatches with the type in the tag.

    Still, some programmers may intentionally change the tag value to avoid type checking.

    Example: Circles and rectangles

    In Pascal, we can define a new record type figure which can store either a circle or a rectangle. A circlehas fields x, y and radius, and a rectangle has x, y, width and height.

    { shape is an enumerated type whose value is circle or rectangle }type shape = (circle, rectangle);{ figure is a record type }type figure = record

    { there are x and y for all cases }x : real, y : real{ variant parts whose tag is form }case form : shape of

    { in case of the value of form is circle }circle: (radius : real);{ in case of the value of form is rectangle }

    17

  • rectangle: (width: real; height: real);end;

    var myfigure : figure;begin

    ....myfigure.x = 2.0; myfigure.y = 3.0;myfigure.form = circle;myfigure.radius = 1.0;...

    end

    5.2.4 Pointer type

    A pointer type is a type whose value is a reference to another variable. By applying dereference operation,we can get a value of the referred variable.

    By using pointers, we can dynamically allocate variables that are not bound to any names. It may causethe following two problems:

    Dangling PointerIf a memory area is released during a pointer is referring to it, the pointer will refer to a garbage or areused area.

    Lost Heap-dynamic VariableIf values of pointers are changed, the memory area referred by the pointers may lose all the references,which means we can never access that area.

    In case of Pascal, a pointer can only refer to an area allocated by new. We must explicitly release theallocated area by dispose. Pascal has the above two problems.

    In case of C, pointers are virtually same as the hardware memory addresses. C has many problemsincluding the above two.

    In case of Java, objects are implicitly referred to by pointers. Automatic garbage collection preventsthe above two problems.

    Example: Linked list in Pascal

    type link = ^cell;cell = record

    info : integer;next : link;

    end;

    var p, front : link;begin

    ...new(p);p^.info := i;p^.next := front;front := p;...

    end

    18

  • 5.2.5 Function type

    A function type is composed of types of parameters and return values. It will be very complex for higher-orderfunctions (i.e. parameters or return values are functions).

    Example: Function type in Haskell

    inc :: Int -> Intinc x = x + 1

    add :: Int -> Int -> Intadd x y = x + y

    twice :: (Int -> Int) -> Inttwice f = f(f(1))

    twice(inc) -- => 3

    5.3 Type conversion5.3.1 Implicit conversion

    In some cases, a value of a certain type is automatically converted into another type for convenience.

    Example: Arithmetic operation

    In most languages, when an arithmetic operation applies to an integer and a floating point number, theinteger is converted into a floating point number. For example, 3 / 2.0 is converted into 3.0 / 2.0.

    Example: String concatenation

    In Java, when + operator applies to a number and a string, the number is converted into a string. Forexample, 2 + "3" is converted into "2" + "3".

    5.3.2 Explicit conversion

    In some languages, programmers can change types of certain values.

    Example: Cast

    In C and Java, writing a type name before an expression instructs a conversion to that type.

    (int)(3.0 / 1.5)

    5.4 Type checkingThe process of verifying consistency of types in a program is called type checking. Type checking at compiletime is very useful for debugging.

    19

  • 5.4.1 Type declaration

    In many languages, a type is explicitly declared for a variable.

    In Fortran, an implicit declaration is possible where a variable is typed according to the initialletter of its name: integer if beginning with I, . . . , N, and real if beginning with other letters.

    In ML and Haskell, a type can be declared for any expression in a program.

    Example: Number constant in Haskell

    3 -- polymorphic type3::Int -- integer3::Float -- floating point

    5.4.2 Type compatibility

    We need a rule to determine compatibility of two user-defined types.

    Name compatibility

    Types are different if their names are different. Easy to implement, but inconvenient in many cases.

    Structure compatibility

    Types are different if their structures are different.

    Example: Type compatibility in Ada

    In the following Ada code, FLOAT, celsius, and fahrenheit are different types with each other sinceAda uses name compatibility.

    type celsius is new FLOAT;type fahrenheit is new FLOAT;

    5.5 Type inferenceIn languages such as ML and Haskell, every expression in a program should have its type. It is too painfulto write types for all expressions, the compiler makes an inference about proper typing if we give minimumdeclarations.

    Example: Type inference in ML

    We need no type declaration for the function inc.

    fun inc x = x + 1;val inc = fn : int -> int

    We need at least one type declaration for the function add.

    20

  • fun add (x, y) = x + y;Error: overloaded variable + cannot be resolved

    fun add (x, y) = x + (y : int);val add = fn : int * int -> int

    fun add (x, y) : int = x + y;val add = fn : int * int -> int

    Note: In SML ver0.5 or after, the + operator is an overloaded function that has default type int, whichmeans fun add(x, y) = x + y; has the type fn: int * int -> int.

    5.6 PolymorphismWhen a single operator or function can deal with values of more than one type, we call it polymorphism.

    ad hoc polymorphism

    Definitions for each type are independent. Also called overloading.

    parametric polymorphism

    Definitions include formal parameters that receive types of data currently processed.

    Example: + operator in Java

    In Java, + operator has two meanings: addition of numbers and concatenation of strings.

    Example: Template in C++

    We can write a function max in C++ as follows:

    template Type max(Type first, Type second) {

    return first > second ? first : second;}

    int a, b, c;char d, e, f;c = max(a, b);f = max(d, e);

    Example: Polymorphic function in Haskell

    In Haskell, the type of function length is [a]->Int where a is a type variable and [ ] is an array type.expression type valuelength [a]->Int function[3::Int, 4] [Int] [3, 4]"abc" [Char] "abc"length [3::Int, 4] Int 2length "abc" Int 3

    21

  • Exercise 12In Haskell, an expression map f x applies the function f to each element of the array x, and then make

    an array collecting their results. For example, the result of map length ["abc", "de"] is [3, 2]. Writethe type of function map, using type variables a and b.

    6 Mid-term paper

    Exercise 11 Exercise 11

    Pick one programming language (except for C, C++, Java, JavaScript), and answer the following question.

    1. Explain features of the language, comparing with other languages.

    2. Give a sample program that fully shows the features of the language. (It is not necessary to write itby yourself. It should be a complete program without any omission.)

    3. Explain why you choose the sample program above.

    Note that:

    The less popular language you pick, the higer score you get.

    Features of a language means syntactic or semantic properties of the language. It does not mean, forexample, there are plenty of libraries, or there is a very good development environment.

    It is not necessary to run the sample program. It is all right if a compiler (or an interpreter) is notavailable as long as specification of the language is clear enough.

    You are strongly requested to cite references. Otherwise you are considered to commit plagiarism.

    There is no restriction about the length of the paper. Normally 2 or 3 pages in A4.

    Deadline is November 30th.

    You should give a presentation in class after December 1st. 2 or 3 students in each week.

    7 ExpressionsAn expression is a syntactic structure that has a value. The most typical example is an arithmetic expressionsuch as a-b+c, where - and + are operators. Unary operators take one argument (e.g. -a) while binaryoperator take two arguments (e.g. a+b).

    7.1 Precedence and associativity of operatorsWhen given an expression, we can investigate its structure by making its ??. We have learned 2.1.2 to writea grammar, but we prefer operator precedence grammar for expressions because it is much simpler.

    Each operator has its precedence. The higher the precedence of a certain operator is, the smallersub-tree it makes (in other words, it connects its arguments earlier than other operators).

    Each binary operator is either left-associative or right-associative. When there are more than oneoperator of the same precedence in an expression, if they are left-associative, the leftmost operatorconnects its arguments first. If right-associative, the rightmost connects first.

    22

  • Instead of drawing parse trees, we usually use parentheses to indicate which part is connected earlierthan other parts.

    Example: Precedences of arithmetic operators

    In most languages, arithmetic operators have the same precedences as mathematics. For example, a +b * c is equivalent to a + ( b * c ).

    Example: Associativities of arithemtic operators

    In most languages, arithmetic operators are left-associative. For example, a - b + c - d is equivalentto (( a - b ) + c ) - d.

    Example: Precedence and associativity in APL

    In APL, all operatos have the same precedence, and are right-associative. For example, A B + C isequivalent to A ( B + C ).

    Exercise 13Suppose precedences and associativities of operators are given by the following table. Put parentheses at

    proper positions in expressions below so that their structures are explicit.operators precedences associativities#, $ high left-associative!, ? low right-associative

    1. a # b $ c

    2. a ! b ? c

    3. a # b ! c $ d

    4. a # b ! c ? d

    5. a # b $ c ! d ? e

    7.2 Order of evaluationEvaluation is the process of computing values of expressions.

    Note that the order of evaluation is a different concept from precedence and associativity.

    Example: Evaluation order of arithmetic operations

    In C, given an expression a*b+c*d, it is undefined that either a*b or c*d is evaluated first.

    Example: Side effect and evaluation order

    In the following C program, the result is different depending on that either a or fun1() in the statement(1) is evaluated first.

    23

  • int a = 1;

    int fun1() {a = 2;return 3;

    }

    void fun2() {a = a + fun1(); /* (1) */

    }

    void main() {fun2();

    }

    As shown above, side effect causes a problem if the order of evaluation is undefined. We may think ofseveral solutions as follows:

    1. Do nothing.The result is compiler dependent.

    2. Prohibit side effect.It is not practical for imperative languages.

    3. Compiler generates a warning if there is a risk.It is hard to detect.

    4. Define the order of evaluation.It obstructs optimization.

    Java adopts (4). It evaluates an expression from left to right (See What are the rules for evaluationorder in Java?21 for detail).

    C/C++ introduces a sequence point22, which is a mixture of (1) and (4).Functional languages such as ML and Haskell receive benefit from (2).

    7.3 Short-circuit evaluationShort-circuit evaluation is an evaluation strategy where some subexpressions may not be evalu-ated if the value of the entire expression can be determined without it.

    Example: Logical operators

    When the value of a is less than 0, the following expression can be evaluated to false without evaluatingb < 10.

    ( a >= 0 ) && ( b < 10 )

    Exercise 14Java has two types of logical operators: && and || are short-circuting and & and | are not. Explain why

    we need both types of operators.

    21http://stackoverflow.com/questions/6800590/what-are-the-rules-for-evaluation-order-in-java22http://en.wikipedia.org/wiki/Sequence_point

    24

    http://stackoverflow.com/questions/6800590/what-are-the-rules-for-evaluation-order-in-javahttp://stackoverflow.com/questions/6800590/what-are-the-rules-for-evaluation-order-in-javahttp://en.wikipedia.org/wiki/Sequence_point

  • 7.4 Lazy evaluationLazy evaluation is an evaluation strategy where an expression is not evaluated until its value is used in otherparts later.

    It is a generalization of short-circuit evaluation.

    Example: range in Python3

    for i in range(10000):if i > 10: breakprint(i)

    In Python2, range(10000) generates a list of 10000 elements and returns them. In Python3, range(10000)returns a list whose elements are not evaluated. The elements will be generated one by one when each timeprint(i) is executed.

    8 Control structures

    8.1 Structured programmingLanguages in early days such as Fortran and COBOL use goto statement extensively, which results in obscureprogram structure. In 1968, Dijkstra insisted a program structure is more readable if it is a hierarchicalcomposition of sequences, iterations and conditional branches.

    Example: Loop in early Basic and Pascal

    10 X=120 IF X>=1000 THEN GOTO 6030 PRINT X40 X=X*250 GOTO 2060 END

    x = 1;while x

  • def barthrow :a, 3

    end

    def foobar

    end

    catch(:a) dofoo

    end

    8.3 Exceptions8.3.1 What is exception?

    In early languages, if something unusual occurs during execution, the program has no choice but to stopwith an error message. Recent languages can deal with such situation more gracefully.

    An exception is an unusual event in a program for which we need some extra processing.

    Detected by hardware: division by zero, to read or write protected memory, end of file, etc.

    Detected by software: index of an array is out of range, etc.

    Defined by programmers: anything you wish.

    8.3.2 Exception handling

    An exception handler is a part of program that is invoked when an exception occurs.The merits of exception handling is as follows:

    No need to write codes for detecting exceptions. Imagine if you need to check that the divisor is notequal to 0 before every division!

    Cleaner code for dealing with an unusual event, especially when it requires non-local exits.

    We can manage several exceptions in one place.

    Languages such as Java force programmers to write exception handlers so that their programs arerobust in unexpected situation.

    Example: Exception handling in PL/I

    An exception handler can be written in anywhere in the program with the ON statement. For example,the following is a handler for an exception SUBSCRIPTRANGE, which occurs when an index of an array is outof range.

    ON SUBSCRIPTRANGEBEGIN;

    PUT LIST (ERROR) SKIP;END;

    26

  • Note that the ON statement is an executable statement (not a declaration), which means bindings betweenexceptions and exception handlers are dynamic. An exception handler is valid after an ON statement isexecuted, and until another ON statement with the same exception name is executed.

    In addition, in order to make an execption handler valid, we need to write an exception name before apart of the program in which the exception may occur. For example, the following code checks the index Iif it is out of range or not.

    (SUBSCRIPTRANGE):BEGIN;

    A = B(I);END;

    Example: Exception handling in Java

    An exception is represented by an instance of an exception class, which is passed to a handler as anargument.

    Exception classes are hierarchical. An execption handler can deal with many kinds of exceptions byspecifying a high level exception class in the hierarchy.

    Bindings between exceptions and exception handlers are lexical. try-catch-finally statement makesthe scope of handlers.

    By declaring throws at the head of a method, an exception can be propagated to the calling method,which allows dynamic bindings between exceptions and exception handlers.

    If there is a possibility of an exception, programmers must either write an exception handlers for it orpropagate it to the calling method.

    Exercise 15Java forces programmers to handle exceptions, but that is not the case for Error and RunTimeException.

    Guess the reason.

    9 Subprograms

    9.1 What is a subprogram?A subprogram is a chunk of code that is independent from other parts to some extent. In most languages,subprograms have the following properties.

    There is a single entry point. (Fortran provides multiple entry points.)

    When a subprogram A calls another subprogram B, A will pause until B terminates. Namely, there isonly one subprogram which is executed at a time. (This is not the case for concurrent languages.)

    In some languages, a subprogram that returns a value is called a function and one that does not is calleda procedure or a subroutine, but both types of subprograms are called functions in other languages such asC. In addition, object-oriented languages usually use the term methods for them.

    27

  • 9.2 ParametersA parameter is used in order to apply a single subprogram to various data.

    Actual parameters

    Data specified when a subprogram is called.

    Formal parameters

    Variable names used in a subprogram to store actual parameters.

    In many languages, acutal parameters are associated to formal parameters by their position (positionalparameters). It is error-prone when a subprogram has many parameters.

    In languages such as Ada and Fortran90, the association between actual parameters and formal param-eters is explicitly specified (keyword parameters). In addition, any actual parameter can be omitted if adefault value is declared for the associated formal parameter.

    Example: Parameters in Ada

    Suppose we have the following declaration in Ada.

    procedure Draw_Rect( X , Y : Integer;Width : Integer := 10;Height : Integer := 10;Color : Integer := 0 )

    We may write any of the following procedure calls.

    Draw_Rect( Width => 20, X => 100, Y => 50, Color => 1 )Draw_Rect( 100, 50, Width => 20, Color => 1 )

    9.3 Passing parameters9.3.1 Direction of passing

    Input

    Data are passed from actual parameters to formal parameters when a subprogram is called.

    Output

    Data are passed from formal parameters to actual parameters when a subprograum finishes its execu-tion.

    In case of output, the actual parameter must be a mutable object (which has a 4.3).

    Example: Passing parameters in Ada

    procedure Foo(A : in Integer;B : in out Integer;C : out Integer) is

    beginB := B + 1;C := A + B;

    end Foo;

    28

  • 9.3.2 Evaluation strategy of parameters

    Pass by value (call by value) First, all the actual parameters are evaluated. Then, the values are copiedto formal parameters.

    It is usually used for input direction. In case it is used for both input and output, we specifically call itpass by copy-restore.

    Pass by reference (call by reference) Formal parameters are bound to entities referred by associatedactual parameters. In other words, formal parameters become 3.3.2 of actual parameters.

    Its direction is inherently both input and output.

    Example: Passing parameters in Pascal

    In Pascal, a foraml parameter declared with var is pass-by-reference, otherwise pass-by-value (inputonly).

    For example, the following procedure does nothing at all.

    procedure swap(a, b : integer)temp : integer;begin

    temp := a;a := b;b := temp

    end;

    If we change the first line as follows, it will swap two parameters as intended.

    procedure swap(var a, b : integer)

    Pass by name (call by name) Actual parameters are evaluated each time associated formal parametersare used in the body of subprograms. The environment used for evaluation is the one at the place where thesubprogram is called. In other words, 3.4.3 that evaluate actual parameters are passed to formal parameters.

    Example: Side effect and pass-by-name

    Suppose the following pseudo code uses pass-by-name.

    main() {int x = 1;output foo(bar(x));

    }

    int foo(y) {int x = 10;return x + y + y; /* bar(x) is substituted for y */

    /* bar is called twice here */}

    int bar(z) {z = z + 1; /* x in main is substituted for z */return z;

    }

    29

  • Exercise 16When pass-by-value (input only), pass-by-reference, and pass-by-name are used, answer the value of

    variables x and list after execution of the following code, respectively.

    void main() {int x = 2, list[5] = {1, 3, 5, 7, 9};swap(x, list[0]);swap(list[0], list[1]);swap(x, list[x]);

    }void swap(int a, int b) {

    int temp;temp = a;a = b;b = temp;

    }

    9.4 CoroutineWhen a subprogram can suspend itself in the middle of its execution, and make another subprogram resumefrom its suspended state, we call them coroutine.

    Example: Fiber in Ruby

    fib = Fiber.new {a,b = 0,1loop {

    Fiber.yield aa,b = b,a+b

    }}

    puts fib.resumeputs fib.resumeputs fib.resumeputs fib.resumeputs fib.resume

    Coroutine is a form of non-preemptive concurrent programming. We will study about concurrent pro-gramming in chapter 11.

    10 Object Oriented Programming

    10.1 Abstraction and ModularizationWhen writing a large program, the following concepts are very important.

    AbstractionOnly essential functions and properties are taken into consideration by hiding other parts.

    ModularizationA program is divided into several parts so that modification of one part does not affect other parts.

    30

  • Abstraction and modularization of control flow is mainly done by subprograms. In addition, we needabstraction and modularization of data structures.

    10.2 Abstract data typeAn abstarct data type is a type that has following properties:

    From outside, we cannot say how data are actually represented and stored.

    The only available operations from outside are subprograms given by the abstract data type.

    The two properties above provide abstarction and modularization of data structures. Since we do notknow actual representation of data, modificatin inside an abstract data type does not affect outside. This isalso called encapsulation or information hiding.

    Example: Floating point numbers

    Floating point numbers can be considered as an abstarct data type.

    Programmers who use a high-level language do not need to know the bit-patterns used to representnumbers. (cf. IEEE Standard 75423)

    Some CPUs may use other bit-patterns or do not have floating point instructions at all, but we donttake care as long as the same results are produced.

    10.3 Package in AdaAt the time Ada was designed, there was no such thing as Internet. It was very important to supportdevelopment of a large program by dividing it to several modules which were developed in different places.

    package is the unit of encapsulation.

    A package consists of a specification package and a body package of the same name.

    A specification package contains interface information. When compiling, only specification package isrequired to use that package.

    Though a specification package is basically a public information, a private part can be declared in aspecification package.

    Example: Stack package

    package Stack_Pack is-- public parttype Stack_Type is limited private;function Empty(S : in Stack_Type) return Boolean;procedure Push(S : in out Stack_Type;

    Element : in Integer);procedure Pop(S : in out Stack_Type);function Top(S : in Stack_Type) return Integer;-- private partprivate

    Max_Size : constant := 100;23https://en.wikipedia.org/wiki/Single-precision_floating-point_format

    31

    https://en.wikipedia.org/wiki/Single-precision_floating-point_format

  • type Stack_Type isrecordList : array ( 1 .. Max_Size ) of Integer;Top_Index : Integer range 0 .. Max_Size := 0;end record;

    end Stack_Pack

    package body Stack_Pack isfunction Empty(S: in Stack_Type) return Boolean is

    beginreturn S.Top_Index = 0;

    end Empty;procedure Push(S : in out Stack_Type;

    Element : in Integer) isbegin

    if S.Top_Index >= Max_Size then-- error handling omitted

    elseS.Top_Index := S.Top_Index + 1;S.List ( Top_Index ) := Element;

    end if;end Push;

    procedure Pop(S : in out Stack_Type) isbegin

    if S.Top_Index = 0then -- error handling omittedelse S.Top_Index := S.Top_Index - 1;end if;

    end Pop;function Top(S : in Stack_Type) return Integer is

    beginif S.Top_Index = 0then -- error handling omittedelse return S.List(S.Top_Index) ;end if;

    end Top;end Stack_Pack;

    We need to declare details of a type Stack_Type in the private part of the specification package becausethe compiler needs to know how much memory is required to allocate a new Stack_Type data while thatinformation should be hidden from users of the package.

    with Stack_Pack;use Stack_Pack;procedure Foo is

    X : Stack_Type; -- allocate memory for a new Stack_TypeY : Integer;begin

    Push(X, 42);Push(X, 17);Y := Top(X);Pop(X);...

    end Foo;

    32

  • 10.4 Object oriented languagesMany people use the term object oriented languages in various different ways. One of the broadest definitionsis the following two conditions:

    There is a unit called object that performs some calculation and stores some data.

    A message is passed from one object to another.

    This definition requires neither class nor dynamic creation of objects.Other (narrower) definitions include more conditions, some of which are:

    Objects are created dynamically.

    Objects are abstract data types.

    Objects can inherit functions of other objects.

    10.5 Designing object oriented languages10.5.1 How pure the language is object oriented?

    It is possible to represent every data as an object and every operation as a message. However, it may beinefficient to implement operations such as 1+2 with objects and messages. In languages such as C++ andJava, primitive parts are not object oriented. On the other hand, in languages such as Smalltalk and Ruby,everything is an object.

    Example: New methods for integers in Ruby

    class Fixnumdef foo

    self + 100end

    end

    1.foo # => 101

    10.5.2 Class-based or prototype-based?

    In many object oritented languages, a class is a description of objects. All the instances of a certain classshare the description.

    In languages such as JavaScript, an object has a set of properties and a prototype object. Some propertiesare shared by objects using the prototype chain.

    10.5.3 What kind of information hiding is possible?

    It is usually a good idea to encapsulate data stored in an object. However, it is sometimes convenient toallow access from outside.

    Example: Controlling Access in Smalltalk

    No Instance variables can be accessed by other objects.

    All methods are accessible from any other object.

    33

  • Example: Controlling Access in C++

    We can choose one of following access modifiers for each variable and method.

    public

    accessible from any class.

    protected

    accessible from subclasses and friends.

    private

    accessible from friends only.

    Example: Controlling Access in Java

    In addition to C++, Package is another unit of information hiding.

    10.5.4 Single inheritance or multiple inheritance?

    Suppose a language has a inheritance mechanism. If there is only one parent class, it is called singleinheritance. If there may be more than one, it is called multiple inheritance.

    Obviously, multiple inheritance is more powerful than single. However, some people think multipleinheritance is hard to use because its semantics is very complicated.

    Example: Inheritance in Java

    Single inheritance for implementation. There is only one superclass whose methods can be used in asubclass.

    Multiple inheritance for specification. There may be many interfaces that specify what kind ofmethods a subclass should have (names of methods, types of parameters and return values).

    10.5.5 How types are checked?

    In most object oriented languages, a class is a type. Since a subclass represents a subset of its superclass,it is natural to define a subclass as a subtype of its superclass (i.e. the subclass type can be substituted forthe superclass type).

    Example: Type checking in Java

    34

  • class Parent {}

    class Child extends Parent {}

    void some_method {Parent x;Child y;

    x = y; //OKy = x; //NG

    }

    Exercise 17In object oriented languages with static type checking such as Java, we can add new methods or override

    parents methods in a subclass, but we cannot delete parents methods. Guess the reason.

    11 Concurrent Programming

    11.1 Concurrent and parallelSequential

    Execution progresses in a predefined order, one step at a time.

    Concurrent

    The execution order of more than one component is not defined. Also called logically concurrent.

    Parallel

    More than one step is executed by hardware at the same time. Also called physically concurrent.

    Concurrent does not necessarily mean parallel. Single CPU can execute concurrent tasks by switchingtasks.

    Preemptive

    A task has a chance to be switched at any time. Switching usually occurs on timer interrupts or I/Oevents.

    Non-preemptive

    A task will not be switched against its will. See 9.4.

    11.2 SynchronizationThread

    An abstract flow of control. Or, a unit of execution that holds its context (CPU registers, contents ofstack, etc.). It is sometimes called a process, a task, or a job, but be careful that these words may beused for different concepts depending on situations.

    Synchronization

    To put a constraint on execution of threads at a certain point of a program.

    Cooperation synchronization

    When we simply say synchronization, it usually means cooperation synchronization. It includes severalcases: for example, a fast thread waits for another slow thread, a thread sends data to another thread,etc.

    35

  • Competetion synchronization

    It is also called mutual exclusion. When a certain resource cannot be accessed by more than one threadat the same time, a constraint should be put so that only one thread access it at a time.

    Critical section

    A part of program that needs mutual exclusion.

    Example: Competition

    Suppose the initial value of a variable x is 1. Both threads A and B will increment x by 1.

    1. A reads 1 (the value of x).

    2. B reads 1 (the value of x).

    3. A computes 1+1 (result of increment)

    4. B computes 1+1 (result of increment)

    5. A writes 2 to x

    6. B writes 2 to x

    11.3 Deadlock and starvationIf a thread locks a shared resource, other threads cannot access it until the thread unlocks it.

    Deadlock

    All threads are waiting for some shared resources to be unlocked. No threads can proceed.

    Starvation

    A certain thread cannot access a shared resource forever while others can do.

    Example: Dining philosophers problem

    See Wikipedia24There is a chance that deadlock occurs.

    loopPick up the left folk.Pick up the right folk.Eat for a while.Put the both folks down.Think for a while.

    end

    Now, philosphers get smarter. Still, there is a chance that starvation occurs.

    24http://en.wikipedia.org/wiki/Dining_philosophers_problem

    36

    http://en.wikipedia.org/wiki/Dining_philosophers_problem

  • loopPick up the left folk.if (the right folk is not available)then

    Put the left folk down.else

    Pick up the right folk.Eat for a while.Put the both folks down.Think for a while.

    endend

    Exercise 18If philosophers sit in a row, instead of a circle, deadlock will not occur. Explain why.

    11.4 SemaphoreA semaphore is an abstract data type used for managing synchronization. It consists of a counter and athread queue.

    P operation

    If the counter is greater than 0, decrement it by 1. Otherwise, suspend the current thread, and put itinto the queue.

    V operation

    If the thread queue is empty, increment the counter by 1. Otherwise, pick a thread from the queue,and let it continue.

    Using semaphores is error-prone. Mistakes easily cause deadlock.

    Example: Producers-consumers problem (without mutual exclusion)

    See Wikipedia25In Ada, wait and release conrrespond to P operation and V operation respectively.

    semaphore fullspots, -- Number of filled spots in the bufferemptyspots; -- Number of empty spots in the buffer

    fullspots.count := 0; -- Initially no spots are filledemptyspots.count := BUFLEN; -- Initially all spots are empty

    task producer;loop-- Produce a datawait(emptyspots); -- Wait if no spot is empty-- Put the data into the bufferrelease(fullspots); -- Increment the number of filled spotsend loop

    end producer;

    task consumer;loop

    25http://en.wikipedia.org/wiki/Producers-consumers_problem

    37

    http://en.wikipedia.org/wiki/Producers-consumers_problem

  • wait(fullspots); -- Wait if no spot if filled-- Get a data from the bufferrelease(emptyspots); -- Increment the number of empty spots-- Consume the dataend loop

    end consumer;

    Example: Producer-consumer problem (with mutual exclusion)

    Accessing the shared buffer should be a critical section. A semaphore access is used to lock the buffer.

    semaphore access; -- 0: unlocked, 1: lockedaccess.count := 1; -- Initially the buffer is unlockedsemaphore fullspots, emptyspots;fullspots.count := 0;emptyspots.count := BUFLEN;

    task producer;loop-- Produce a datawait(emptyspots);wait(access); -- Lock the buffer-- Put the data into the bufferrelease(access); -- Unlock the bufferrelease(fullspots);end loop

    end producer;

    task consumer;loopwait(fullspots);wait(access); -- Lock the buffer-- Get a data from the bufferrelease(access); -- Unlock the bufferrelease(emptyspots);-- Consume the dataend loop

    end consumer;

    11.5 MonitorA monitor is a syntactical structure of mutual exclusion.

    Inside a monitor, only one thread can be executed at a time. This enforces mutual exclusion.

    A thread can sleep in a monitor, which enables another thread to enter the monitor.

    A thread can wake up another thread sleeping in a monitor.

    It is less likely to make a mistake about mutual exclusion, compared to semaphore. Still, it is difficult towrite cooperation synchronizations.

    Example: Producer-comsumer problem in Concurrent Pascal

    38

  • type databuf =monitor

    const bufsize = 100;var buf : array [1..bufsize] of integer;

    next_in, next_out : 1..bufsize;filled : 0..bufsize;sender_q, receiver_q : queue;

    procedure entry deposit(item : integer);beginif filled = bufsize

    then delay(sender_q);buf[next_in] := item;next_in := (next_in mod bufsize) + 1;filled := filled + 1;continue(receiver_q)end ;

    procedure entry fetch(var item : integer) ;beginif filled = 0

    then delay(receiver_q);item := buf[next_out];next_out := (next_out mod bufsize) + 1;filled := filled - 1;continue(sender_q)end;

    beginfilled := 0;next_in := 1;next_out := 1end;

    type producer = process(buffer: databuf);var newvalue : integer;begincycle

    { produce newvalue }buffer.deposit(newvalue);

    endend;

    type consumer = process(buffer: databuf);var stored_value : integer;begincycle

    buffer.fetch(stored_value);{ consume stored_value }

    endend;

    var new_producer : producer;new_consumer : consumer;

    39

  • new_buffer : databuf;

    begininit new_buffer,

    new_producer(new_buffer),new_consumer(new_buffer);

    end;

    Exercise 19Which features in Java correspond to the following concepts?

    monitor

    sleeping in a monitor

    waking up another thread

    11.6 ChannelSince it is error-prone to use shared memory with mutual exclusion, there is an idea that communicationshould be used for synchronization. It is theoretically based on process algebras.

    11.6.1 Occam

    Occam was developed for Transputer, a microprocessor architecture for parallel computing of the 1980s.Concepts of Occam are taken from the communicating sequential processes (CSP) which is one of process

    algebras. Its program is a collection of processes communicating with each other through channels. A channelis a one-to-one, uni-directional, and synchronous (i.e. sending and receiving must take place simultaneously)communication devise.

    See An Introduction to the occam Language26 for detail.

    11.6.2 Go

    Go was first announced by Google in 2009, and Version 1 was released in March 2012.A goroutine is a function executing concurrently with others. Two goroutines can communicate via a

    channel. A channel may be buffered (asynchronous) or unbuffered (synchronous).See The Go Programming Language27 for detail.

    12 Functional Programming

    12.1 Concept of the functional programming languages12.1.1 reduction

    Functional programming is a paradigm where computation is done by reduction via function application.To understand the notion of reduction, consider a simple question 1+2=?. We may answer 41 or

    square root of 9 mathematically, but the expected answer is 3. Reduction is, intuitively speaking, aprocedure to convert an expression into a simpler equivalent expression.

    A program in functional programming languages consists of function definitions and an expression whosevalue is the result of the program. Reduction starts from the expression using function definitions, and thebody of function definitions will be reduced using other function definitions repeatedly, until it reaches thesimplest form (usually a single value).

    26http://frmb.org/occtutor.html27http://golang.org

    40

    http://frmb.org/occtutor.htmlhttp://golang.org

  • 12.1.2 referential transparency

    One of the most essential property of functional programming languages is the following:

    Referential transparencythe value of an expression solely depends on its subexpressions (i.e. literaly same expressions alwaysresult in the same value).

    Referential transparency guarantees that there is no need to take states into consideration.In contrast, values of expressions vary in the course of execution in imperative (procedural) languages

    because values of variables can be changed by assignmentsVariable names are directly bound to values in functional languages (cf. 3.3.1). Once it is bound, it will

    never change. However, the same name may be bound to another value in another environment.You may think switching environments is practically same as assigning values. However, environments

    are usually associated with syntactic structures and switched in a nesting manner, while assignments arenon-structured and destructive operations.

    12.2 LispLisp is a multi-paradigm language. It has functional features as well as imperative features such as assign-ments and iterations. A subset of Lisp that has only functional features is sometimes used for educationalor research purpose.

    Extremely simple syntax (S-expression).

    List is the main data structure.

    No type declaration.

    Functions are first-class objects.

    Suitable for reflection because both programs and data are represented by lists.

    Example: Higher order function

    (mapcar (lambda (b) (* b b)) (1 2 3 4))

    12.3 Haskell12.3.1 Static type checking and type inference

    See 5.5.Type system is not directly related to functional paradigm, but many functional languages have powerful

    type systems. The reason is that we can find many bugs by investigating types because higher-order functionshave complex types which bring rich information.

    12.3.2 Lazy evaluation

    See 7.4.Lazy evaluation is also not directly related to functional paradigm. It is difficult for imperative languages

    to use lazy evaluation since we cannot tell when side-effects occur.

    Example: Infinite list

    Suppose we want to check if a certain integer is equal to the square of another integer. First, we definean infinite list squares as follows:

    41

  • squares = [ n * n | n 0, a fact if n=0.

    Example: Syllogism

    28http://en.wikibooks.org/wiki/Haskell/Understanding_monads

    42

    http://en.wikibooks.org/wiki/Haskell/Understanding_monads

  • human(socrates).human(plato).mortal(X) :- human(X).

    Example: Appending lists

    append([], Y, Y).append([H | X], Y, [H | Z]) :- append(X, Y, Z).

    13.2.2 Query

    Action of Prolog interpreter is as follows:

    1. Input a query.

    2. Determine whether the query is provable from the program.

    3. If there is no variable in the query, output yes or no.

    4. If there are variables in the query, output values of variables that conform one of provable instances.

    Example: Syllogism

    ?- mortal(socrates).yes

    ?- mortal(X).X = socratesX = plato

    Example: Appending lists

    Is it true that appending [a,b] and [c,d] results in [a,b,c,d] ?

    ?- append([a, b], [c, d], [a, b, c, d]).yes

    What is the result of appending [a,b] and [c,d] ?

    ?- append([a, b], [c, d], Z).Z = [a, b, c, d]

    Appending [a,b] and what results in [a,b,c,d] ?

    ?- append([a, b], Y, [a, b, c, d]).Y = [c, d]

    Appending what and [c,d] results in [a,b,c,d] ?

    ?- append(X, [c, d], [a, b, c, d]).X = [a, b]

    43

  • 13.2.3 Program execution

    Prolog interpreter searches a proof of the given query using unification and resolution.

    1. Make a negation Q (called a goal clause) of the given query Q .

    2. Try to find a contradiction between Q and the program P .

    3. If a contradiction is found between Q, an instance of Q, and P, Q is provable by contradiction.

    13.3 Problems of Prolog13.3.1 Order of resolution

    In order to do declarative programming, the interpreter should non-deterministically select literals used inresolutions. However, most of existing Prolog interpreters select literals in deterministic order (from top tobottom, left to right). This is because 1) to make interpreters simpler, and 2) to write efficient programsthat take advantage of this order. In exchange, programs may fall into infinite loops depending on the orderof literals.

    Example: Infinite loop

    Provided that a relation parent is defined, we want to define a transitive relation ancestor.The following program will fall into an infinite loop.

    ancestor(X, X).ancestor(X, Y) :- ancestor(Z, Y), parent(X, Z).

    The following will not.

    ancestor(X, X).ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y).

    13.3.2 Negation

    If a query Q is not provable, it does not necessarily mean Q is false. However, most of Prolog interpreterassumes Q is true (Q is false) if it cannot find a proof of Q. This rule is called negation as failure (cf.Wikipedia29). It is different from logical negation.

    29https://en.wikipedia.org/wiki/Negation_as_failure

    44

    https://en.wikipedia.org/wiki/Negation_as_failure

    IntroductionAbout this courseEvaluation

    QuestionsDefinition of a languageDifferences among languagesCharacterGrammarParadigm

    Definition of ``good'' programming languageHistory of programming languagesReasons to study the theory of programming language

    Syntax and SemanticsBrief introduction to the formal language theoryDefinition of formal languagesBNF notationParse treeAmbiguous grammar

    Glance at the semantics theoryOperational semanticsAxiomatic semanticsDenotational semantics

    Names and BindingsNames in a programNamespaceBindingsDefinition of bindingsAnonymous and alias

    ScopeStatic scopingDynamic scopingClosure

    Bindings of functions

    VariablesWhat is a variable?TypeLeft valueMemory managementStatic data areaStackHeap

    Extent

    TypesWhat is a type?Why use types?Type systems

    Various typesEnumerated typeSubrange typeUnion typePointer typeFunction type

    Type conversionImplicit conversionExplicit conversion

    Type checkingType declarationType compatibility

    Type inferencePolymorphism

    Mid-term paperExpressionsPrecedence and associativity of operatorsOrder of evaluationShort-circuit evaluationLazy evaluation

    Control structuresStructured programmingNon-local exitsExceptionsWhat is exception?Exception handling

    SubprogramsWhat is a subprogram?ParametersPassing parametersDirection of passingEvaluation strategy of parameters

    Coroutine

    Object Oriented ProgrammingAbstraction and ModularizationAbstract data typePackage in AdaObject oriented languagesDesigning object oriented languagesHow pure the language is object oriented?Class-based or prototype-based?What kind of information hiding is possible?Single inheritance or multiple inheritance?How types are checked?

    Concurrent ProgrammingConcurrent and parallelSynchronizationDeadlock and starvationSemaphoreMonitorChannelOccamGo

    Functional ProgrammingConcept of the functional programming languagesreductionreferential transparency

    LispHaskellStatic type checking and type inferenceLazy evaluationMonad

    Logic ProgrammingFeatures of logic programmingPrologDefinition of programsQueryProgram execution

    Problems of PrologOrder of resolutionNegation