Title: CS 363 Comparative Programming Languages
1CS 363 Comparative Programming Languages
2Fundamentals of Subprograms
- General characteristics of subprograms
- 1. A subprogram has a single entry point
- 2. The caller is suspended during execution of
the called subprogram - 3. Control always returns to the caller when the
called subprograms execution terminates
3Fundamentals of Subprograms
- Procedures provide user-defined statements
- Functions provide user-defined operators
4Fundamentals of Subprograms
- Basic definitions
- A subprogram definition is a description of the
actions of the subprogram abstraction - A subprogram call is an explicit request that the
subprogram be executed - A subprogram header is the first line of the
definition, including the name, the kind of
subprogram, and the formal parameters - The parameter profile of a subprogram is the
number, order, and types of its parameters
5Fundamentals of Subprograms
- Basic definitions (continued)
- The protocol of a subprogram is its parameter
profile plus, if it is a function, its return
type - A subprogram declaration provides the protocol,
but not the body, of the subprogram - A formal parameter is a dummy variable listed in
the subprogram header and used in the subprogram - An actual parameter represents a value or address
used in the subprogram call statement
6Design Issues for Subprograms
- 1. What parameter passing methods are provided?
- 2. Are parameter types checked?
- 3. Are local variables static or dynamic?
- 4. Can subprogram definitions appear in other
subprogram definitions?
7Design Issues for Subprograms
- 5. What is the referencing environment of a
passed subprogram? - 6. Can subprograms be overloaded?
- 7. Are subprograms allowed to be generic?
8The General Semantics of Calls and Returns
- Def The subprogram call and return operations of
a language are together called its subprogram
linkage
9Implementing Simple Subprograms
- Call Semantics
- 1. Save the execution status of the caller
- 2. Carry out the parameter-passing process
- 3. Pass the return address to the callee
- 4. Transfer control to the callee
10Implementing Simple Subprograms
- Return Semantics
- Complete the parameter-passing process
- If is a function, move the functional value to a
place the caller can get it - 3. Restore the execution status of the caller
- 4. Transfer control back to the caller
11Implementing Simple Subprograms
- Required Storage Status information of the
caller, parameters, return address, and
functional value (if it is a function) - The format, or layout, of the non-code part of an
executing subprogram is called an activation
record - An activation record instance is a concrete
example of an activation record (the collection
of data for a particular subprogram activation)
12An Activation Record for Simple Subprograms
13Code and Activation Records of a Program with
Simple Subprograms
14Parameter Passing
15Fundamentals of Subprograms
- Actual/Formal Parameter Correspondence
- 1. Positional
- 2. Keyword
- e.g. SORT(LIST gt A, LENGTH gt N)
- Advantage order is irrelevant
- Disadvantage user must know the formal
parameters names - Default Values
- e.g. procedure SORT(LIST LIST_TYPE
- LENGTH INTEGER 100)
- ...
- SORT(LIST gt A)
16Pass-by-value
- in mode
- Typically physical move of data
- Disadvantages
- Requires more storage (duplicated space)
- Cost of the moves (if the parameter is large)
17Pass-by-result
- out mode
- Locals value is passed back to the caller
- Physical move is usually used
- Disadvantages
- If value is passed, time and space
- In both cases, order dependence may be a problem
- e.g.
- procedure sub1(y int, z int)
- ...
- sub1(x, x)
- Value of x in the caller depends on order of
assignments at the return
18Pass-by-value-result
- inout mode
- Physical move, both ways
- Also called pass-by-copy
- Disadvantages
- Those of pass-by-result
- Those of pass-by-value
19Pass-by-reference
- inout mode
- Pass an access path
- Also called pass-by-sharing
- Advantage passing process is efficient (no
copying and no duplicated storage) - Disadvantages
- Slower accesses
- Allows aliasing because of collisions
20Pass-by-Reference collisions
- Actual parameter collision
- procedure sub1(a int, b int)
- ...
- sub1(x, x)
- Array element collisions
- sub1(ai, aj) / if i j /
- sub2(a, ai)
- Collision between formals and globals
- Root cause of all of these is The called
subprogram is provided wider access to nonlocals
than is necessary - Pass-by-value-result does not allow these aliases
(but has other problems!)
21Pass-by-name thunks
- By textual substitution
- Formals are bound to an access method at the time
of the call, but actual binding to a value or
address takes place at the time of a reference or
assignment - Purpose flexibility of late binding
- Resulting semantics
- If actual is a scalar variable, it is
pass-by-reference - If actual is a constant expression, it is
pass-by-value - If actual is an array element, it is like nothing
else
22Pass-by-name
- procedure sub1(x int y int)
- begin
- x 1
- y 2
- x 2
- y 3
- end
- sub1(i, ai)
- procedure sub1
- begin
- i 1
- ai 2
- i 2
- ai 3
- end
23Language Examples
- 1. FORTRAN
- Before 77, pass-by-reference
- 77 - scalar variables are often passed by
value-result - 2. ALGOL 60
- Pass-by-name is default pass-by-value is optional
24Language Examples
- 3. ALGOL W
- Pass-by-value-result
- 4. C
- Pass-by-value
- 5. Pascal and Modula-2
- Default is pass-by-value pass-by-reference is
optional - 6. C
- Like C, but also allows reference type
parameters, which provide the efficiency of
pass-by-reference with in-mode semantics
25Language Examples
- 7. Ada
- All three semantic modes are available with
checking - If out, it cannot be referenced
- If in, it cannot be assigned
- 8. Java
- Like C, except only references
26Type checking Parameters
- Type checking parameters (now considered very
important for reliability) - FORTRAN 77 and original C none
- Pascal, FORTRAN 90, Java, and Ada it is always
required - ANSI C and C choice is made by the user
27Implementing Parameter Passing Methods
- ALGOL 60 and most of its descendants use the
run-time stack - Value - copy it to the stack references are
indirect to the stack - Result - same
- Reference - regardless of form, put the address
in the stack - Name - run-time resident code segments or
subprograms evaluate the address of the
parameter called for each reference to the
formal - Very expensive, compared to reference or
value-result
28Multidimensional Arrays as Parameters
- If a multidimensional array is passed to a
subprogram and the subprogram is separately
compiled, the compiler needs to know the declared
size of that array to build the mapping function
(i.e. address computation for individual elements)
29Multidimensional Arrays as Parameters
- C and C
- Programmer is required to include the declared
sizes of all but the first subscript in the
actual parameter - This disallows writing flexible subprograms
- Solution pass a pointer to the array and the
sizes of the dimensions as other parameters the
user must include the storage mapping function,
which is in terms of the size parameters
30Multidimensional Arrays as Parameters
- Pascal
- Not a problem (declared size is part of the
arrays type) - Ada
- Constrained arrays - like Pascal
- Unconstrained arrays - declared size is part of
the object declaration (Java is similar)
31Subprograms as Parameters
- Issues
- 1. Are parameter types checked?
- Early Pascal and FORTRAN 77 do not
- Later versions of Pascal and FORTRAN 90 do
- Ada does not allow subprogram parameters
- Java does not allow method names to be passed
- as parameters
- C and C - pass pointers to functions
parameters can be type checked
32Subprogram as Parameters
- 2. What is the correct referencing environment
for a subprogram that was sent as a parameter? - a. That of the subprogram that enacted it
- Shallow binding
- b. That of the subprogram that declared it
- Deep binding
33Passing Subprograms as Parameters
- Example sub1
- sub2
- sub3
- call sub4(sub2)
- sub4(subx)
- call subx
-
- call sub3
- Shallow binding gt sub2, sub4, sub3, sub1
- Deep binding gt sub2, sub1
What is the referencing environment of sub2
when it is called in sub4?
34Parameters that are Subprogram Names
- For static-scoped languages, deep binding is most
natural - For dynamic-scoped languages, shallow binding is
most natural
35Overloaded Subprograms
- Def An overloaded subprogram is one that has the
same name as another subprogram in the same
referencing environment - C and Ada have overloaded subprograms built-in,
and users can write their own overloaded
subprograms
36Subprograms as User-Defined Overloaded Operators
- Example (Ada) (assume VECTOR_TYPE has been
defined to be an array type with INTEGER
elements) - function ""(A, B in VECTOR_TYPE)
- return INTEGER is
- SUM INTEGER 0
- begin
- for INDEX in A'range loop
- SUM SUM A(INDEX) B(INDEX)
- end loop
- return SUM
- end ""
- Are user-defined overloaded operators good or
bad?
37Design Issues for Functions
- 1. Are side effects allowed?
- a. Two-way parameters (Ada does not allow)
- b. Nonlocal reference (all allow)
- 2. What types of return values are allowed?
38Allowable return types
- Language Examples
- 1. FORTRAN, Pascal - only simple types
- 2. C - any type except functions and arrays
- 3. Ada - any type (but subprograms are not types)
- 4. C and Java - like C, but also allow classes
to be returned
39Implementing Return Types
- Typically done on runtime stack or special
register. - Call procedure places value in known place
- Caller retrieves value from this place
40Local Vars Static vs. Dynamic
- Dynamic
- new instance created (and initialized) each time
the call is made - Advantages
- a. Support for recursion
- b. Storage for locals is shared among some
subprograms
- Static
- Single copy holds its value between calls
- Advantages
- a. Saves allocation and deallocation time
- b. Simplifies addressing
- c. Subprograms can be history sensitive
41Local referencing environments
- Language Examples
- 1. FORTRAN 77 and 90 - most are static, but the
implementer can choose either (User can force
static with SAVE) - 2. C - both (variables declared to be static are)
(default is stack dynamic) - 3. Pascal, Java, and Ada - dynamic only
42Accessing Nonlocal Environments
- Def The nonlocal variables of a subprogram are
those that are visible but not declared in the
subprogram - Def Global variables are those that may be
visible in all of the subprograms of a program
43Accessing Nonlocal Environments
- Methods
- 1. FORTRAN COMMON blocks
- The only way in pre-90 FORTRAN to access nonlocal
variables - Can be used to share data or share storage
- 2. Static scoping
44Accessing Nonlocal Environments
- Methods (continued)
- 3. External declarations - C
- Subprograms are not nested
- Globals are created by external declarations
(they are simply defined outside any function) - Access is by either implicit or explicit
declaration - Declarations (not definitions) give types to
externally defined variables (and say they are
defined elsewhere)
45Accessing Nonlocal Environments
- Methods (continued)
- 4. External modules - Ada
- More about these later (Chapter 11)
- 5. Dynamic Scope
46Implementing Subprograms with Stack-Dynamic Local
Variables
- More complicated because
- The compiler must generate code to cause implicit
allocation and deallocation of local variables - Recursion must be supported (adds the possibility
of multiple simultaneous activations of a
subprogram)
47Typical Activation Record for a Language with
Stack-Dynamic Local Variables
48Implementing Subprograms with Stack-Dynamic Local
Variables
- The activation record format is static, but its
size may be dynamic - The dynamic link points to the top of an instance
of the activation record of the caller - An activation record instance is dynamically
created when a subprogram is called
49An Example C Function
- void sub(float total, int part)
-
- int list4
- float sum
-
4 3 2 1 0
50An Example C Program Without Recursion
- void C(int q)
- ...
-
- void main()
- float p
- ...
- B(p)
- ...
-
- void A(int x)
- int y
- ...
- C(y)
- ...
-
- void B(float r)
- int s, t
- ...
- A(s)
- ...
51Stack Contents For Program
- Note that main calls B
- B calls A
- A calls C
52Implementing Subprograms in ALGOL-like Languages
- The collection of dynamic links in the stack at a
given time is called the call chain - Local variables can be accessed by their offset
from the beginning of the activation record. This
offset is called the local_offset - The local_offset of a local variable can be
determined by the compiler - Assuming all stack positions are the same size,
the first local variable declared has an offset
of three plus the number of parameters, e.g., in
main, the local_offset of Y in A is 3
53Recursion
- The activation record used in the previous
example supports recursion, e.g. -
- int factorial(int n)
- lt-----------------------------1
- if (n lt 1)
- return 1
- else return (n factorial(n - 1))
- lt-----------------------------2
-
- void main()
- int value
- value factorial(3)
- lt-----------------------------3
-
54Activation Record for factorial
55Nested Subprograms
- Some non-C-based static-scoped languages (e.g.,
Fortran 95, Ada, JavaScript) use stack-dynamic
local variables and allow subprograms to be
nested - Observation All variables that can be nonlocally
accessed reside in some activation record
instance in the stack - The process of locating a nonlocal reference
- 1. Find the correct activation record instance
- 2. Determine the correct offset within that
activation record instance
56The Process of Locating a Nonlocal Reference
- Finding the offset is easy
- Finding the correct activation record instance
- Static semantic rules guarantee that all nonlocal
variables that can be referenced have been
allocated in some activation record instance that
is on the stack when the reference is made
57Static Chains
- A static chain is a chain of static links that
connects certain activation record instances - The static link in an activation record instance
for subprogram A points to the closest activation
record instance of A's static parent - The static chain from an activation record
instance connects it to all of its static
ancestors
58Static Chains (continued)
- To find the declaration for a reference to a
nonlocal variable - You could chase the static chain until the
activation record instance (ari) that has the
variable is found, searching each ari as it is
found, if variable names were stored in the ari - Def static_depth is an integer associated with a
static scope whose value is the depth of nesting
of that scope
59Static Chains (continued)
- main ----- static_depth 0
- A ----- static_depth 1
- B ----- static_depth 2
-
-
-
-
- C ----- static_depth 1
60Static Chains (continued)
- Def The chain_offset or nesting_depth of a
nonlocal reference is the difference between the
static_depth of the reference and that of the
scope where it is declared - A reference can be represented by the pair
- (chain_offset, local_offset)
- where local_offset is the offset in the
activation record of the variable being referenced
61Example Pascal Program
- program MAIN_2
- var X integer
- procedure BIGSUB
- var A, B, C integer
- procedure SUB1
- var A, D integer
- begin SUB1
- A B C lt-----------------------1
- end SUB1
- procedure SUB2(X integer)
- var B, E integer
- procedure SUB3
- var C, E integer
- begin SUB3
- SUB1
- E B A lt--------------------2
- end SUB3
- begin SUB2
- SUB3
62Example Pascal Program
- program MAIN_2
- var X integer
- procedure BIGSUB
- var A, B, C integer
- procedure SUB1
- var A, D integer
- begin SUB1
- A B C lt-----------------------1
- end SUB1
- procedure SUB2(X integer)
- var B, E integer
- procedure SUB3
- var C, E integer
- begin SUB3
- SUB1
- E B A
- end SUB3
- begin SUB2
- SUB3
MAIN_2 calls BIGSUB BIGSUB calls SUB2(7) SUB2
calls SUB3 SUB3 calls SUB1
A - (0, 3) B - (1, 4) C - (1, 5)
63Stack Contents at Position 1
MAIN_2 calls BIGSUB BIGSUB calls SUB2(7) SUB2
calls SUB3 SUB3 calls SUB1
In SUB1 A - (0, 3) B - (1, 4) C - (1,
5)
64Example Pascal Program
- program MAIN_2
- var X integer
- procedure BIGSUB
- var A, B, C integer
- procedure SUB1
- var A, D integer
- begin SUB1
- A B C
- end SUB1
- procedure SUB2(X integer)
- var B, E integer
- procedure SUB3
- var C, E integer
- begin SUB3
- SUB1
- E B A lt--------------------2
- end SUB3
- begin SUB2
- SUB3
in SUB3 E - (0, 4) B - (1, 4) A - (2,
3)
65Example Pascal Program
- program MAIN_2
- var X integer
- procedure BIGSUB
- var A, B, C integer
- procedure SUB1
- var A, D integer
- begin SUB1
- A B C
- end SUB1
- procedure SUB2(X integer)
- var B, E integer
- procedure SUB3
- var C, E integer
- begin SUB3
- SUB1
- E B A
- end SUB3
- begin SUB2
- SUB3
In SUB2 A - (1, 3) D - an error E -
(0, 5)
66Static Chain Maintenance
- How to set the static link?
- Let Psd be the static_depth of P, and Qsd be the
static_depth of Q - Assume Q calls P
- There are three possible cases
- 1. Qsd Psd
- 2. Qsd lt Psd
- 3. Qsd gt Psd
67Static Chain Maintenance
- Qsd Psd - They are at same static depth
- Ps static link should be the same as Qs Q
copies its link
Ps ari
Qs ari
68Static Chain Maintenance
- Qsd lt Psd - P must be enclosed directly in Q
- Ps static link should point at Q
Ps ari
Qs ari
69Static Chain Maintenance
- Qsd gt Psd - Q is n levels down in the nesting
must follow Qs static chain n levels and copy
that pointer
S
P R Q
Ps ari
Suppose n is 2
Qs ari
Rs ari
Ps ari
Ss ari
70Nested Subprograms
- Evaluation of the Static Chain Method
- Problems
- 1. A nonlocal reference is slow if the number of
scopes between the reference and the declaration
of the referenced variable is large - 2. Time-critical code is difficult, because the
costs of nonlocal references are not equal, and
can change with code upgrades and fixes
71Alternative Displays
- The idea Put the static links in a separate
stack called a display. The entries in the
display are pointers to the activation records'
that have the variables in the referencing
environment. - Represent references as
- (display_offset, local_offset)
- where display_offset is the same as chain_offset
72Displays (continued)
- Mechanics of references
- Use the display_offset to get the pointer into
the display to the activation record with the
variable - Use the local_offset to get to the variable
within the activation record
73Displays (continued)
- Display maintenance (assuming no parameters that
are subprograms and no pass-by-name parameters) - Note that display_offset depends only on the
static depth of the procedure whose activation
record is being built. It is exactly the
static_depth of the procedure. - There are k1 entries in the display, where k is
the static depth of the currently executing unit
(k0 is for the main program)
74Displays (continued)
- For a call to procedure P with a static_depth of
k - a. Save, in the new ari, a copy of the display
pointer at position k - b. Put the link to the ari for P at position k in
the display - At an exit, move the saved display pointer from
the ari back into the display at position k
75Example Pascal Program
- program MAIN_2
- var X integer
- procedure BIGSUB
- var A, B, C integer
- procedure SUB1
- var A, D integer
- begin SUB1
- A B C
- end SUB1
- procedure SUB2(X integer)
- var B, E integer
- procedure SUB3
- var C, E integer
- begin SUB3
- SUB1
- E B A
- end SUB3
- begin SUB2
- SUB3
76Stack Contents at Position 1
MAIN_2 calls BIGSUB BIGSUB calls SUB2(7) SUB2
calls SUB3 SUB3 calls SUB1
In SUB1 A - (0, 3) B - (1, 4) C - (1,
5)
77Static Chain Maintenance
- Qsd Psd - They are at same static depth
- No update needed since both have same enclosing
scope
78Static Chain Maintenance
- Qsd lt Psd - P must be enclosed directly in Q
- Save displayPsd in Qs ari (in case we care
about the value later). Update displayPsd to
point at P. When call returns, update display.
Ps ari
Psd
Becomes
Qs ari
Qs ari
Qsd
Qsd
79Static Chain Maintenance
- Qsd gt Psd - Q is n levels down in the nesting
must follow Qs static chain n levels and copy
that pointer
S
P R Q
Ps ari
Suppose n is 2
Qs ari
Rs ari
Ps ari
Ss ari
80Static Chain Maintenance
- Qsd gt Psd - Q is n levels down in the nesting
must follow Qs static chain n levels and copy
that pointer. When call returns, update display.
Ps ari
Becomes
Qs ari
Qs ari
Rs ari
Rs ari
Ps ari
Ps ari
Ss ari
Ss ari
81Nested Subprograms
- The display can be kept in registers, if there
are enough--it speeds up access and maintenance - Comparing the Static Chain and Display Methods
- 1. References to locals
- Not much difference
- 2. References to nonlocals
- If it is one level away, they are equal
- If it is farther away, the display is faster
- Display is better for time-critical code, because
all nonlocal references cost the same
82Nested Subprograms
- 3. Procedure calls
- For one or two levels of depth, static chain is
faster - Otherwise, the display is faster
- 4. Procedure returns
- Both have fixed time, but the static chain is
slightly faster - Overall Static chain is better, unless the
display can be kept in registers
83Blocks
- Two Methods
- 1. Treat blocks as parameterless subprograms
- Use activation records
- 2. Allocate locals on top of the ari of the
subprogram - Must use a different method to access locals
- A little more work for the compiler writer
84Coroutines
- A coroutine is a subprogram that has multiple
entries and controls them itself - Also called symmetric control
- A coroutine call is named a resume
- The first resume of a coroutine is to its
beginning, but subsequent calls enter at the
point just after the last executed statement in
the coroutine
85Coroutines
- Typically, coroutines repeatedly resume each
other, possibly forever - Coroutines provide quasi-concurrent execution of
program units (the coroutines) - Their execution is interleaved, but not overlapped
86Coroutines
87Generic Subprograms
- A generic or polymorphic subprogram is one that
takes parameters of different types on different
activations - Overloaded subprograms provide ad hoc
polymorphism - A subprogram that takes a generic parameter that
describes the type of the parameters of the
subprogram provides parametric polymorphism
88Generic Subprograms
- Examples of parametric polymorphism
- 1. Ada
- Types, subscript ranges, constant values, etc.,
can be generic in Ada subprograms and packages,
e.g. - generic
- type ELEMENT is private
- type VECTOR is array (INTEGER range ltgt)
- of ELEMENT
- procedure GENERIC_SORT(LIST in out
- VECTOR)
89- procedure GENERIC_SORT(LIST in out VECTOR)
- is
- TEMP ELEMENT
- begin
- for INDEX_1 in LIST'FIRST ..
- INDEX_1'PRED(LIST'LAST) loop
- for INDEX_2 in INDEX'SUCC(INDEX_1) ..
- LIST'LAST loop
- if LIST(INDEX_1) gt LIST(INDEX_2) then
- TEMP LIST (INDEX_1)
- LIST(INDEX_1) LIST(INDEX_2)
- LIST(INDEX_2) TEMP
- end if
- end loop -- for INDEX_1 ...
- end loop -- for INDEX_2 ...
- end GENERIC_SORT
90Generic Subprograms
- procedure INTEGER_SORT is new GENERIC_SORT(
- ELEMENT gt INTEGER
- VECTOR gt INT_ARRAY)
91Generic Subprograms
- Ada generics are used to provide the
functionality of subprogram parameters generic
part is a subprogram - Example
- generic
- with function FUN(X FLOAT) return FLOAT
- procedure INTEGRATE(LOWERBD in FLOAT
- UPPERBD in FLOAT
- RESULT out FLOAT)
92Generic Subprograms
- procedure INTEGRATE(LOWERBD in FLOAT
- UPPERBD in FLOAT
- RESULT out FLOAT) is
- FUNVAL FLOAT
- begin
- ...
- FUNVAL FUN(LOWERBD)
- ...
- end
- INTEGRATE_FUN1 is new INTEGRATE(FUN gt FUN1)
93Generic Subprograms
- C
- Templated functions
- e.g.
- template ltclass Typegt
- Type max(Type first, Type second)
- return first gt second ? first second
-
94Generic Subprograms
- C template functions are instantiated
implicitly when the function is named in a call
or when its address is taken with the operator - Another example
- template ltclass Typegt
- void generic_sort(Type list, int len)
- int top, bottom
- Type temp
95Generic Subprograms
- for (top 0 top lt len - 2 top)
- for (bottom top 1 bottom lt len - 1
- bottom)
- if (listtop gt listbottom)
- temp list top
- listtop listbottom
- listbottom temp
- // end of for (bottom ...
- // end of generic_sort
96Generic Subprograms
- Example use
- float flt_list100
- ...
- generic_sort(flt_list, 100)
- // Implicit instantiation
97Separate Independent Compilation
- Def Independent compilation is compilation of
some of the units of a program separately from
the rest of the program, without the benefit of
interface information - Def Separate compilation is compilation of some
of the units of a program separately from the
rest of the program, using interface information
to check the correctness of the interface between
the two parts.
98Separate Independent Compilation
- Language Examples
- FORTRAN II to FORTRAN 77 - independent
- FORTRAN 90, Ada, C, Java - separate
- Pascal - allows neither