Lecture 19
Implementing Programming Languages
Programming Languages
UW CSE 341 - Autumn 2022
Updates
Implement-A-Language: Standard Workflow
"(fun x -> x + x) 4"
concrete syntax (string / file contents)
Type-Checking
Possible type
errors / warnings
Call
Function
+
Constant
4
x
x
x
Var
Var
abstract syntax tree (AST)
Rest of Implementation
AST that type-checks
Parsing
Possible syntax
errors / warnings
Workflow, In Words
Interpreter vs. Compiler
“Rest of implementation” takes AST and gives a way to “run the program”
Two fundamental approaches to implementing a language LBI (language being implemented)
Crucial to keep LBI, M, T straight
Reality can be more complex
Sermon: Languages Aren’t Their Implementations
Interpreter versus compiler versus combinations is about a particular language implementation, not the language definition
Implement-A-Language: Standard Workflow
"(fun x -> x + x) 4"
concrete syntax (string / file contents)
Parsing
Possible syntax
errors / warnings
Type-Checking
Possible type
errors / warnings
Rest of Implementation
AST that type-checks
Call
Function
+
Constant
4
x
x
x
Var
Var
abstract syntax tree (AST)
Skipping Parsing
(struct call …)
(struct function …)
(struct var …)
…
(call (function (list "x")
(add (var "x")(var "x")))
(const 4))
Call
Function
+
Constant
4
x
x
x
Var
Var
We’ve already done this for arithmetic!
M = Racket
LBI = arithmetic
Recap of our plan
Syntax Errors vs. Type Errors
Subtle but important distinction:
Syntax Errors
Lots of possible Racket values that make no sense in terms of LBI syntax
Okay to crash the interpreter in such cases
Do not test for these or try to handle them (that would be parser’s job)
Interpreter “return type”
Adding Booleans
As before, there are “syntax errors” we will just ignore:
But now there is also a new kind of error possible...
Dynamic Type Checking
Adding Variables
Adding Variables
Setting up the interpreter
Whole interpreter moves into the main helper function eval-under-env:
Top-level eval-exp makes initial call to helper with the empty environment
Grading detail: Do not move eval-under-env inside eval-exp; leaving it at top-level helps us grade. (Otherwise would be good style.)
Closures
Most interesting part of Homework 5 is implementing first-class functions
Again, we have been preparing for this all quarter 😉
First-class Functions
“Magic”: how do we use the right environment for lexical scope?
No magic really: closures just “remember” by storing the right environment!
To evaluate a function expression:
Calling Functions (call e1 e2)
The Cost of Closures
Free Variables Example
Free Variables Example
Computing Free Variables
Optional: compiling closures
Have now explained how an interpreter implements closures, but what about a compiler to a target language like C/assembly that does not have closures?
This compilation technique is called closure conversion. It’s cool. :)
Implementing LBI Macros
Remember how we are implementing languages
Remember what we know about macros
Implementing LBI Macros
With this set up, we can use PL M functions that return LBI ASTs as “LBI macros”
See code for examples.
Downside: