λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

University of California, Berkeley/ElectricalEngineering & ComputerSciences

Interpreters

Review : Tail Recursion

- An expressio in a tail context is evaluated a sthe last step the function call

- Function calls in a tail context are called tail calls

- If all recursive calls are in tail contexts, we say that function is tail recursive

Review : Writing Tail Recursive Functions

1. Identify recursive calls that are not in a tail context

2. Create a helper function with arguments to accumulate the computation that prevents if from being tail recursive

Example : Length of Linked List

Goal : Write a function that takes in a list and returns the length of the list. Make sure it is tail recursive.

 

Translation

problem : computers can only understand one language, binary ( 0s and 1s )

solution : programming languages, Languages like Python, Java, C etx are translated to 0s and 1s

This translation step comes in a couple forms :

compiled ( pre-translated ) _ translate all at once and run later

Interpreted ( translated on-the-fly ) _ translated while the programs is running

Interpreters

An interpreter does 3 things :

- Reads input from user in a specific programming language

- Translates input to be coputer readable and evaluates the result

- Prints the result for the user

There are two languages involved :

- Implemented language _ this is the language the user types in

- Implementation language _ this is the language interpreter is implemented in 

Implemented language is translated into the Implementation language ( in our case, implement Scheme to Python )

Read - Eval - Print Loop ( REPL )

input string : Read -> expression : Eval -> value : Print : output string -> loop

Reading Input

Lexical Analysis ( Lexer ) : turning the input into a collection of tokens

- A token : single input of the input string, ex. literals, names, keywords, delimiters

Syntactic Analysis ( Parser ) : turning tokens into a representation of the expressio in the implementing language

Representing Scheme Primitive Expressions

Self-Evaluating expression : use Python booleans and Python numbers

Symbols : use Python strings

Representing Combinations

: Combinations are just Scheme lists containing an operator and operands

Python Pairs

: To accurately represent Scheme combinations as linked lists, let's write a Pair class in Python

: There is one instance of nil. No other instances can be created

Reading Combinations

Special case : quote

- Recall that the quote special form can be invoked in two ways : ( quote < expr > ) '< expr >

- The special ' syntax gets converted by the reader into a qupte expression, which is a list with 2 elements

Eval

Evaluating Expression 

: Rules for evaluating an expression depends on the expression's type.

: Types of Scheme expressions _ self-evaluating expressions, symbols, call expressions, special form expressions

: Eval Takes in one arguemnt besides the expression itself _ the current environment

Frames and Environments

- When evaluating expressions, the current environment consists of the current frame, its parent frame, and all its ancestor frames until the Global Frame.

Frames in our interpreter

- Frames are represented in our interpreter as instances of the Frame class

- Each Frame instance has two instance attributes :

 1. bindings : a dictionary that binds Sheme symbols ( Python strings ) to Scheme values 

 2. parent : the parent frame, another Frame instance

Evaluating primitive expressions

- self-evaluating expressions : These expressions evaluate to themselves

- symbols :

 1. Look in the current frame for the symbol. If it is found return the value bound to it.

 2. If it is not found in the current frame, look in the parent frame. If it is not found in the parent frame, look in its parent frame, and so on.

 3. If the global frame is reached and the name is not found, raise a SchemeError.

Evaluating Combinations

( < operator > < operand 1 > < operand 2 > )

: The operator of a combination tells us whether it is a special form expression or a call expression

- If the operator is a symbol and is found in the dictionary of special forms, the combination is a special form

( each special form has special rules for evaluation )

Types of Procedures

- A built-in procedure is a procedure that is predefined in our Scheme interpreter. 

 ( ex. +, list, modulo, etc )

- A user-defined procedure is a procedure defined by the user, either with a lambda expressio or a define expression.

Built-In procedures

Applying built-in procedures

: call the Python function that implements the built-in procedure on the arguments

User-Defined procedures

: applying user-defined procedures

step 1. open a new frame whose parent is the parent frame of the procedure being applied

step 2. bind the formal parameters of the procedure to the arguments in the new frame

step 3. evaluate the body of the procedure in the new frame

The evaluator

: the evaluator consist of two mutually-recursive components

Evaluator

-   Eval

Base cases : self-evaluating expressions, look up values bound to symbols

Recursive cases : Eval ( operator ), Eval ( o ) for each operand o, Apply ( proc, args ), Evale (expr ) for expression expr in body of special form

-   Apply

Base cases : Built-in procedures

Recursive cases : Eval ( body ) of user defined procedures

Counting eval / apply calls : built-in procedures

: how many calls to eval and apply are made in order to evaluate this expression ?

Counting eval / apply calls : user-defined procedures

: how many calls to eval and apply are made in order to evaluate the second expression ?

'University of California, Berkeley > ElectricalEngineering & ComputerSciences' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

Macros  (0) 2019.08.02
Interpreters lab  (0) 2019.08.01
More Scheme  (0) 2019.07.31
Scheme  (0) 2019.07.30
Week 6  (0) 2019.07.30