87
PLC: Blocks © 25 February 2022 1 / 86

PLC: Blocks 19 August 2021 1 / 86

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

PLC: Blocks © 25 February 2022 1 / 86

Overview of Course

• Names, References, Pointers• Expressions, Control Flow• Types• Blocks, Procedures• Exceptions• Modularity• Object-Oriented Programming

PLC: Blocks © 25 February 2022 2 / 86

Next Few Sections

• block structure• procedures and parameter passing• dynamic versus static scoping• implementation of non-local access• downward/upward funarg

• exception handling• modules

• data abstraction• transparent versus opaque data types

• OO programming

PLC: Blocks © 25 February 2022 3 / 86

Overview of Blocks Procedures

• Significance of blocks and scope• Scope rules• Dynamic versus static scoping• Procedures and parameter passing• Implementation of non-local access• Downward/upward funarg• Implications for programming language design

PLC: Blocks © 25 February 2022 4 / 86

Abstraction

Abstraction: conceptualization without reference to specific instances. The act ofdetermining the fundamental, essential, important, intrinsic propertiesdisassociated from the specific details.Abstraction: Any generalization technique that ignores or hides details to capturesome kind of commonality between different instances for the purpose of controllingthe intellectual complexity of engineered systems, particularly software systems.Two kinds of abstraction: process abstraction and data abstraction (cf. modularity)

PLC: Blocks © 25 February 2022 5 / 86

Blocks

The fundamental difference between (old) Fortran and Algol-like languages is theblock. A block has two intertwined meanings. First, a block is the access-definingunit of the language. Second, a block is a sequence of executable statements thatare treated as a unit. In most languages subprocedures are blocks in both senses ofthe word. In Pascal the only access-defining unit is the procedure. In contrast,Algol and Ada have other access-defining constructs called blocks.

Blocks play a diminished role in OO languages like Java and C++.

PLC: Blocks © 25 February 2022 6 / 86

Blocks

declare-- declarations

begin-- executable code

end;

PLC: Blocks © 25 February 2022 7 / 86

In Java declarations can appear anywhere in a block (syntactically like anotherform of statement, but declarations are not runtime actions). The Ada syntax ismore explicit (and verbose)./* Java */ -- Ada

declareint x; X: Integer ;x = 3; beginint y=x+4; X := 3;y = 2*y; declare

Y: Integer := X+4;begin

Y := 2*y;end;

end;

PLC: Blocks © 25 February 2022 8 / 86

Names of many kinds of things are introducted by declaration in blocks. Not justvariables.declare

-- declarations of exceptionsE,F,G,H: exception ;-- procedure declarationprocedure R;-- declaration : variable-- introduction with attributesX: Integer ;-- declaration and runtime actionY: Integer := 3;-- declaration , but possibly-- no action during runtimeZ: constant Integer := 3;

beginX := 3; -- action

end;

PLC: Blocks © 25 February 2022 9 / 86

Blocks can be nested in other blocks and in subprocedures.Blocks without names must be “called” or executed at the point in the programwhere they are defined. On the other hand, subprocedures (blocks with names)may be called from a place different from the place in the program where they aredefined.

PLC: Blocks © 25 February 2022 10 / 86

Blocks and procedures are similar. A block is a simple from a subprocedure.

Main: declareprocedure R is

I: Integer ;begin

null; -- doend R;

beginR; --call R

end Main;

Main: beginR: declare

I: Integer ;begin

null; -- doend R;

end Main;

PLC: Blocks © 25 February 2022 11 / 86

Uhlike blocks, one may paramertize subprocedures and resuse them. This is atemendous advantage and extremely important, but it is the commonality of theextent of the variables we focus on.One may reuse subprocedures and avoid repeating the code (again very important),and the reuse of subprocedures in different contexts gives rise to importantsemantic and implementation considerations.

PLC: Blocks © 25 February 2022 12 / 86

PLC: Blocks © 25 February 2022 13 / 86

Scope and extent

Recall . . ..

