/
Names and Binding Imperative programming has instructions that manipulate Names and Binding Imperative programming has instructions that manipulate

Names and Binding Imperative programming has instructions that manipulate - PowerPoint Presentation

trish-goza
trish-goza . @trish-goza
Follow
351 views
Uploaded On 2018-10-28

Names and Binding Imperative programming has instructions that manipulate - PPT Presentation

the state of the process the state is the collection of variables and their values For variables storage binding types scope Design issues for identifiers maximum length for the name what are the legal characters ID: 699790

variable type variables binding type variable binding variables time dynamic languages reference static memory scope subprogram int calls types

Share:

Link:

Embed:

Download Presentation from below link

Download Presentation The PPT/PDF document "Names and Binding Imperative programming..." is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.


Presentation Transcript

Slide1

Names and Binding

Imperative programming has instructions that manipulate

the “state” of the process

the

“state” is the collection of variables and their values

For variables: storage

, binding,

types, scope

Design issues for

identifiers

maximum length for the name? what are the legal characters?

COBOL

uses –

for connectors which detracts from readability

are

letters case sensitive

?

if so,

this

can detract from both readability and

writability

are

the special words of the language context sensitive (key words) or reserved?

in

FORTRAN, INTEGER and REAL are context sensitive leading to this possibility

INTEGER REAL

REAL INTEGERSlide2

Variables

A variable is an abstraction of

a memory location (for reference)

type-specific

methods to perform operations

The address is sometimes referred to as the l-value

Aliases

arise when multiple identifiers refer to the same memory

location, created through

pointers

pointing at the same allocated piece of memory

parameter passing

using pass by reference

union types

(covered in chapter

6)

Type

specifies

allowable

range of values

and

allowable operations

Value

current

value stored in memory,

referred

to as the

r-valueSlide3

Binding

Binding is the association of an object to its attributes, operations, or name

there are many different types of bindings

bindings

can occur at different times

design

time binding: binding * to multiplication

language implementation time binding:

int

size and operations

compile time binding: binding type to a variable

(as in

int

x; )

link

time binding: binding function name to a specific function

definition

load time binding: binding variable to memory location

run time binding: binding variable to memory location or bind a polymorphic variable to specific class type

Binding is

static

if it occurs before run time and remains unchanged, otherwise binding is

dynamicSlide4

Bindings: Variable Declarations

Binding the identifier name to the declared type

Are variables declared explicitly or implicitly?

most languages

historically have required

explicit variable declarations

exceptions are

FORTRAN (

based on first letter of variable name,

I

..

N for integer

,

otherwise real)

BASIC and

PL/I (

type

binding occurs when variable is first assigned a

value)

