CS558 Programming Languages

Similar documents
CS558 Programming Languages

CS558 Programming Languages

CS558 Programming Languages. Winter 2013 Lecture 3

CS 330 Lecture 18. Symbol table. C scope rules. Declarations. Chapter 5 Louden Outline

Programming Languages Third Edition. Chapter 7 Basic Semantics

CS558 Programming Languages Winter 2018 Lecture 4a. Andrew Tolmach Portland State University

The SPL Programming Language Reference Manual

Semantic Analysis. Outline. The role of semantic analysis in a compiler. Scope. Types. Where we are. The Compiler Front-End

In Java we have the keyword null, which is the value of an uninitialized reference type

Chapter 5. Names, Bindings, and Scopes

CS558 Programming Languages

The role of semantic analysis in a compiler

CS321 Languages and Compiler Design I Winter 2012 Lecture 13

Closures. Mooly Sagiv. Michael Clarkson, Cornell CS 3110 Data Structures and Functional Programming


Topics Covered Thus Far CMSC 330: Organization of Programming Languages

The Compiler So Far. CSC 4181 Compiler Construction. Semantic Analysis. Beyond Syntax. Goals of a Semantic Analyzer.

Semantic Analysis. Outline. The role of semantic analysis in a compiler. Scope. Types. Where we are. The Compiler so far

CSE 307: Principles of Programming Languages

Short Notes of CS201

CS558 Programming Languages

Closures. Mooly Sagiv. Michael Clarkson, Cornell CS 3110 Data Structures and Functional Programming

CS201 - Introduction to Programming Glossary By

CMSC 330: Organization of Programming Languages

The PCAT Programming Language Reference Manual

Programmin Languages/Variables and Storage

Outline. Introduction Concepts and terminology The case for static typing. Implementing a static type system Basic typing relations Adding context

CSCE 314 Programming Languages. Type System

Topics Covered Thus Far. CMSC 330: Organization of Programming Languages. Language Features Covered Thus Far. Programming Languages Revisited

Attributes, Bindings, and Semantic Functions Declarations, Blocks, Scope, and the Symbol Table Name Resolution and Overloading Allocation, Lifetimes,

CS558 Programming Languages

Semantic Analysis and Type Checking

CS558 Programming Languages

Informal Semantics of Data. semantic specification names (identifiers) attributes binding declarations scope rules visibility

Lecture 7: Type Systems and Symbol Tables. CS 540 George Mason University

Programming Languages Third Edition. Chapter 10 Control II Procedures and Environments

THE GOOD, BAD AND UGLY ABOUT POINTERS. Problem Solving with Computers-I

Chapter 5 Names, Binding, Type Checking and Scopes

CS558 Programming Languages

G Programming Languages - Fall 2012

CS 360 Programming Languages Interpreters

CS 430 Spring Mike Lam, Professor. Data Types and Type Checking

CS558 Programming Languages. Winter 2013 Lecture 4

CSC 533: Organization of Programming Languages. Spring 2005

Anatomy of a Compiler. Overview of Semantic Analysis. The Compiler So Far. Why a Separate Semantic Analysis?

Class Information ANNOUCEMENTS

Semantic Analysis. Lecture 9. February 7, 2018

Names, Bindings, Scopes

Design Issues. Subroutines and Control Abstraction. Subroutines and Control Abstraction. CSC 4101: Programming Languages 1. Textbook, Chapter 8

CMSC 330: Organization of Programming Languages

CMSC 330: Organization of Programming Languages. Memory Management and Garbage Collection

CPSC 3740 Programming Languages University of Lethbridge. Data Types

CPSC 213. Introduction to Computer Systems. Instance Variables and Dynamic Allocation. Unit 1c

Name, Scope, and Binding. Outline [1]

CS 536 Introduction to Programming Languages and Compilers Charles N. Fischer Lecture 11

CMSC 330: Organization of Programming Languages

