CS655 Class Notes: A Historical Overview of Programming Languages - Prof. Raphael A. Finke, Study notes of Programming Languages

An overview of the historical development of programming languages, from fortran to ml, with a focus on their features and evolution. Topics include constructs, imperative languages, block structure, parameter passing modes, iterators, and ml's type system.

Typology: Study notes

Pre 2010

Uploaded on 10/01/2009

koofers-user-76j
koofers-user-76j 🇺🇸

9 documents

1 / 13

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
CS655 class notes
Raphael Finkel
October 1, 2009
1 Intro
Lecture 1, 8/27/2009
Handout 1 My names
Mr. / Dr. / Professor /
Raphael / Rafi / Refoyl
Finkel / Goldstein
Plagiarism read aloud from handout 1
Assignments on web and in handout 1.
E-mail list: [email protected]; instructor uses to reach students.
All students will have MultiLab accounts, although you may use any
computer you like to do assignments.
textbook all homework comes from here
First assignment (Chapter 1, due Thursday)
2 Software tools
A programming language is an example of a software tool.
Implementation
Use (client)
Spec
Usable?
Compilable?
Elegant?
1
pf3
pf4
pf5
pf8
pf9
pfa
pfd

Partial preview of the text

Download CS655 Class Notes: A Historical Overview of Programming Languages - Prof. Raphael A. Finke and more Study notes Programming Languages in PDF only on Docsity!

CS655 class notes

Raphael Finkel

October 1, 2009

1 Intro

Lecture 1, 8/27/

  • Handout 1 — My names
    • Mr. / Dr. / Professor / —
    • Raphael / Rafi / Refoyl
    • Finkel / Goldstein
  • Plagiarism — read aloud from handout 1
  • Assignments on web and in handout 1.
  • E-mail list: [email protected]; instructor uses to reach students.
  • All students will have MultiLab accounts, although you may use any computer you like to do assignments.
  • textbook — all homework comes from here
  • First assignment (Chapter 1, due Thursday)

2 Software tools

A programming language is an example of a software tool.

Implementation

Use (client) Spec

Usable?

Compilable?

Elegant?

3 McLennan’s Principles (elicit first)

4 Algol-like languages: review

  • First generation: Fortran
    • constructs based on hardware
    • lexical: linear list of statements
    • control: sequence, goto , do , subroutines using reference pa- rameter mode
    • data: arithmetic, including complex; arrays with a 3-d limit
    • name: separate scopes; common area
  • Second generation: Algol 60
    • lexical: free format; keywords
    • control: nested; if , while , for , but baroque; subroutines with value and name parameter modes.
    • data: generalized arrays, but no complex
    • name: nested scopes with inheritance and local override
  • Third generation: Pascal (return to simplicity)
    • data: user-defined types; records, enumerations, pointers
    • control: subroutines with value and reference parameter modes; case statement
  • Fourth generation: Ada (abstract data types)
    • lexical: bracketed syntax
    • data: modules with controlled export; generic modules
    • control: concurrency with rendezvous
  • Fifth generation: Other directions
    • dataflow
    • functional. We will study ML and Lisp.
    • object-oriented. We will study Smalltalk.
    • declarative (logic). We will study Prolog.

7 Imperative languages

  • Imperative languages involve statements that modify the current state by changing the values of variables.
  • A variable is an identifier bound (usually statically) to a type, having a value that can change over time. The L-value of a variable is the use of a variable on the left side of an assignment (think of “address”); the R-value of a variable is its use on the right side (think of “current value”).
  • A type is a set of values, associated (mostly statically) with opera- tions defined on those values. Type conversion means expressing a value of one type as a value of another type. - coercion: implicit conversion - cast: explicit conversion - non-converting cast: rarely needed. qua operator of Wisconsin Modula, reinterpret cast<> of C++.
  • An operation is a function or an operator symbol as shorthand. It can be heterogeneous. - operators have arity (example: unary, binary), precedence, as- sociativity - operators may be infix (+), prefix (unary - ), postfix (->) - operators may have short-circuit (lazy) semantics
  • An operation is overloaded if its identifier or operator symbol has multiple visible definitions. Overloading is resolved (usually stati- cally) by arity, operand types, and return type. Overloading resolu- tion can be exponentially expensive.
  • A primitive type has no separately accessible components. Exam- ples: integer, character, real, Boolean.
  • A structured type has separately accessible components. Examples: pointer (dereference), record (field select), array (subscript), disjoint union (variant select). An associative array is an array whose index type is string.
  • A constant is like a variable, but it has no L-value and an unchanging R-value.