Scope. The scope of a declaration is the portion of the program text in which theidentifier introduced in the declaration is visible; i.e., has the attributes given to itby the declaration. We also speak of visibility.More about scope after introducing “block structure” . . .

Extent. The extent of a location in memory is the period of program execution inwhich the location can be accessed by some name or expression in the program.

PLC: Blocks © 25 February 2022 14 / 86

From the perspective of some point in the program, the local environment is thecollection of bindings declared in current block. The nonlocal environment is thecollection of all the accessible variables not declared in the current block.

PLC: Blocks © 25 February 2022 15 / 86

Blocks, Scope, and Complexity

Blocks are an important programming tool in managing the complexity ofprograms.Localization of scope. An important principle in making efficient, clear programs islocalization of scope. Identifiers should be declared in the smallest scopecontaining its uses.

Though not directly related to blocks, the following definition captures the essenceof an additional technique to reduce the complexity of programs.Single assignment style. In single assignment style every variable is assigned exactlyonce.Such variables can be declared final in Java.

PLC: Blocks © 25 February 2022 16 / 86

ScopeHere is an example of using single assignment style in Java to compute the monthof Easter in the Gregorian calendar. Notice that it was deemed preferable to assignto the variable epact twice, and so it cannot be declared final. All the variablesare declared just before they are needed.final int year = Integer . parseInt (args [0]);final int golden = (year % 19) + 1;final int century = (year / 100) + 1;final int gregorian = (3* century / 4) - 12;final int clavian = ((8* century + 5)/25) - 5;int epact = (11* golden +20+ clavian - gregorian )%30;if (epact ==24 || (epact ==25&& golden ==11)) epact ++;final int moon = (44- epact <21 ? 74:44) - epact;final int extra = (5* year / 4) - gregorian - 10;final int sunday = moon + 7 - (( extra+moon )%7);final String month = (sunday >31)?"April":"March";

PLC: Blocks © 25 February 2022 17 / 86

Scope

Here is an example of using single assignment style in Java to compute the monthof Easter in the Gregorian calendar.final int year = Integer . parseInt (args [0]);final int golden = (year % 19) + 1;final int century = (year / 100) + 1;final int gregorian = (3* century / 4) - 12;final int clavian = ((8* century + 5)/25) - 5;final int pre_epact = (11* golden +20+ clavian - gregorian )%30;final int epact =

(epact ==24 || (epact ==25&& golden ==11)) ? pre_epact +1 : pre_epact ;final int moon = (44- epact <21 ? 74:44) - epact;final int extra = (5* year / 4) - gregorian - 10;final int sunday = moon + 7 - (( extra+moon )%7);final String month = (sunday >31)?"April":"March";

PLC: Blocks © 25 February 2022 18 / 86

Epact

The epact (Latin epactae, from Greek: epaktai hèmerai = added days) has beendescribed as the age of the moon in days on January 1, and occurs primarily inconnection with tabular methods for determining the date of Easter. It varies(usually by 11 days) from year to year, because of the difference between the solaryear of 365–366 days and the lunar year of 354–355 days.’ee-pakt

PLC: Blocks © 25 February 2022 19 / 86

Call graph

Call graph of

funarg/main.adb

See also Sebesta, 8e, Figure 5.3, page 230.

call graph

PLC: Blocks © 25 February 2022 20 / 86

Semantics of Blocks

Since the execution of a subroutine continues until all the subroutines it has calledhave returned, calls behave in a LIFO (stack) order.The static enclosing block is always (usually) in the stack of activation recordsmaking it possible to find a block’s nonlocal variables by skipping through thestack.

PLC: Blocks © 25 February 2022 21 / 86

Scott 4e, Example 9.4, page 413.Whether or not a subroutine is called directly by the lexically surround-

ing routine, we can be sure that the surrounding routine is active; there isno other way that the current routine could have been visible, allowing itto be called.

PLC: Blocks © 25 February 2022 22 / 86

Interplay of static and dynamic factors.

runtime/calls.adbruntime/nested.adbruntime/blocks.adbruntime/recurse.adbruntime/var_access.adb

