Ti1220 Lecture 2: Names, Bindings, and Scopes

Post on 05-Dec-2014

2,366 views 3 download

description

 

transcript

TI1220 2012-2013Concepts of Programming Languages

Eelco Visser / TU Delft

Lecture 2: Names, Bindings, and Scopes(Sebesta Chapter 5)

Outline

Messages from the lab

Names

Variables

Binding & binding time

Scope

Demo: Spoofax name binding language

Messages from the Lab

“There were not a lot of students at the lab. This of course is ok for the first week, but students should be told that they stand no chance of passing the graded assignments without the tutorials, or the exam without the graded assignments.”

“There are too many rooms for the number of students. Could you mention that they should start filling the rooms from the top, one by one and then move down as they fill up. Room 0.010 is quite unhandy for labs because of the cubicles.”

“WebLab of course does not work properly in Internet Explorer, we should tell students that.”

Email addressese.visser@tudelft.nl: for personal questions about grades and suchti1220.ewi@gmail.com: for general questions about the labti1220.ewi+lab@gmail.com: for questions about the lab (addresses all student assistants)

PoliciesOur first response: did you ask this question at the lab?We’re closed in the weekend (in principle)Please report problems with WebLab immediately

Names (Identifiers)

Name Forms

[a-zA-Z][a-zA-Z0-9\_]* -> ID %% typical

"$" [a-zA-Z][a-zA-Z0-9\_]* -> PhpID [\$\@\%][a-zA-Z][a-zA-Z0-9\_]* -> PerlID "@" [a-zA-Z][a-zA-Z0-9\_]* -> RubyInstanceVar"@@" [a-zA-Z][a-zA-Z0-9\_]* -> RubyClassVar

Case Sensitive or Case Insensitive?

foobar == FooBar == FOOBAR ?

C-based languages: case sensitiveC convention: variable names only lower case letters Pascal: case insensitiveJava convention: CamelCase instead of under_scores

Special Words

keyword: identifier with special meaning in certain contexts

reserved word: special word that cannot be used as a name

Integer AppleInteger = 4

type

name

Fortran

Integer RealReal Integerpackage example;

class User { private String name; public String get_name { return name; }} Java

Variables

A program variable is an abstraction of a computer memory cell or collection of cells

machine language: absolute numeric address of data

assembly language: names for data

The attributes of a variable:NameAddressValueTypeLifetimeScope

the address of a variable is the machine memory address with which it is associated

def gcd(x: Long, y: Long): Long = if (y == 0) x else gcd(y, x % y)

each call to gcd creates new instances of x and y

alias: multiple variables accessing same memory location (more next week)

Type & Value

the type of a variable determines the range of values the variable can store and the set of

operations that are defined for values of the type

the value of a variable is the contents of the memory cell or cells associated with the variable

Binding & Binding Time

a binding is an association between an attribute and an entity

Example bindingsvariable to typevariable to valuefunction call to function definition

val msg = "Hello, " + "world!"

println(msg)

defining occurrencebinding

val variables cannot be rebound

applied occurrence

Binding Variable Identifiers

var greeting = "Hello, world!"

greeting = "Leave me alone, world!"

var variables can be rebound

rebinding

bindingdefining occurrence

Binding Variable Identifiers

def widthOfLength(s: String) = s.length.toString.length

val maxWidth = widthOfLength(longestLine)

bindingdefining occurrence

applied occurrence

Binding Function Identifiers

class ChecksumAccumulator { var sum = 0}

var acc = new ChecksumAccumulatorvar csa = new ChecksumAccumulator

acc.sum = 3csa = acc

binding

applied occurrence

defining occurrence

Binding Class Identifiers

class ChecksumAccumulator { var sum = 0}

var acc = new ChecksumAccumulatorvar csa = new ChecksumAccumulator

acc.sum = 3csa = acc

mutation

binding

rebinding

Rebinding vs Mutation

object foo { val foo : Int = 0 def foo(x : Int) = x + 1}

object bar { def bar() = foo.foo(foo.foo) }

variables, functions, objects are in separate name spaces

Namespaces

the time at which a binding takes places is called binding time

Example binding timeslanguage design timelanguage implementation timecompile timeload timelink timerun time

Type int in Cbound to range of possible values (e.g. 32 bit words)at language implementation time

Variable in Javabound to data typeat compile time

Variable in JavaScriptbound to data typeat run time

Symbolic Constants (C)

#include <stdio.h>#define LOWER 0 /* lower limit of table */#define UPPER 300 /* upper limit */#define STEP 20 /* step size */