Compilers. Type checking. Yannis Smaragdakis, U. Athens (original slides by Sam

Names, Scope, and Bindings

Weeks 6&7: Procedures and Parameter Passing

CS321 Languages and Compiler Design I. Winter 2012 Lecture 2

The Compiler So Far. Lexical analysis Detects inputs with illegal tokens. Overview of Semantic Analysis

CPSC 213. Introduction to Computer Systems. Winter Session 2017, Term 2. Unit 1c Jan 24, 26, 29, 31, and Feb 2

SEMANTIC ANALYSIS TYPES AND DECLARATIONS

Advances in Programming Languages: Regions

1 Lexical Considerations

Heap, Variables, References, and Garbage. CS152. Chris Pollett. Oct. 13, 2008.

Lecture Notes on Memory Management

Static Semantics. Lecture 15. (Notes by P. N. Hilfinger and R. Bodik) 2/29/08 Prof. Hilfinger, CS164 Lecture 15 1

Functional Programming. Pure Functional Programming

SE352b: Roadmap. SE352b Software Engineering Design Tools. W3: Programming Paradigms

CSE 504. Expression evaluation. Expression Evaluation, Runtime Environments. One possible semantics: Problem:

Lecture 13: Complex Types and Garbage Collection

CS 241 Honors Memory

Static Semantics. Winter /3/ Hal Perkins & UW CSE I-1

Syntax Errors; Static Semantics

Names, Scope, and Bindings

Lexical Considerations

Run-time Environments

Run-time Environments

CMSC 330: Organization of Programming Languages. Ownership, References, and Lifetimes in Rust

Lecture 14. No in-class files today. Homework 7 (due on Wednesday) and Project 3 (due in 10 days) posted. Questions?

G Programming Languages - Fall 2012

INF 212 ANALYSIS OF PROG. LANGS FUNCTION COMPOSITION. Instructors: Crista Lopes Copyright Instructors.

CSE 307: Principles of Programming Languages

Lecture Notes on Memory Management

Lecture 16: Static Semantics Overview 1

CS321 Languages and Compiler Design I. Fall 2013 Week 8: Types Andrew Tolmach Portland State University

Runtime. The optimized program is ready to run What sorts of facilities are available at runtime

CS1622. Semantic Analysis. The Compiler So Far. Lecture 15 Semantic Analysis. How to build symbol tables How to use them to find

Lexical Considerations

Compiler construction

Computer Science Department Carlos III University of Madrid Leganés (Spain) David Griol Barres

PIC 10A Pointers, Arrays, and Dynamic Memory Allocation. Ernest Ryu UCLA Mathematics

Variables. Substitution

Project Compiler. CS031 TA Help Session November 28, 2011

Names, Scopes, and Bindings. CSE 307 Principles of Programming Languages Stony Brook University

Scope, Functions, and Storage Management

Qualifying Exam in Programming Languages and Compilers

Compiler Construction

Outline. Java Models for variables Types and type checking, type safety Interpretation vs. compilation. Reasoning about code. CSCI 2600 Spring

Transcription:

CS558 Programming Languages Winter 2017 Lecture 4a Andrew Tolmach Portland State University 1994-2017

Semantics and Erroneous Programs Important part of language specification is distinguishing valid from invalid programs Useful to define three classes of errors that make programs invalid Of course, even valid programs may not act as the programmer intended!

Static Errors Static errors can be detected before the program is run (at compile or pre-interpretation time) Includes lexical errors, syntactic errors, type errors, etc. Error checker can give precise feedback about erroneous location in source code Language semantics are usually defined only for programs that have no static errors

Checked Runtime Errors Checked runtime errors are violations that the language implementation is required to detect and report at runtime, in a clean way. E.g. in Scala or Java: division by 0, array bounds violations, dereferencing a null pointer Depending on language, might cause an error message + abort, or raise an exception (which in principle can be caught by program) Language semantics must specify what runtime errors are checked and how

Unchecked Runtime Errors Unchecked runtime errors are violations that the implementation does not have to detect. Subsequent behavior of the computation is arbitrary (language semantics typically silent about this) No fail-stop behavior: error might not be manifested until long after it occurs E.g. in C: division by 0, array bounds violations, dereferencing a null pointer Safe languages like Scala, Java, Python have no such errors!

Today: Binding, Scope, Storage Part of being a high-level language is letting the programmer name things: variables constants types functions classes modules fields operators... Generically, we call names identifiers An identifier binding makes an association between the identifier and the thing it names An identifier use refers to the thing named The scope of a binding is the part of the program where it can be used 6

Scala Example object Printer { def print(expr: Expr) : String = unparse(expr).tostring() } def unparse(expr: Expr) : SExpr = expr match { case Num(n) => SNum(n) case Add(l,r) => SList(SSym("+")::unparse(l)::unparse(r)::Nil) case Mul(l,r) => SList(SSym("*")::unparse(l)::unparse(r)::Nil) case Div(l,r) => SList(SSym("/")::unparse(l)::unparse(r)::Nil) } binding use keyword Identifier syntax is language-specific Usually unbounded sequence of alpha numeric symbol(?) Further rules/conventions for different categories Identifiers are distinct from keywords! Some identifiers are pre-defined 7

Names, values, variables Most languages let us bind variable names to memory cells containing values Name gives access to cell for read or update Many languages also let us bind names directly to (immutable) values computed by expressions Sometimes (confusingly) also called variables Scala var vs. val They let us share expressions to save repeated writing and, maybe, evaluation 8

Local Value Bindings expr ::= num expr + expr... (expr) id let id = expr in expr scope Add (let a = 8 + 5 in a * 3) + 3 Leta Num3 Add Mul binding use Num8 Num5 Vara Num3 9

Bound vs. Free A variable use x is bound if it appears in the scope of a binding for x Otherwise, it is free Bound and free are relative to an enclosing subexpression, e.g. a is bound in (let a = 8 + 5 in a * 3) but free in a * 3 We cannot evaluate a free variable 10

scopea scopeb Parallel Scopes Add (let a = 8 + 5 in a * 3) + (let b = 1 in b + 2) Leta Letb Add Mul Num1 Add Num8 Num5 Vara Num3 Varb Num2 What if both let s bind a? 11

Nested Scopes (let a = 8 + 5 in let b = a - 10 in a * b) + 2 Leta Add Num2 Add Letb scopea scopeb Mul Num8 Num5 Sub Vara Varb scopea scopea&b Vara Num10 12

scopea Shadowing Add (let a = 8 + 5 in let a = a - 10 in 36 + a) + 3 Leta Num3 Add Leta scopea Num8 Num5 Sub Add Vara Num10 Num36 Vara Nearest enclosing binding wins 13

Functions and parameters Consider adding functions with parameters to our expression language We give names to these parameters The scope of a parameter is the function body The value of each parameter is provided at the function call (or application ) site declaration AST (f x (+ x 3)) application AST (@ f (* 13 3)) { { function name formal parameter body 14 function name actual parameter

Function parameter scoping (f x (+ x 3)) Fundeff,x Add scopex Varx Num3

Function Name Scoping Typically, we want to allow functions to be recursive Scope of function s name includes its own body scopef letfun f x = if x = 0 then 1 else x*f(x-1) in f(42) 16

Mutually Recursive Definitions letrec f(x) = g(x + 1) and g(y) = f(y - 1) in f(2) + g(4) scopef,g Many earlier languages were designed to be compiled by a single pass through the source code and therefore use forward declarations void g (double y); /* declares g but doesn t define it */ void f(double x) { g(x+1.0); } void g(double y) { f(y-1.0); } /* definition is here */ C In some languages, all top-level definitions are (implicitly) treated as mutually recursive.

Dynamic Scope What should happen in the following program? letfun f(x) = x + y in f 42 How about this one? letfun f(x) = x + y in let y = 2 in f(42) One possible answer: let the value of y leak into f This is an example of dynamic scope Bad idea! 18 Why?

Static scope / Lexical scope Better if this program remains erroneous letfun f(x) = x + y in let y = 2 in f(42) Looking at a function declaration, we can always determine if and where a variable is bound without considering the dynamic execution of the program! Some scripting languages still use dynamic scope, but as programs get larger, its dangers become obvious 19

Re-using names What happens when the same name is bound twice in the same scope? If the bindings are to different kinds of things (e.g. types vs. variables), can often disambiguate based on syntax, so no problem arises (except maybe readability): type Foo = Int val Foo : Foo = 10 val Bar : Foo = Foo + 1 Scala Here we say that types and variables live in different name spaces If the bindings are in the same namespace, typically an error. But sometimes additional info (such as types) can be used to pick the right binding; this is called overloading

Named scopes: modules, classes Often, the construct that delimits a scope can itself has a name, allowing the programer to manage explicitly the visibility of the names inside it OCaml modules module Env = struct type env = (string * int) list let empty : env = [] let rec lookup (e:env) (k:string) : int =... end let e0 : Env.env = Env.empty in Env.lookup e0 "abc" Java classes class Foo { static int x; static void f(int x); } int z = Foo.f(Foo.x)

Semantics via Environments An environment is a mapping from names to their bindings The environment at a program point describes all the bindings in scope at that point Environment is extended when binding constructs are evaluated Environment is consulted to determine the meaning of names during evaluation

Environments for everything Environments can hold binding information for all kinds of names a variable name is (typically) bound to location [in the store] containing the variable a value (constant) name may be bound directly bound to the value [environment = store] a function name is bound to description of the function s parameters and body a type name is bound to a type description, including the layout of its values a class name is bound to a list of the class s content etc.

Variables and the Store In most imperative languages, variable names are bound to locations, which in turn contain values. So evaluating a variable declaration involves two things: 1. allocating a new store location (and perhaps initializing its contents) 2. creating a new binding from variable name to location In most languages, there are other ways to allocate storage too, such as explicit new operations or implicit boxing operations Simplistic store model: mutable map from locations to values Better models require distinguishing different classes of storage

Storage Lifetimes Typical computations use far more memory locations in total than they use at any one point So most language implementations support re-use of memory locations that are no longer needed Allocation Point Lifetime Deallocation Point time The lifetime of every object should cover all moments when the object is being used Otherwise, we get a memory safety bug

Storage Classes: Static Data Lifetime = Entire Execution Typically used for global variables and constants If language has no recursion, can also be used for function-local variables Fixed address known before program executes No runtime allocation/deallocation costs

Storage Classes: Stack Data Nested Lifetimes (last allocated is first deallocated) Typically used for function-local variables (and internal control data for function calls) Works because function call lifetimes also nest Allocation/deallocation are very cheap (just adjust the stack pointer) Produces good locality for caches, virtual memory

Storage Classes: Heap Data Arbitrary Lifetimes Typically used for explicitly allocated objects Some languages implicitly heap-allocate other data structures, e.g. bignums, closures, etc. Allocation/deallocation are relatively expensive Run-time library must decide where to allocate Deallocation can be done manually (risking memory bugs) or by a garbage collector

Scope, Lifetime, Memory Safety Lifetime and scope are closely connected For a language to be memory safe, it suffices to make sure that in-scope identifiers never point (directly or indirectly) to deallocated objects For stack-allocated local variables, this happens naturally Stack locations are deallocated only when function returns and its local variables go out of scope forever For heap data, easiest to enforce safety using a garbage collector (GC) GC typically works by recursively tracing all objects reachable from names that are currently in scope (or that might come back into scope later) Only unreachable objects are deallocated, making their locations available for future re-allocation

Explicit Deallocation Many older languages (notably C/C++) support explicit deallocation of heap objects Somewhat more efficient than GC char *foo() { char *p = malloc(100); free(p); return p;} But makes language unsafe: dangling pointer bug occurs if we deallocate an object that is still in use [unchecked runtime error] Converse problem: space leak bug occurs if we don t deallocate an unneeded object. Not a safety problem, but may unnecessarily make program run slower or crash with out of memory error