PLC: Blocks © 25 February 2022 23 / 86

Scope Rules

The nested structure of scoping can be represented pictorially via contour diagramsor nested boxes. The local environment of every block appears in a box. Thenonlocal environment comprises all the variables in surrounding boxes. This rulecorresponds to implicit inheritance, i.e., variables declared in outer blocks arevisible to inner blocks. Variables declared in inner blocks are not visible. If a nestedblock introduces an identifier declared in an outer block, then the outer declarationis eclipsed and there is a hole in its scope for the scope of the inner block. Almostall languages use implicit inheritance, although Euclid does not.

PLC: Blocks © 25 February 2022 24 / 86

Scope Rules

Static scoping or lexical scoping means that a procedure is called in theenvironment of its definition.A procedure is defined in one place in the program, but may well be called in anentirely different environment or environments. If a procedure is called in theenvironment of its caller, then we have dynamic scoping sometimes known asdynamic binding, or fluid binding. This is the most recently occurring andstill-active binding of a variable.

PLC: Blocks © 25 February 2022 25 / 86

Static Versus Dynamic Scoping

Outer: declareb: Boolean := true;-- 1st decl of variable bprocedure P isbegin

print (b); -- variable b not local to Pend P;

beginInner: declare

b: Boolean := false; -- 2nd decl of bbegin

P; -- call procedure Pend Inner;

end Outer;

PLC: Blocks © 25 February 2022 26 / 86

Typical Exam Question

Write a simple, Algol-like program that distinguishes dynamic scoping from staticscoping. Explain.

[See previous program.]

In dynamic scoping “false” is printed because the environment of the caller(“Inner” block) is used; in static scoping the environment in which the procedure isdefined is used (“Outer” block), so “true” is printed.

PLC: Blocks © 25 February 2022 27 / 86

Grading Exam Question

10 obviously correct, exemplary explanation9 -1 for absurd syntax, but clear explanation8 -1 for too many declarations7 -1 for too many blocks6 clearly different behavior5 separate environment for call site; weak explanation4 a non-local variable32 two declarations, same variable10 blank sheet

PLC: Blocks © 25 February 2022 28 / 86

Static versus Dynamic

Illustration of non-local and global variables in Python.

scope/scope1.pyscope/scope2.pyscope/scope3.pyscope/scope4.py – static versus dynamic

PLC: Blocks © 25 February 2022 29 / 86

Static versus DynamicScott 4e, Figure 3.9, 143.

n: integerprocedure first

n:=1 -- non-local variableprocedure second

n: integerfirst () -- call first

n :=2if readInteger()>0

second()else

first()writeInteger(n)

PLC: Blocks © 25 February 2022 30 / 86

Static versus Dynamic

n: integer = 2procedure first:

third ()writeInteger(n) -- non-local variable

procedure second:n: integer = 1first () -- call first

procedure third:n: integer = 3

second()

PLC: Blocks © 25 February 2022 31 / 86

Static versus DynamicMain: declare

N : Integerprocedure First isbegin

Third; Put (N);end First;procedure Second is

N : Integer ;begin

N := 1; First;end Second ;procedure Third is

N : Integer ;begin

N := 3;end Third;

beginN := 2; Second ;

end Main;

PLC: Blocks © 25 February 2022 32 / 86

Procedural Abstraction

A procedure is a block with a name so that it can be called many times, perhaps indifferent contexts.The subprocedure is an important building block in writing complex programs,because the details of a subprocedure can be ignored. Caller needs to know what itdoes; not how it does it.If you find yourself writing the “same” code again and again, it is time for asubprocedure.

PLC: Blocks © 25 February 2022 33 / 86

Interface

Interface. In general, an interface is the boundary between distinct systems.Specifically, the specification or protocol governing their interaction.Procedure specification. A procedure specification describes the interface betweenthe procedure and the caller of the procedure. This may include the number,mode, default values and type of the procedure’s parameters, and, if a function,the return type.Many different terms are in use for this concept: parameter profile, profile,protocol, prototype, type.Side effect. A side effect is some action or effect that a subprocedure has on thecaller that is not advertised through the procedure specification. For example, achange to a non-local variable is a side effect. Even the use of a non-local mayeffect the outcome of a procedure call.