8 Parameters

  • Nomenclature
    • Formal parameter : the identifier that the procedure uses to re- fer to the parameter; it is elaborated when the procedure is in- voked.
    • Actual parameter : the expression that computes the value of the parameter; it is evaluated in the environment of the caller.
    • Linkage : The machine-oriented mechanism by which the caller A causes control to jump to the called procedure B, including initializing B’s stack frame, passing parameters, passing results back to A, and reclaiming B’s stack frame when it has com- pleted.
  • Parameter-passing modes
    • value mode : The formal has its own L-value, initialized to the R-value of the actual. The language design may restrict the for- mal to read-only use. Value mode is the only mode available in C.
    • result mode : The formal has its own L-value, not initialized. When B returns, the formal’s L-value is copied back to the ac- tual (which must have an L-value, so the actual cannot be an arbitrary expression). Result mode was introduced in Algol-W.
    • value-result mode : The formal has its own L-value, initialized to the R-value of the actual. As B returns, its value is copied back to the actual (which must have an L-value). Value-result mode was introduced in Algol-W.
    • reference mode : The formal has the same L-value as the ac- tual (which must have an L-value, which might be a temporary location). The language may allow the programmer to specify read-only use of the formal parameter. Reference mode is the only mode available in Fortran.
    • name mode : All accesses to the formal parameter re-evaluate the actual (either for L-value or R-value, depending on the ac- cess to the formal). This evaluation is in the RE of the caller, typ- ically by means of a compiled procedure called a thunk. Name mode was invented for Algol-60 and never used again.

def treeNodes(tree): if tree != null: for element in treeNodes(tree.left): yield element yield tree.value for element in treeNodes(tree.right): yield element

  • Wouldn’t it be nice to have a yieldall construct:

def treeNodes(tree): if tree != null: yieldall treeNodes(tree.left): yield tree.value yieldall treeNodes(tree.right):

This construct might be able to use shortcuts to improve efficiency.

10 Macro package to embed iterators in C

  • Macros are IterSTART , IterFOR , IterDONE , IterSUB , IterYIELD.
  • Usage: book 48:
  • Implementation
    • setjump and longjmp for linkage between for and the con- trolling iterator, between yield and its controlled loop.
    • Padding between stack frames to let longjmp() be called with- out harming frames higher on the stack. Three integers is enough in Linux on an i686.
    • A Helper routine to actually call the iterator and act as padding.
    • The top frame must be willing to assist in creating new frames.

11 General coroutines — Simula 67

  • Problem: binary-tree node-equality test in symmetric order
  • Solution
    • Independently advance in each tree book 38:
  • Lecture 4, 9/10/
  • Each coroutine has its own stack; main has its own stack.
  • All the stacks are joined via static-chain pointers into a cactus stack.
  • A scope must not exit until all its children exit, or we must use a reference count. This is an example of the dangling NLRE problem.
  • Syntax (Simula 67)
  • Records have initialization code that may execute detach.
  • Another coroutine may resume it via explicit call.
  • Ole-Johann Dahl, designer of Simula 67, got the Turing award in

12 Power loops

  • How can you get a dynamic amount of for -loop nesting?
  • Application: n queens book 57:
  • Usual solution: single for loop with a recursive call.
  • Cannot use that solution in Fortran, which does not allow recursion.
  • Solution: Power loops. book 57:
  • Implementation: Only needs branches, no recursion. book 59:
  • How general is this facility?
  • Do power loops violate principle 20?

13 IO

  • Attempt to strip a programming language of all non-essential ele- ments.
  • What’s left: goto with parameters, hence formal-actual bindings.
  • Parameters can be integer, anonymous function, or continuation.
  • A function is passed by closure : pointer to code, pointer to NLRE.
  • The property consists of a set of values.
  • Strong typing means the compiler
    • knows the type of every R-value and identifier
    • enforces type compatibility on assignment and formal-actual binding - compatible means type equivalent, a subtype, or convert- ible
  • A subtype consists of a subset of the values
    • Assignment and formal-actual binding require a dynamic check.
    • Subtype examples: range of integers, subclass of class
    • subTypeVar := baseTypeVar
  • Type equivalence
    • structural equivalence : expand type to a canonical string rep- resentation; equivalence is string equality. - lax: ignore field names, ignore array bounds, ignore index type, flatten records. - pointers require that we handle recursive types (and still build finite strings)
    • name equivalence : reduce a type to an instance of a type con- structor - type constructors : array , pointerTo , enum , struct , derived. - lax ( declaration equivalence ): multiple uses of one type constructor are equivalent

17 What does polymorphic mean?

People use the term polymorphic to mean various features.

  • Static procedure overloading with compile-time resolution (Ada, Java). Here, the type of the procedure (its signature ) determines whether it is a viable candidate for resolving the overloading.
  • Dynamic method binding (Java, Smalltalk, C++ deferred binding). Here, the dynamic type (class) of the value (object) determines which procedure (method) to invoke.
  • Types described by type identifiers (perhaps with the compiler infer- ring the types of values) (ML). Here, the dynamic type constraints on the parameter and return value determine the effective type of the function.
  • Passing an ADT as a parameter (Russell).
  • Generic packages (Ada), templates (C++).

18 Unusual first-class values

  • A first-class value can be returned from a function. In languages with variables, a first-class value can be stored in a variable.
  • A second-class value can be an actual parameter.
  • A third-class value can be used “in its ordinary way”.
  • Labels and procedures
    • Usually third class values; the “ordinary way” is in a goto statement or a procedure-call statement.
    • They could be second class. They must be passed as a closure. For a label, the closure includes the RE of its target, so the stack can be unwound to the right place. For a procedure, the closure includes its NLRE to resolve non-local references.
    • To make them first class, we still need to build a closure, which we can then store in a variable. But the lifetime of that variable might exceed the life of the RE stored in the closure. This is the dangling-NLRE problem. book 76:
  • To resolve the dangling-NLRE problem
    • Let it happen and call the program “erroneous”.
    • Prevent it from happening by restricting the language.
      • Don’t let labels or procedures be first-class: Pascal
      • Don’t let scopes nest, so there is no need for closures (for procedures; labels are still problematic): C
      • Only allow top-level procedures (or labels) be first-class: Modula-
    • Let it happen and make it work: allocate all frames from the heap and use explicit release (reference counts suffice).

squares :: [Int] squares = [n*n | n <- [1 .. 5] ] fermat :: [Int] fermat = [(a, b, c, n) | a<-[3..], b<-[3..], c<-[3..], n<-[3..], ((aˆn) + (bˆn) == (cˆn))] quicksort :: [Int] -> [Int] quickSort [] = [] quickSort (a:rest) = quickSort [b | b <- rest, b <= a] ++ [a] ++ quickSort [b | b <- rest, b > a]

  • List comprehensions give us an easy way to implement Lisp’s mapcar function:

mapcar (list, function) = [function a | a <- list]

In fact, we can generally avoid using mapcar entirely.

  • One can combine lazy evaluation, comprehension, and infinite lists to gain memoization (dynamic programming)

cache :: [Int] cache = [fib x | x <- [0 ..]] fib :: Int -> Int fib 0 = 1 fib 1 = 1 fib n = cache!!(n-1) + cache!!(n-2)

  • Haskell has interfaces , much like Java, which are like types that pro- vide certain operations.