some recent languages use type inference (ML, Haskell, Miranda, F#),

type is determined by compiler based on given operations

Scripting/interpreted languages often have dynamic binding where variables are

typeless

see the next slideSlide5

Dynamic Type Binding

Introduced in LISP

binding of type is not explicit

derived

by examining assignment statements at

runtime

variable can store different types at different types

this is commonly handled by using a pointer so that the compiler only has to worry about creating storage for an address and then the type is bound based on when the value is allocated memory at run-time

Other languages that use dynamic type binding include JavaScript

, Perl, JavaScript, Ruby, and PHP

note

that in Perl, different types of variables are determined by their name

$name is a scalar, @name is an array, %name is a hash structure

In JavaScript

and Lisp you have to declare local variables but not type themSlide6

Static Lifetime

The lifetime is the time from which a variable is

bound

to memory until it is

unbound

a static lifetime means that the variable is bound before program execution begins and remains the same until program termination

Variables are statically bound if they are

global variables

variables in a C function declared as static

variables in a FORTRAN subroutine

this allows the subprogram to retain the value of the variable after the subprogram

terminates but prohibits

recursion or shadowing

Static is the most efficient form of binding

access is performed using direct memory addressing mode

no overhead needed for allocation or deallocation at runtime Slide7

Stack Dynamic Lifetime

Variable bound when execution reaches variable’s declaration in the code – through run-time stack

local variables, parameters for Algol-descended

languages (C/C++/Java, Pascal, Ada,

etc

)

also, variables declared within a block

Allocation

and deallocation are performed by the run-time

environment

allows for recursion

requires extra run-time overhead

Variable

unbound

(popped off the stack) when the

code

that contains the local

var

/parameter terminates and thus is no longer available/accessible

FORTRAN

95 includes a Save list instruction to save the list of variables somewhere other than the stack

if you want to retain a variable’s value in C, declare it as staticSlide8

Explicit Dynamic Lifetime

Variable storage allocated/deallocated explicitly at

runtime

from the heap

heap memory is nameless and accessed by pointers

pointer itself may be named (e.g.,

int

*p; ) or pointed to by another pointer if itself was allocated on the heap

Allocation instructions differ by language

C/C++:

malloc

,

calloc

, free, C++ also uses new for objects

Pascal, Ada: new, free

Java, C#: new, no deallocation instruction

PL/I: allocate, free

C

# has parameters that can be either stack dynamic or explicit dynamic

The variable’s

type

is bound at compile time even though the variable’s memory is not

allocated

until run-time

note that since

memory deallocation is often OS

specific

some

languages do not

actually implement a deallocation

routineSlide9

Implicit Dynamic Lifetime

Variable’s

memory

bound

while it is assigned a value

variable’s

attributes

bound

during this time

if the variable

is unbound and bound to a new memory location, then its attributes (including type)

can change

Lisp and JavaScript both use this approach

ALGOL 58

has “flex

for arrays

also used this approach

memory comes from the heap but no explicit allocation or deallocation (deallocation handled by garbage collection)

this form of lifetime has the highest

degree of flexibility but also highest amount of overhead

no compile-time type checking is possible since

type

can

change

any

type checking (if performed at all), must be done at run-time

allows for Generic code which can operate on any typeSlide10

Type Checking

Ensures that operands of an operator are compatible

compatible

type is either one that is legal for the operator or is allowed via an implicit coercion

(automatic conversion from one type to another)

for instance, an

int

can be coerced into a float and a float into a double but not the other way

A

type error (often called a

type mismatch

) occurs if an operand is not appropriate for an operator and cannot be coerced

If all bindings of variable to type are static, then type checking can be done completely at compile time

dynamically typed languages like Lisp, JavaScript

and APL perform dynamic (run-time) type checking

only

type checking is complicated if a memory location can store different types at different times of a program’s execution

(known as a Union type)Slide11

Strongly Typed

A

language

is strongly typed if

all

type checking errors are detectable before run-time

a more restrictive definition is if every identifier in a program has a single type associated with it and known at compile time

Both definitions require static

binding of variables

Being strongly

typed

is

desirable because it offers the best reliability with regard to type

errors

the problem with having a strongly typed language is that it removes flexibility

To be strongly typed, a language cannot have

dynamic type binding

union types

implicit coercions and unchecked conversionsSlide12

A Look at Various Languages

Few languages are strongly typed because nearly all languages have a mechanism to get around type checking

FORTRAN – in early versions, parameters were not checked, union types

Pascal – variant records are a type of union

C, C++ – optional parameters are not typed, union types available, pointers can be void pointers (another union type)

Ada, Java and C# – close to strongly typed in that no type errors can arise implicitly, however, all three languages have unchecked conversions

which

can lead to typing errors

APL, SNOBOL, LISP – dynamic type binding

ML, F# - strongly typed through type inferenceSlide13

Type Compatibility

Type compatibility determines whether a type error should arise or not

types are compatible if one is coercible into another

Languages

determine

compatibility based

two

strategies

name type compatibility

variables declared

using the same declaration or the same type

example: int x; int y; // x and y are name type compatible

compatible by structure

variables

have the same structure even though they are of differently named types, for example:

struct

foo { int x; float y; };

struct

bar { int x; float y;};

foo a; bar b; // a and b are structure type compatible

C uses compatibility by

structure, C

++ uses name compatibility

Ada uses name compatibility except for anonymous arrays which use structure compatibilitySlide14

Scope

Scope is the range of statements from which a variable is “visible”

where

the variable can be

referenced

Scope rules

determine

how the name being referenced

is associated

with a particular

memory location

this is necessary when dealing with non-local references to variables, or when variables are re-declared inside of blocks

Two

forms of

scope:

static

and dynamic

nearly all languages use static scope because it is easier to understand and type checking can be performed at compile time

LISP is

one of the few that has used dynamic

scope (although it now uses static scope unless overridden)

the Bash interpreter also uses dynamic scopeSlide15

Static Scope

Introduced in ALGOL 60 to bind names to non-local

variables, copied

by most

languages

since

scope for any variable can be determined prior to execution

two subtypes of static

scoping: subprogram nesting is allowed (Pascal-like languages) and not allowed (C-like languages)

if

subprograms can be nested, then this creates a hierarchy of scopes formed by the definitions of the subprograms

example: sub1 is defined inside of sub2 which is inside of sub3, then a variable referenced in sub3 but not declared in sub3 would be found in sub2, and if not in sub2, then in sub1

if two or more subprograms use the same name for a variable, the reference is to the definition that occurs in the subprogram innermost to the current, whereas the outer variable is “hidden”

in Ada,

hidden variables

can

be

accessed via notation like: sub1.xSlide16

Example of

Static Scope

Consider a program with nested subprograms:

Main contains A and B

A contains C and D

B contains E

In the language of this program, a nested

subprogram can call any nested subprogram

above it within the same subprogram, and

can be called by the subprogram it is nested in

so A can call C and D, D can call C, but C

cannot call D

B (which appears below A) can call A or D

but D and C cannot call B or E

Assume x is declared in MAIN, B and C and assume MAIN calls

B calls E calls

A calls

D calls C

If x is referenced in E, it is B’s x whereas

if x is referenced in D, it is MAIN’s x (not C’s) because D is statically scoped inside of MAIN but not in C

MAIN

MAIN

A

B

C

D

E

A

C

B

E

DSlide17

Blocks

In C-like languages

static scoping is not as much an issue because subprograms are not nested inside one another

But C-like languages

do allow

nested blocks

blocks

have

the same scope rules as static scoping

a variable is found in the section of code it is referenced, or else you must follow the blocks outward until you reach the definition or reach the end of the

function

Java

and C# do not allow duplication of variables in nested inner

blocks so that this is not an issue

note that OOPLs have another form of scope, the instance datum whose scope is based on its visibility modifier

we will explore this later in the semesterSlide18

Example

void

scopeexample

(

int

x)

{… // reference 1

{

int

x; // declaration A

… // reference 2

{

… // reference 3

{

int

x; // declaration B

… // reference 4

{

… // reference 5

}

}

}

}

… // reference 6

}

In

this

example, reference

1 is

to the

parameter

, reference 2

and 3 are to declaration A, reference 4 and 5

are to declaration

B, reference 6 is to the parameter again. If x were not the name of the parameter, reference 1, 2 and 6 would yield

syntax errorsSlide19

Dynamic Scoping

Scope is based on the

sequence

of calling subprograms

To

determine reference

search backward through the chain of subprogram calls until

the variable declaration is found in a previously active subprogram

dynamic scoping harms readability because, at compile-time, you do not know the sequence of subprogram invocations

consider three subprograms which all use a variable x and any of which could call the subprogram foo

foo accesses x, which x is being accessed? there is no way to know except at run-time

this also harms reliability since it makes any program harder to understand

Dynamic

scoping was used in APL, SNOBOL4, early LISPsSlide20

Example

MAIN

-

declaration of x

SUB1

-

declaration of x -

...

call SUB2

...

SUB2

...

-

reference to x -

...

MAIN calls SUB1

SUB1 calls SUB2

SUB2 references x

Static scoping –

reference to x is

to MAIN's x

Dynamic scoping - reference to x is

to SUB1's x

From

the static scope example

, if MAIN calls B calls E

calls A calls

D, and we access x in D, then we will

reference B’s

x, not MAIN’sSlide21

Referencing Environment

This is the

collection of variables which are accessible (visible)

to a given instruction in the program

in statically scoped languages, each statement’s

referencing environment

can be determined at compile time

in dynamically scoped languages, the

referencing environment

of a statement consists of

all

variables

(local and parameters) in

the local subprogram

all variables (local and parameters) declared in

active subprograms whose names are note the same as those of more recent declarations

all global variables

if none of the variables/parameters share the same name, then the referencing environment for a dynamically scoped language is all variables/parameters of all active subprograms!Slide22

Example

procedure Example is

A, B : Integer;

procedure Sub1 is

X, Y : Integer;

begin

 1

end;

procedure Sub2 is

X : Integer;

procedure Sub3 is

X : Integer;

begin

…  2

end;

begin

…  3

end;

begin

…  4

end.

Referencing

Environment at

1: X, Y of Sub1

A, B of Example

2: X of Sub3

A and B of Example

(X of Sub2 is hidden

but accessible as

Sub2.X)

3: X of Sub2,

A and B of Example

4: A and B of Example

Ada codeSlide23

Constants, Variable Initializations

An

identifier bound to a value at the time it is bound to storage and unalterable during its lifetime

constants

aid readability

and reliability of a program

Ada, C++, Java allow dynamic binding of constants so that the value is not set by the programmer but can be determined at runtime (for instance, passed into a method as a parameter)

For convenience, variable initialization can occur prior to execution

FORTRAN: Integer Sum Data Sum /0/

Ada: Sum : Integer :=0;

ALGOL 68: int first := 10;

C, C++, C#, Java

: int

num

= 5;

LISP (Let (x (y 10)) ... )