PLC: Blocks © 25 February 2022 34 / 86

Procedures

Actual argument. An expression supplied as an argument in the procedure call issaid to be an actual argument.Formal parameter. The name used within the subroutine or function to refer to theactual argument supplied when the subroutine is called is said to be formalparameter. The actual arguments may vary every time the subroutine is called inthe program, but the names of the formal parameters are given once in thedefinition of the subroutine. These names are picked by the programmer when thesubroutine is written. Usually, the formal parameters and their types are introducedat the beginning of the subroutine’s definition.

PLC: Blocks © 25 February 2022 35 / 86

Association to Actual Arguments

Some common ways of associating formal parameters to the actual arguments are:Positional associationNamed association or keyword association orDefault parametersSebesta 8e, 9.2.3 Parameters, page 388 (formal parameters, positional parameters,keyword parameters, default values)

PLC: Blocks © 25 February 2022 36 / 86

Sometimes parameters can have a variable number of arguments—evenstrongly-types languages, like Java.

Examples of these follow.

PLC: Blocks © 25 February 2022 37 / 86

Ada Positional, Named, and Default

passing/association.adb

Python has positional, named (called keyword), and default parameters. Butbecause it is not strongly typed, there is no overloading.Java has only positional association of parameters. Because of overloading there isno necessity for default parameters and the added complication of overloadingresolution was judged to be too much.

PLC: Blocks © 25 February 2022 38 / 86

Default Parameters in Pythondef f (a, L=[]): -- L is the same mutable list

L. append (a)return L

print f(4 ,[1 ,2 ,3]) f(1), f(2), f(3)

def g (a, L=None ):if L is None:

L = []L. append (a)return L

print g(4 ,[1 ,2 ,3]) , g(1), g(2), g(3)

The output:

[1, 2, 3, 4] [1] [1, 2] [1, 2, 3][1, 2, 3, 4] [1] [2] [3]

PLC: Blocks Default Parameters © 25 February 2022 39 / 86

Default Parameters

See also Scala’s call-by-name default parameters.

PLC: Blocks Default Parameters © 25 February 2022 40 / 86

Variable Number Of Arguments

Ever wondered how printf worked in Java with any number of arguments. Ittreats them exactly as an homogeneous array. Similarly, Python treats thearguments a list.

PLC: Blocks Default Parameters © 25 February 2022 41 / 86

Parameter Passing MechanismA parameter passing mechanism is a facility provided by a programming languageto pass data between the caller and the callee.

Webber, Chapter 18 Parameters, page 350.Sebesta, 8e, Section 9.5 Parameter Passing Methods.

We identify seven distinct means.• call by reference – pass l-value• call by value – pass r-value to local variable• copy-out – local variable, initially undefined, copied back• copy-in/copy-out – previous two mechanisms combined∗ text substitution∗ call by name∗ call by need

PLC: Blocks Parameter Passing © 25 February 2022 42 / 86

Parameter Passing

The common parameter-passing mechanisms are defined by how they areimplemented.On the other hand it might make more sense to define the mechanisms by how thesubprocedure is supposed to act.

PLC: Blocks Parameter Passing © 25 February 2022 43 / 86

Parameter Passing

Many programs pass data to subroutines using non-local variables. In the pastFORTRAN’s COMMMON block was used in this way. And today this is commonin the instance variables of OO languages like Java. Because this reliance onnon-local or external data sources is not described in the subprocedurespecification, this practice leads to programs that are difficult to understand.Ideally the procedure specification (declaration) documents all communication inand out of a subprocedure. (Consider this issue in the context of raisingexceptions, too.)

PLC: Blocks Parameter Passing © 25 February 2022 44 / 86

Side Effects Are Evil

Mike Myers as Dr. Evil

PLC: Blocks Parameter Passing © 25 February 2022 45 / 86

