Title: CptS 355 Programming Language Design
1CptS 355Programming Language Design
Procedures 1 Concepts
- Roger Ray
- WSU Vancouver, Spring 2001
proc1.ppt
2Where Are We?
examples (specific languages)
data structures
how (compilers)
control structures
abstraction structures
3Procedure Issues
values to be manipulated
returnedresult
procedure code a "black-box", thatcan abstract
any piece of code
4Important Terminology
- Basic terms for code that is in one place but can
be used from many places - subroutine
- subprogram
- Alternate terms
- procedure - esp. when emphasizing that the code
performs an action - function - esp. when the code returns a value
- Other terms
- context - the environment within which the code
is evaluated - closure - a procedure with a special kind of
context (more later) - abstract - a fancy term for procedure that can
return anything, even types - OOP terms
- method - a family of procedures all with same
interface (more later) - And, for parameters
- formal - a name used in the procedure code
- actual - a value passed to the code
void foo (int x) ....
foo (14)
5What Is A Procedure?
- Consider this procedure definition
- And, this usage, in another file
- Output will be
b.cpp
a.cpp
static int x 0 int foo (int y) x x
y return x
extern int foo (int) void main () printf
("d\n" foo (2)) printf ("d\n" foo (3)) printf
("d\n" foo (4))
Precisely what does "foo" mean so that this
happens?
6To Talk Precisely, We Need to Recall ...
int i i 3
- a command
- has irreversible effect
- a declaration
- has reversible effect
- an expression
- yields a value
modifies
modifies
store a collection of values
environmenta collection of names
accesses
state (store, environment)
7What Happened ...
extern int foo (int) void main () printf
("d\n" foo (2)) printf ("d\n" foo (3)) printf
("d\n" foo (4))
b.cpp
static int x 0 int foo (int y) x x
y return x
a.cpp
- "foo" is bound to a procedure value in the global
environment - that value is a pair
- code (address of first instruction)
- an environment (the one w/ "x" bound)
- the extern is resolved
- the global env is searched for "foo"
- the name "foo" (in "b.cpp" env) is bound to what
that global "foo" is bound - "foo (2)" is evaluated
- evaluate "foo" (result is a procedure)
- evaluate "2" (result is actual parameter)
- get (code, env) from the procedure
- create new env w/ actual bound to formal
- evaluate code in that new environment
- "return" provides final value for "foo(2)"
foo (code, environment)
x x y return x
x int var, value 0
y int var, value 2
(enclosing env)
8What Is A Procedure?
code context
- A procedure is a pair
- code -- command to execute may return a result
- context -- the environment to wrap around that
code - Key idea
- code is interpreted in environment of procedure
definition, extended with formal/actual
correspondences - not the environment of usage (the caller)
- Other attributes
- formal types (the names are private to the code,
and are not attributes) - return type ("void" means no result)
extern int foo (int)
typedef int fooType (int) extern fooType foo
9Implemented Using a Call-Return Stack
- The stack organizes procedure calls
frame
frame
frame pointerchanges when call/return
FP
stack pointerchanges as push/pop
frame
SP
stack (growing downwards)
Detailed example
void main () printf ("d\n", A (5)) int A
(int x) int y 1 return (y B
(2x)) int B (int z) return (3z)
main frame
x return old FP y ...
5
"x" bound to FP 1"y" bound to FP 2
1
A's frame
z return old FP ...
10
FP
B's frame
SP
IC
10Several Language Design Issues
- Allowed return types e.g. can't return arrays
(Fortran) - Allowed formal types e.g. can't pass structures
(original C) - Allowed commands e.g. functions can't have
side-effects (Pascal) - Details of parm passing e.g. by-value,
by-reference, by-name - Syntactic conveniences e.g. "generic" and
"overloaded" subprograms - Restrictions on context see following ...
Resolutions are a designer's choice
balancing abstraction vs. efficiency
11Restrictions on Context
Context must be static
Context may be dynamic
stack frame
heap frame
int foo (int y) ...
- C, C, Java
- Fortran, Cobol
- PL/1
procedure value
code
(code, stack frame)
(code, heap frame)
context the global env local statics, so code
can determine context on its own
"closure"
12Context Stack Frame
- Consider this code
- The context for "swap" must be the stack frame
created by call to "arrange" - "swap" is bound in the scope created by the call
- "swap" context stack frame with binding for "a"
- the context doesn't exist at compile-time
dynamic! - Why useful?
(extended C)
void arrange (int n, int a) void swap (int
i, int j) int t ai ai aj aj
t ... complicated logic that calls swap ...
"a" in "swap" context is from the stack frame of
"arrange"
13Context Heap Frame
- Consider this code
- As before, context for "swap" must be the stack
frame created by "swapper" - But, that frame will disappear when "swapper"
returns! - So, the frame must be copied onto the heap
- "swap" context pointer to that heap chunk
- This approach required if allowed to return
procedures without restriction
(extended C)
typedef void Action (int, int) Action swapper
(int a) void swap (int i, int j) int t
ai ai aj aj t return swap
... int b100 Action f swapper (b) ... f (3,
4)
"swap" context must be preserved for later call
14Heap Context Useful to Implement Iterators
typedef int Iterator (Node) Iterator preorder
(Tree t) ... return a procedure
... Iterator postorder (Tree t) ... return
a procedure ... void print (Tree t) Node
n Iterator eachNode preorder (t) while
(eachNode (n)) printf ("d\n" n-gtdata)
E.g.Traverse a binary tree without revealing
the implementation
(extended C)
- Each time the iterator procedure is called, it
returns true/false and sets a node pointer. - The procedure maintains the state of the
iteration in it's context.
15How To Implement an Iterator
(extended C)
typedef int Iterator (int) Iterator range (int
lo, delta, hi) int now int f (int var)
var (now delta) return now lt
hi now lo return f void demo ()
int i Iterator oneToTen range (1, 1,
10) while (oneToTen (i)) printf ("d\n"
i)
f (code address, context)
frame on heap with now, lo, delta, hi
these are the state of the iteration
oneToTen (i) set i to next number, if any, and
return true or, if no next number, return false
16Parameter Passing Has Various Approaches
extern int a, i void foo (int x) i 1 x
2 a0
int a 11, 12, i 0 extern void foo
(int) void bar () foo (ai) printf ("d
d\n", a0, a1)
what is printed
how implemented
examplelanguages
The actual and the formal must get together ...
issues
- By-value
- formal parameter x is bound to a new variable
- actual parameter value is assigned to the
variable - By-reference
- formal parameter x is bound to the actual
parameter - thus the formal becomes an "alias" for the actual
- By-name
- formal is bound to a implicit procedure
- this re-evaluates the actual when the formal is
used
17Arrays and Structures Often Muddy Picture
static int a 1, 2, 3 static int b
b a b0 -1 printf ("d\n", a0)
- As we saw previously, designers have made
different array assignment choices - assign by-value values are copied from one place
to another - assign by-reference only address of values is
copied - For languages that use call by-value and assign
by-value there is a problem - an array actual parameter must be copied onto the
stack,because alterations via the formal
parameter should not change the actual - and, if the function returns an array as result,
it must be copied back somewhere! - Most designers have decided this is not useful,
so have chosen - arrays are passed by-reference e.g. Fortran,
PL/1 - arrays can NOT be returned from functions e.g.
Fortran - or they are returned by-reference (programmer
beware!) e.g. PL/1 - And, similarly for structures
18Dangers of Returning Arrays ...
Example (in C)
int add (int x, int y, int n) int
zn, i for (i 0 i lt n i) zi
xi yi return z main () int a
1, 2, 3 int b 10, 20, 30 int
c add (a, b, 3) printf ("d\n", c2)
note
- Is this legal C?
- What happens?
19Returning Arrays (continued)
Example (in Java)
int add (int x, int y) int n
x.length int z new int n for (int i
0 i lt n i) zi xi
yi return z void main () int a
1, 2, 3 int b 10, 20, 30 int c
add (a, b) System.out.println (c2)
note
- What are the differences from C?
- What are the advantages?
- What is the implementation?
20Procedures as Parameters is Useful
include ltstdio.hgt int dbl (int x) return
xx int sqr (int x) return xx void
map (int f(int), int a, int n) for (int i
0 i lt n i) ai f (ai) int
main () int a 1, 2, 3 map (dbl, a,
3) printf ("d\n", a2) map (sqr, a, 3)
printf ("d\n", a2)
map.cpp
legal C
Example usage
- Libraries
- sorting and searching
- Numerical
- function plotting
- root finding
- numerical integration
- numerical differentiation
- AI
- game playing
- GUI
- event procedures
g -o map map.o map
what is printed?
21GUI Event Procedures Solve a Hard Problem
- How structure the code for a GUI?
- minimize new application code
- maximize look feel consistency
application code
GUI framework code
lajfd al x y / z ifjf a
alfkjd afdl aldfsj lajfd al x y / z ifjf a
alfkjd afdl aldfsj lajfd al x y / z ifjf a
screenareas
coordinate via "event procedures" ... procedures
as parameters
mouse events
22Event Procedure Details
alfkjd afdl aldfsj lajfd al x y / z ifjf a
lajfd al x y / z ifjf a
- Application code
- init routine called ...
- ask framework to create a button
- register an event procedure
- return
- event procedure called ...
- do things
- update screen
- update variables
- return
- Framework code
- call application init routine
- wait for mouse signal
- determine relevant screen area
- find associated button data structure
- find registered event procedure
- call that procedure
- continue receiving signals
alfkjd afdl aldfsj lajfd al x y / z ifjf a
void init () Button b new Button
(...) b-gtonClick handler
void handler (MouseEvent e) ...
Much more on this when we discuss OOP ...
23Overloading Can Increase Code Clarity
- Permit several bindings of a name within an
environment, each to a procedure - Match of applied to binding occurrence is
disambiguated by type of actuals - Thus, procedures must be "sufficiently different"
in formal types - aka "signature" or "protocol"
(Algol 68 includes return type hairy!)
C example
int x 1 2 // call (int, int)
addition double y 1.0 2.0 // call (double,
double) addition
- C rules
- Look for exact match use it
- Look for match after applying standard coercions
use any match found - Look for match after applying user-defined
coercions OK if unique match - Issues
void print (int a) ... void print (double b)
... void print (int a, int width) ...
print (1) print (2.0) print (1, 10)
int z 1 ltlt 5 cout ltlt 5 cout ltlt "abc"
We will see lots of this inside the Turtle
compiler
24Other C Conveniences
- Your own overloaded operators (also Algol 68)
- e.g. , -, , , etc.
- you can define new data types via "struct" along
with operators and coercions - overloading allows new operators and coercions to
co-exist with built-in ones - your new data type is indistinguishable from a
built-in data type - Default parameter values
Complex average (Complex a, Complex b) return
(a b) / 2
too complex for beginners!
void print (double b) ... void print (int a,
int width 5) ...
allows code to evolve!
print (1, 10) print (1) print (2.0)
25How Make An Interface Clear?
- Two customers for clarity
- maintainer -- use procedure correctly
- compiler -- generate best code
- Accordingly, many aspects contained in procedure
signatures - formal types -- all modern languages
- return type -- ditto
- exceptions -- Java
- side effects -- Pascal
- reentrancy -- Java
- modification rights -- CLU, C
- pre/post conditions -- Eiffel
26Modification Rights (C)
- Can promise to not modify content of a structure
- add adjective "const" to a formal
- excellent coding practice
- Can also use "const" in definitions
- more flexible than define's
- still, "constant expressions" (e.g. static array
bounds) must be int via built-in ops
int strlen (const char s) // won't change any
si
char strcpy (char s, const char t) // may
change some si
const double PI 4 atan (1, 1)
define PI 3.1415926535897932384626433832795
27Pre/Post Conditions
- Help user understand how to use your routine
- pre what your code assumes is true at start
- post what your code claims is true at end
- Help debug your code
- add checking code in your implementation via
"assert" macro
// indexOfMin Return index of min element in an
array. int indexOfMin (int a, int
n) / pre n gt 1, a0..n-1 any values in
any order post aresult lt ai for all
i0..n-1 /
foo.h
int indexOfMin (int a, int n) assert (n gt
1) ... assert (isValidResult (result, n,
a)) return result
foo.cpp
28Other Topics To Which We Will Return
- How can we make a type such as "List" be
reusable? - done via "generic" procedures, parametric types
("templates"), and "polymorphism" - How can we express procedural commonality between
types? - done via "inheritance" (key OOP technique)
struct List1 int first List next List
(...)
struct List2 Person first List next List
(...)
...
struct List int first List next int
length ()
struct DoubleList int first DoubleList
next DoubleList previous int length ()
29Orthogonality Motivates Many Design Decisions
y
- orthogonal n (math)
- directions are at right angles
- dimensions are independent
(2, 5)
x
- orthogonal n (cpt sci)
- concepts can be used in any combination without
restrictions or inconsistencies
30A Resulting Design Principle
Principle of Uniformity
Things that seem alike should behave alike
31Procedure Design is an Example of Uniformity
Things that seem alike should behave alike
int f () int x 1 return x
For integers, an inner scope can declare and
return.
typedef int P () P outer2 (int a) int inner2
() return aa return inner2
int g () int a100 return a
void outer1 (int a) int inner1 () return
aa ... use inner1 ...
Can arrays be returned from procedures?
Can procedures be declared in an inner scope?
Can those procedures be returned?
32Closet ...
33How to Implement Inner Procedures
int outer (...) int x, ... int inner1 (...)
... inner1 commands ... int inner2 (...)
innermost (...) ... innermost commands
... ... inner2 commands ... ...
outer commands ...
Example(in extended C)
- Implementation
- Procedure (code address, context)
- context 0, if outer procedure
- context fp of defining scope, if inner
- Access outer variables as context-gtvariable
- Handle deeper nesting via static link chain
- each frame has a pointer to frame of the defining
scope - that pointer context of the active procedure
- ¹ the calling scope study diagram 3.5 in text
34How to Implement Inner Procedures
int outer (...) int x, ... int inner1 (...)
... inner1 commands ... int inner2 (...)
innermost (...) ... innermost commands
... ... inner2 commands ... ...
outer commands ...
operation
procedure (code address, context) context
frame pointer of binding scope, or 0 outer
0 inner1 fp2 inner2 fp2 innermost
fp4 static link in frame context of active
procedure fp1 -gt static link 0 fp2 -gt static
link 0 fp3 -gt static link fp2 fp4 -gt static
link fp2 fp5 -gt static link fp4 code finds
value of x via "pointer-gtx" outer fp
-gtx inner1 fp -gt static link -gt x inner2 fp -gt
static link -gt x innermost fp -gt static link -gt
static link -gt x
main frame
fp1
stack
outer frame
fp2
main -gt outer -gt inner1 -gt inner2 -gt innermost
inner1 frame
fp3
inner2 frame
fp4
innermost frame
fp5
35Inner Procedures Enable Iterators
typedef int Iterator (int) Iterator range (int
lo, delta, hi) int now int f (int var)
var (now delta) return now lt
hi now lo return f void demo ()
int i Iterator oneToTen oneToTen range
(1, 1, 10) while (oneToTen (i)) printf
("d\n" i)
(extended C)
- What should happen?
- How was that accomplished?
- Why would this be useful?
- Why is this uncommonly implemented?
- What are some languages that do?
36Modules
George's
mine
How can I reuse someone else's definitions?
D1 D2 D3
a set of interrelated bindings that I want to
reuse
D4 C
- What are examples of this situation?
- What are some of the behaviors we want?
- What are some languages that support this merging?
37There Are Many Possible Approaches
- The problem is one of merging environments
original env.
exported env.
importing env.
resulting env.
D1 D2 D3
D1 D2
__?__ C
D4
38Overloading
Things that seem alike should behave alike ...
1 2 4.5 6.1
I can use same symbol for built-in operations on
integers and reals
(C)
int max (int x, int y) return x gt y ? x
y double max (double x, double y) return x
gt y ? x y void demo () printf ("d\n",
max (14, 5)) printf ("g\n", max (3.14,
2.78))
Why not the same name for one of my operations?
- What is (should be) printed?
- Why?
- Is this useful?
- What are some problems?
- What are some languages?
39Summary
- Terminology
- names vs. values vs. types
- definitions vs. commands declarations
- store vs. environment
- bound vs. free
- scope vs. lifetime
- Namespaces
- Storage Allocation
- static, stack, heap issues and methods
- Principle of Uniformity
- applied to arrays and procedures
- Other
- modules
- overloading
40Goal of Orthogonality
y
- orthogonal n (math)
- directions are at right angles
- dimensions are independent
(2, 5)
x
- orthogonal n (cpt sci)
- concepts can be used in any combination without
restrictions or inconsistencies
41Goal of Orthogonality
y
- orthogonal n (math)
- directions are at right angles
- dimensions are independent
(2, 5)
x
- orthogonal n (cpt sci)
- concepts can be used in any combination without
restrictions or inconsistencies
42Typical Memory Organization
...
Process1
Processn
image
image
aka "address space"
context
context
000 ...
... fff
data
heap
stack
avail
shell stuff
code
"text"
"bss"