/* print Fahrenheit-Celsius table */main() { int fahr; for (fahr = LOWER; fahr <= UPPER; fahr = fahr + STEP) printf("%3d %6.1f\n", fahr, (5.0 / 9.0) * (fahr - 32));}

0 -17.8 20 -6.7 40 4.4 60 15.6 80 26.7100 37.8120 48.9140 60.0160 71.1180 82.2200 93.3220 104.4240 115.6260 126.7280 137.8300 148.9

compile-time binding of values

Typedefs (C)

typedef int Length;

Length len, maxlen;Length *lengths[];

typedef struct tnode *Treeptr;typedef struct tnode { /* the tree node: */ char *word; /* points to the text */ int count; /* number of occurrences */ struct tnode *left; /* left child */ struct tnode *right; /* right child */} Treenode;

Treeptr talloc(void) { return (Treeptr) malloc(sizeof(Treenode));}

compile-time binding of type name

Function Definitions and Calls (Scala)

def max(x: Int, y: Int): Int = { if (x > y) x else y}

max(3, 5)

function statically bound, argument values dynamically bound to formal parameters

Recursion (Scala)

def fib(x: Long): Long = if (x <= 0) 1 else if (x == 1) 1 else fib(x - 1) + fib(x - 2)

def gcd(x: Long, y: Long): Long = if (y == 0) x else gcd(y, x % y)

recursion requires dynamic binding of variables

a binding is static when it occurs before run time and remains

unchanged throughout execution

a binding is dynamic if it first occurs during run time or can change in the course of program execution

Function Expressions (JS)

// This function expression defines a function that squares its argument.// Note that we assign it to a variablevar square = function(x) { return x * x;}var q = square(10);function square(x) { return x * x; }

// Function expressions can include names, which is useful for recursion.var f = function fact(x) { if (x <= 1) return 1; else return x * fact(x - 1);};

// Function expressions can also be used as arguments to other functions:data.sort(function(a, b) { return a - b; });

// Function expressions are sometimes defined and immediately invoked:var tensquared = (function(x) { return x * x; }(10));

var square = function foo(x) {! return x * x;};

var z = square;

var r = z(10);

console.log(r);

function squareF(x) { return x * x; }

var q = squareF(10);

console.log(q);

var sq = squareF;

console.log("sq: " + sq);

console.log("sq(12): " + sq(12));

console.log(foo(3));

Type binding of variable

How specified? explicit vs implicit

When bound? static vs dynamic

an explicit declaration is a statement in a program that lists variable names and specifies that

they are a particular type

an implicit declaration is a means of associating variables with types

through default conventions, rather than declaration statements

In implicit typing, all constants, variables and arrays beginning with the letters I, J, K, L, M, or N are automatically taken to be of type INTEGER.

Constants, variables and arrays beginning with all other letters are assumed to be REAL.

Thus, with implicit typing, the variable COUNT is REAL whilst the variable KOUNT is an INTEGER.

Implicit typing can be overridden with explicit type declaration.

source: http://www.obliquity.com/computer/fortran/datatype.html

Fortran: static types, implicitly declared

$a : scalar (string or numeric value)#a : array%a : hash structure

Perl: implicitly declared with different name spaces

Variables and Expressions (C)

#include <stdio.h>

/* print Fahrenheit-Celsius table for fahr = 0, 20, ..., 300 */int main() { int fahr, celsius; int lower, upper, step; lower = 0; /* lower limit of temperature scale */ upper = 300; /* upper limit */ step = 20; /* step size */ fahr = lower; while (fahr <= upper) { celsius = 5 * (fahr - 32) / 9; printf("%d\t%d\n", fahr, celsius); fahr = fahr + step; } return 0;}

static types, explicitly declared

type inference: implicit type declaration using context

Languages with type inferenceMLHaskellOCamlF#ScalaVisual BASIC 9.0+Go

def widthOfLength(s: String) = s.length.toString.length

val lines = Source.fromFile(args(0)).getLines.toList

val longestLine = lines.reduceLeft( (a, b) => if (a.length > b.length) a else b)

val maxWidth = widthOfLength(longestLine)

Scala: static types, inferred from context

dynamic type binding: variable is bound to type when it is assigned a value

Languages with dynamic type bindingRubyJavaScriptLispSchemePythonPHP

Variable Declaration (JS)

var i;var sum;

var i, sum;

var message = "hello";var i = 0, j = 0, k = 0;

for(var i = 0; i < 10; i++) console.log(i);for(var i = 0, j=10; i < 10; i++,j--) console.log(i*j);for(var p in o) console.log(p);