Call-By-ReferenceThe earliest parameter passing mechanism was call-by-reference in FORTRAN.Pass the l-value of actual to the procedure. Hence, the formal refers directly tosame location as the actual argument.

PLC: Blocks Parameter Passing © 25 February 2022 46 / 86

Call-By-Reference

Gries recounts that you could change the constant 2 to 3 in an early FORTRANcompiler!

Main: declareprocedure Change (out X:Int)isbegin

X := 3;end Change ;Y : Integer := 2

beginChange (Y);Put (Y); -- Y=3, of course

end Main;

Main: declareprocedure Change (out X:Int)isbegin

X := 3;end Change ;

beginChange (2); -- illegal argPut (2);

end Main;

PLC: Blocks Parameter Passing © 25 February 2022 47 / 86

Issues with Call-By-Reference

Different names referring to the same thing is the definition of aliasing.1 procedure/main.adb

2 procedure/parameter_aliasing.adb

PLC: Blocks Parameter Passing © 25 February 2022 48 / 86

Call-By-ValueAllocate local storage for each formal parameter. Copy the r-value of each actualargument at the beginning of the call.

PLC: Blocks Parameter Passing (Call-By-Value) © 25 February 2022 49 / 86

In C parameters passed by value (only); how does information ever flow back to thecaller? Parameters passed by reference can be simulated with pointers.void proc (int* x, int y) { *x = *x+y }proc (&a,b); // pass reference to a

But in Pascal and C++ the writer of the procedure can ask for call-by-reference.void proc (int& x, int y) { x = x + y }proc(a,b); // compiler knows to pass reference

PLC: Blocks Parameter Passing (Call-By-Value) © 25 February 2022 50 / 86

Java uses only call-by-value. Primitive types cannot be passed by reference(wrapper classes are not a work around). For primitive types this can be annoying.Everything else is an object. A pointer is passed as the “value” of an object.The efficiency of call-by-reference is acheived for references to objects. Theappearance of call-by-reference is obtained with mutable objects (like arrays).

PLC: Blocks Parameter Passing (Call-By-Value) © 25 February 2022 51 / 86

Copy-Out

declareA: array 1..10 of Integer ;i: Integer := 1;procedure P (x: out Integer ) isbegin

i := 2; x := 3;end P;

begin-- L-value computed just before callP (A[i]);

end;

PLC: Blocks Parameter Passing (Copy-Out) © 25 February 2022 52 / 86

Copy-In/Copy-Out

Call-by-value (copy-in) combined with copy-out.The actual argument mus thave an l-value.

PLC: Blocks Parameter Passing (Copy-In/Copy-Out) © 25 February 2022 53 / 86

Parameter Passing

Copy-in/copy-out is not the same as call by reference.declare

G: Integer := 1;procedure P (X: Integer ) is

-- reference ** copy -in/copy -outbegin -- ** X:=G:=1

X := 6; -- G:=X:=6 ** X:=6G := 9; -- G:=9 ** G:=9

end P; -- ** G:=X:=6-- G=9 ** G=6

beginP (G); -- call P

end;

PLC: Blocks Parameter Passing (Copy-In/Copy-Out) © 25 February 2022 54 / 86

Implmentation or Intention?

Parameter passing defined by the method of implementation of the formal/actualassociation (call-by-reference, call-by-value, copy-in/copy-out).Parameter passing defined by the intent of programmer in using the parameters:in, out, in/out.Parameter passing defined by the outcome of the procedure call with the actualssubstituted for the formals. Might be considered the correct way, but there aresome implementation issues (text substitution, call-by-name, call-by-need.)

PLC: Blocks Parameter Passing © 25 February 2022 55 / 86

Implementing Block-Structured Languages

During the running of the program every subprocedure needs to know where thecode is to execute next (a subprocedure is not always called from the same point inthe program). In the absence of recursion, a global place for each subprocedure’sreturn address could be allocated.However, in the presence of recursion, it seems necessary and advantageous for theruntime system of a language to keep (during execution) a stack of addresses forall the pending subprocedure calls in order that each subprocedure can continueexecution at the point in was suspending in order to execute another subroutine.

