CS 152: Programming Language Paradigms Modules, Structs, Hashes, and Operational Semantics Prof. Tom Austin San José State University
Modules
Review Modules from HW 1 (in-class)
How do we organize code in Java? • Packages provide units of code • Keywords specify method access
In Java, keywords specify access • public • protected • no keyword (package access) • private
Java method access levels • public : everyone • protected : subclasses and code in the same package • no keyword (package access): code in the same package • private : only code in the current class
Organizing Code in Racket Racket organizes code in terms of imports and exports . • The library specifies which code is available to others by the provide keyword. – anything not named by provide is hidden. • If you want to use the library, you use the keyword require .
Organizing Code in Racket • Exports specify public values: (provide big-add) • Imports specify code dependencies: (require "big-num.rkt")
Structs and Hashes
Structs • Structures allow us to create more sophisticated data structures: (struct name ( field1 field2 … )) • Once we have a structure, we can destructure it with the match keyword to get at the contents. • <Example in class>
Hashes • Hashes are maps of key/value pairs. • Unlike Java, hashes are immutable. • <example in class>
Formal Semantics
Why do we need formal semantics?
Everyone knows what an if statement does, right? if true then x = 1 At the end of this code else snippet, the value of x will be 1 x = 0
Everyone knows what an if statement does, right? if false then x = 1 else At the end of this code snippet, the value of x will be 0 x = 0
Everyone knows what an if statement does, right? if 0 then Will x be set to 0, like in C/C++? x = 1 Will x be set to 1, else like in Ruby? x = 0 Or will it be an error, like in Java?
Everyone knows what an if statement does, right? x = if true Is assignment valid or an error? then 1 else 0
Formal semantics define how a language works concisely and with minimal ambiguity .
A Review of Compilers We don't care Lexer/ about source tokens Parser code Tokenizer lexing or parsing. Abstract Compiler Interpreter Syntax Tree (AST) Machine code Commands We don't care if we have a compiler or interpreter
A Review of Compilers We don't care Lexer/ about source tokens Parser code Tokenizer lexing or parsing. Abstract Compiler Interpreter Syntax Tree (AST) Machine code Commands We don't care if we have a compiler or interpreter
ASTs are the key to Abstract understanding a language Syntax Tree (AST)
Bool* Language e ::= expressions: true constant true | false constant false | if e conditional then e Despite appearances, these are really ASTs else e
Values in Bool* v ::= values: true constant true | false constant false
Formal Semantic Styles • Operational semantics – Big-step (or "natural") – Small-step (or "structural") • Axiomatic semantics • Denotational semantics
Formal Semantic Styles • Operational semantics – Big-step (or "natural") – Small-step (or "structural") • Axiomatic semantics • Denotational semantics
Operational semantics specify how expressions should be evaluated. There are two different approaches. Small-step semantics evaluate an expression until it is in normal form & cannot be evaluated any further.
In contrast, big-step operational semantics evaluate every expression to a value. Big-step rules tend to have a recursive structure.
Big-Step Evaluation Relation An expression e … … evaluates to … ⇓ e v … a value v .
Big-Step Evaluation Relation limits when the rule applies Preconditions ⇓ e v
Big-step semantics for Bool* B-IfTrue e1 ⇓ true e2 ⇓ v if e1 then e2 else e3 ⇓ v e1 ⇓ false e3 ⇓ v B-IfFalse if e1 then e2 else e3 ⇓ v v ⇓ v B-Value
Bool* big-step example true ⇓ true false ⇓ false if true ⇓ false then false false ⇓ false else true if (if true then false else true) then true ⇓ false else false
Converting our rules into code (in-class)
Bool* extension: numbers Users demand a new feature – numbers! We will add 3 new features: • Numbers, represented by n • succ , which takes a number and returns the next highest number. • pred , which takes a number and returns the next lowest number.
Extended Bool* Language e ::= true | false | if e then e else e | n Let's extend our | succ e semantics to handle these new language | pred e constructs
Lab: Write a Bool* Interpreter • Starter code is available on the course website • Extend Bool* with numbers, succ , and pred
Pop Quiz: Write operational semantics e ::= e and e | e or e | not e e ⇓ v | true | false v ::= true | false
Adding State to Semantics
SpartanLang e ::= !x dereferencing | v values | x:=e assignment | e;e sequence | e op e binary operations | if e then e conditionals else e end | while e do e end while loops
SpartanLang (continued) v ::= i integers | b booleans binary operators op ::= + | - | \ | * | < | > | <= | >=
Bool* vs. SpartanLang evaluation Bool* relation: e ⇓ v SpartanLang relation: ⇓ v, σ ' e, σ A "store", represented by the Greek letter sigma
The Store • A mapping of references to values • Roughly analogous to the heap in Java
Key store operations • σ (x) – get the value for reference x . • σ [x:=v] – create a copy of store σ , except … – reference x has value v .
Special syntax for references In languages like ML, references are accessed with special syntax: • x = ref 42 creates a new reference with value 42 and stores the reference in variable x. • x := 7 changes the value of the reference to 7. • !x – gets the value of the reference that x refers to.
HW 2: Write an Interpreter for SpartanLang. Details in Canvas
Recommend
More recommend