var i = 10;i = "ten";

list = [10.2, 3.5];list = 47;

JavaScript: dynamic type binding

Ruby

all variables are references

all data are objects (there is only one type)

any variable can reference an object

Disadvantages of dynamic typing

programs are less reliable: types not checked by compiler

cost of checking types at run time

next week: storage bindings and lifetime

Scope

the scope of a variable is the range of statements in which the variable is visible

a variable is local in a program unit or block if it is declared there

the non-local variables are those that are visible but not declared in a program

unit

class ChecksumAccumulator { private var sum = 0 def add(b: Byte): Unit = { sum += b } def checksum(): Int = { return ~(sum & 0xFF) + 1 }}

Scala: variable sum is non-local for methods add and checksum

static scoping: scope of variable can be statically determined

nested scopes: Ada, JavaScript, Scheme, Scala, F#, Python

non-nested scopes: C-based languages

function big() { function sub1() { var x = 7; sub2(); } function sub2() { var y = x; } var x = 3; sub1();}

static scoping in JavaScript

Variable Scope (JS)

var scope = "global"; // Declare a global variablefunction checkscope() { var scope = "local"; // Declare a local variable with the same name return scope; // Return the local value, not the global one}checkscope() // => "local"

Variable Scope (JS)

scope = "global"; // Declare a global variable, even without var.function checkscope2() { scope = "local"; // Oops! We just changed the global variable. myscope = "local"; // This implicitly declares a new global variable. return [ scope, myscope ]; // Return two values.}checkscope2() // => ["local", "local"]: has side effects!

scope // => "local": global variable has changed.myscope // => "local": global namespace cluttered up.

Nested Functions (JS)

var scope = "global scope"; // A global variablefunction checkscope() { var scope = "local scope"; // A local variable function nested() { var scope = "nested scope"; // A nested scope of local variables return scope; // Return the value in scope here } return nested();}checkscope() // => "nested scope"

function hypotenuse(a, b) { function square(x) { return x * x; } return Math.sqrt(square(a) + square(b));}

if (list[i] < list[j]) { int temp; temp = list[i]; list[i] = list[j]; list[j] = temp;}

block: sections in which allocation of storage for variables is allocated

void sub() { int count; ... while (...) { int count; count++; ... } ...}Java and C# do not allow

shadowing of variables

def printMultiTable() { var i = 1 // only i in scope here while (i <= 10) { var j = 1 // both i and j in scope here while (j <= 10) { val prod = (i * j).toString // i, j, and prod in scope here var k = prod.length // i, j, prod, and k in scope here while (k < 4) { print(" ") k += 1 } print(prod) j += 1 } // i and j still in scope; prod and k out of scope println() i += 1 } // i still in scope; j, prod, and k out of scope}

block scope in Scala:order of declaration

matters

Function Scope and Hoisting (JS)

function test(o) { var i = 0; // i is defined throughout function if (typeof o == "object") { var j = 0; // j is defined everywhere, not just block for ( var k = 0; k < 10; k++) { // k is defined everywhere, not just loop console.log(k); // print numbers 0 through 9 } console.log(k); // k is still defined: prints 10 } console.log(j); // j is defined, but may not be initialized}

JavaScript does not have block scope!

Use Before Declaration

var scope = "global";function f() { console.log(scope); // Prints "undefined", not "global" var scope = "local"; // Variable initialized here, but defined everywhere console.log(scope); // Prints "local"}

function f() { var scope; // Local variable is declared at the top of the function console.log(scope); // It exists here, but still has "undefined" value scope = "local"; // Now we initialize it and give it a value console.log(scope); // And here it has the value we expect}

let val name1 = expression1 ... val namen = expressionnin expressionend;

let val top = a + b val bottom = c - din top / bottomend;

let binding in ML

Describing Static Name Binding Rules

module names

imports include/Delftnamespaces Module Entity Propertyrules

Module(x, _) : defines Module x scopes Entity Entity(x, _) : defines Entity x of type Type(x) scopes Property Property(x, t) : defines Property x of type t Type(x) : refers to Entity x refers to Entity "String" refers to Entity "Int"

NaBL: Spoofax Name Binding Language

module blog

imports user entity BlogPosting { name : String poster : User body : String blog : Blog title : String}

entity Blog { title : String author : Blog}

entity User { name : String}

Reading & Programming in Week 2

Reading: Sebesta

Chapter 5: Names, Bindings, Scopes

Week 3: Dynamic Binding & Storage

WebLab:

C tutorialJavaScript tutorialMore Scala tutorial

Grammars and regular expressions