PLC: Blocks Non-Local Variable Access © 25 February 2022 56 / 86

Implementing Block-Structured Languages

As a matter of fact, this can be extended to a structured record of asubprocedure’s invocation that includes not only the return address but argumentsand local variables as well.The LIFO order makes it very efficient to reuse the space allocated to localvariables.And, and . . . , the nonlocal variables seem to be in some other subprocedure’s (orblock’s) local variables.

PLC: Blocks Non-Local Variable Access © 25 February 2022 57 / 86

Implementing Block-Structured Languages

This activation record is a data structure providing parameters, local variables, thenon-local environment, and the return address of each invocation of asubprocedure.Because of the nature of subprocedure call and return (LIFO), it is reasonable tocreate instances of these activation records on a stack.This stack, part of the runtime system and is called the run-time stack or simplythe stack.

PLC: Blocks Non-Local Variable Access © 25 February 2022 58 / 86

Static and Dynamic Structure

Static, hierarchical structure of runtime/nested.adb and dynamic, run-timebehavior of the program.

RQ Q Q R

P P P P P Q Q QN N N N N N N N N N N

begin == time ==> end

PLC: Blocks Non-Local Variable Access © 25 February 2022 59 / 86

Non-Local Variable Access

The tricky part about implementing the run-time behavior of the program correctlyis non-local variable access.Decisions about how to implement this access have a profound impact onprogramming language design as we shall see.

PLC: Blocks Non-Local Variable Access © 25 February 2022 60 / 86

Block Structure

PLC: Blocks Non-Local Variable Access © 25 February 2022 61 / 86

Block Structure

PLC: Blocks Non-Local Variable Access © 25 February 2022 62 / 86

Block Structure

PLC: Blocks Non-Local Variable Access © 25 February 2022 63 / 86

Non-Local Variable Access

A key observation about the stack implementation of the run-time environment isthat two values pinpoint a variable in static binding. One, the static distance is thedifference in static nesting between a variable use and its declaration. The staticnesting is how deeply nested a declaration or variable use is. Two, offset is a moreor less arbitrary displacement within an activation record locating where the variableis stored. At compile time this information can easily be stored in the symbol tableand used to generate code to access the local or nonlocal variable. A local variable(static distance equal zero) is located in the current activation record. A nonlocalvariable is located n hops (where n is the static distance) along the static chain.This fetch can be done in constant time if the static links are kept in an array.

PLC: Blocks Non-Local Variable Access © 25 February 2022 64 / 86

The static link is a pointer (during the execution of the program) to the activationrecord of the statically enclosing procedure or block.The static chain of the currently active procedure is the sequence of activationrecords representing the statically enclosing procedure or blocks.This static link must be maintained at runtime.

PLC: Blocks Non-Local Variable Access © 25 February 2022 65 / 86

Ada Program Example

The static link is not equal to the dynamic link. Also note that in the presence ofrecursive calls more than one activation record for a given subprocedure may be onthe call stack.

1 block/main.adb – static versus dynamic link, recursion

PLC: Blocks Non-Local Variable Access © 25 February 2022 66 / 86

Implementing Variable Access

fetch M[EP + offset(v)] ; local variable

AR := M[EP].SL ; activation record of parentfetch M[AR + offset(v)] ;

AR := M[EP].SL ; activation record of parentAR := M[AR].SL ; traverse second static link...

AR := M[AR].SL ; traverse last static linkfetch M[AR + offset(v)] ;

PLC: Blocks Non-Local Variable Access © 25 February 2022 67 / 86

Subprogram Call

When the compiler encounters a subprogram call . . . it determines the subprogram thatdeclared the called subprogram, which must be a static ancestor of the calling routine. Itthen computes the nesting_depth, or number of enclosing scopes between the caller andthe subprogram that declared the called subprogram. This information is stored and can beaccessed by the subprogram call during execution. At the time of the call, the static link ofthe called subprogram’s activation record instance is determined by moving down the staticchain of the caller the number of links equal to the nesting_depth computed at compiletime.Sebesta 11th, section 10.4.2 Static Chains, page 434–435

PLC: Blocks Non-Local Variable Access © 25 February 2022 68 / 86

Subprogram Call

In a language with nested subroutines and static scoping (e.g., Ada, Common Lisp, ML,Scheme, or Swift), objects that lie in surrounding subroutines, and that are thus neitherlocal nor global, can be found by maintaining a static chain (Figure 9.1). Each stack framecontains a reference to the frame of the lexically surrounding subroutine. This reference iscalled the static link. By analogy, the saved value of the frame pointer, which will berestored on subroutine return, is called the dynamic link. The static and dynamic links mayor may not be the same, depending on whether the current routine was called by itslexically surrounding routine, or by some other routine nested int hat surrounding routine.Scott 4e,

PLC: Blocks Non-Local Variable Access © 25 February 2022 69 / 86

Calling A Procedure; transmit parametersM[SP].PAR[1] := evaluation of parameter 1M[SP].PAR[n] := evaluation of parameter n

M[EP].IP := resume ; save resume locationM[EP].DL := EP ; set dynamic link

AR := M[EP].SL ; static parent, and so onAR := M[AR].SL ;M[SP].SL := AR ; set static linkEP := SP ; push new activation record; callee should increment stack size; SP := SP + size(callee’s activation record)goto entry(callee)resume:

PLC: Blocks Non-Local Variable Access © 25 February 2022 70 / 86

Upward Funarg Problem

OK, fine. The program of non-local variable access is marvelously solved. Let uspush the boundaries.

“First-class subroutines in a language with nested scopes introduce an additionallevel of complexity: they raise the possibility that a reference to a subroutine mayoutlive the execution of the scope in which that routine was declared.”Scott, page 144.

PLC: Blocks Non-Local Variable Access © 25 February 2022 71 / 86

Passing Procedures

Consider programs in which procedure pass other procedures around as arguments.

PLC: Blocks Non-Local Variable Access © 25 February 2022 72 / 86

Passing Procedures

1 What gets passed to Q to represent P or T?2 What code must be emitted to implement the call fp(5)?

For any procedure call we must:1 transmit the parameters,2 save the return address,3 set the dynamic link,4 start the execution of the new procedure,5 set the static link.

Closure. The value of a procedure is a closure—an ep, ip pair: environment pointerand code (instruction) pointer.

PLC: Blocks Non-Local Variable Access © 25 February 2022 73 / 86

Closure

A closure is a program and the referencing environment where it was de-fined.

Sebesta, 11th, page 406.

In a language with first-class functions and static scope, a function valueis generally represented by a closure, which is a pair consisting of a pointerto function code and a pointer to an activation record.

Mitchell, page 182.

PLC: Blocks Non-Local Variable Access © 25 February 2022 74 / 86

Calling A Formal Procedure

; transmit parametersM[SP].PAR[1] := evaluation of parameter 1...

M[SP].PAR[n] := evaluation of parameter n

M[EP].IP := resume ; save resume locationM[EP].DL := EP ; set dynamic link

M[SP].SL := fp.EP ; set static linkEP := SP ; push new activation record; callee should increment stack size; SP := SP + size(callee’s activation record)goto fp.IPresume:

PLC: Blocks Non-Local Variable Access © 25 February 2022 75 / 86

Ada Program Examples

1 funarg/main.adb – nested blocks, non-local variables2 funarg/pass.adb – passing procedures3 funarg/diff.adb – procedures with different environment pointers4 funarg/down.adb – again passing procedures, but trouble5 funarg/ret.adb – returning procedures with different environment pointers6 funarg/up.adb – trouble with returning procedures7 funarg/abuse.adb – slipping closure out of its environment

PLC: Blocks Non-Local Variable Access © 25 February 2022 76 / 86

Ada Program Examples

1 funarg/accessibility.adb – illustrate dynamic accessibility check

PLC: Blocks Non-Local Variable Access © 25 February 2022 77 / 86

Passing a procedure down is not a problem; set the ep to the correct parent. Hereis the stack of the program funarg/down.adb at different times during theexecution of the program.

DownRQ

DownRQ

fp=P

DownRQ

DownRQ

fp=T

PLC: Blocks Non-Local Variable Access © 25 February 2022 78 / 86

Passing a procedure up is a problem; the ep is set to an activation record that ispopped off the stack. Here is the stack of the program funarg/up.adb atdifferent times during the execution of the program.

Up Up

Rep(P)

Upep(P) Up

anon=P

Up Up

Rep(T)

Upep(T)R

Up ??

PLC: Blocks Non-Local Variable Access © 25 February 2022 79 / 86

Upward Funarg Problem

So, what is the conclusion? Either

1 Forbid returning and assigning subprocedures. E.g., Pascal.2 Fine print with pointer types. E.g., Ada.3 Restrict all local procedures. E.g., Modula-3. Even though downward function

args would be quite safe, assigning procedure values makes it impossible toknow if its use is upward or downward. Modula-3 encourages a “flat”structure.

4 No local procedures. E.g., C, C++, Java.1 recent lambdas implemented as closures as classes

5 Throw out the stack-based implementation. E.g., functional languages(discussed later).

PLC: Blocks Non-Local Variable Access © 25 February 2022 80 / 86

Ada

Here are the details from the Ada reference manual:3.10.2 Operations of Access Types ¶24 X’AccessThe view denoted by the prefix X shall satisfy the following additional

requirements, presuming the expected type for X’Access is the generalaccess type A:

¶29 b A check is made that the accessibility level of X is not deeperthan that of the access type A. If this check fails, Program_Error is raised.

In general, this is determined statically, but access parameters and generics requiredynamic checks. We saw this error in the program funarg/up.adb

PLC: Blocks Non-Local Variable Access © 25 February 2022 81 / 86

PLC: Blocks Non-Local Variable Access © 25 February 2022 82 / 86

Modula-3

2.3.1 Assignment An expression e is assignable to a variable v if:• the type of e is assignable to the type of v, and• the value of e is a member of the type of v, is not a local

procedure, and if it is an array, then it has the same shape as v.The first point can be checked statically; the others generally require

runtime checks. Since there is no way to determine statically whetherthe value of a procedure parameter is local or global, assigning a localprocedure is a runtime rather than a static error.

and . . .

PLC: Blocks Non-Local Variable Access © 25 February 2022 83 / 86

Modula-3

. . . return is handled like an assignment . . .

2.3.11 Return A RETURN statement for a function procedure has theform:

RETURN Expr

where Expr is an expression assignable to the result type of the procedure

funarg/Down.m3funarg/Up.m3

PLC: Blocks Non-Local Variable Access © 25 February 2022 84 / 86

C And Procedures

The programming language C has no nested procedures, so a closure need onlycontain a pointer to the code. No restrictions on passing procedure pointers areneeded.In C++ and Java you can pass subprocedures only inside classes. Pointers toinstances of classes are “closures;” they point to all the instance variables and allthe methods.Passing subprocedures in C++ and Java is clumsy.

inner/Searcher.javamember/function.cc

PLC: Blocks Non-Local Variable Access © 25 February 2022 85 / 86

Go And Procedures// New returns a function Count.// Count prints the number of times it has been invoked .func New () (Count func ()) {

n := 0return func () {

n++fmt. Println (n)

}}

func main () {f1 , f2 := New (), New ()f1() // 1f2() // 1 ( different n)f1() // 2f2() // 2

}

PLC: Blocks Non-Local Variable Access © 25 February 2022 86 / 86

Summary

1 Block-structured languages required the development of new run-timetechniques

2 An activation record represents the state of a procedure3 Activation records contain the local variables4 Instruction counter represents the site of control; the environment pointer

represents the context5 A static link points to the activation record of the lexical parent6 Variables are addressed by two coordinates: static distance and offset7 Accessing a variable requires two steps; can be done in one machine instruction

PLC: Blocks © 25 February 2022 87 / 86