CMPE 152: Compiler Design March 7 Class Meeting

Slides:



Advertisements
Similar presentations
CS 152: Programming Language Paradigms April 9 Class Meeting Department of Computer Science San Jose State University Spring 2014 Instructor: Ron Mak
Advertisements

CS 153: Concepts of Compiler Design September 2 Class Meeting Department of Computer Science San Jose State University Fall 2015 Instructor: Ron Mak
CS 153: Concepts of Compiler Design September 9 Class Meeting Department of Computer Science San Jose State University Fall 2015 Instructor: Ron Mak
CS 153: Concepts of Compiler Design October 5 Class Meeting Department of Computer Science San Jose State University Fall 2015 Instructor: Ron Mak
CS 152: Programming Language Paradigms April 2 Class Meeting Department of Computer Science San Jose State University Spring 2014 Instructor: Ron Mak
CS 153: Concepts of Compiler Design September 16 Class Meeting Department of Computer Science San Jose State University Fall 2015 Instructor: Ron Mak
Implementing Subprograms What actions must take place when subprograms are called and when they terminate? –calling a subprogram has several associated.
CS 153: Concepts of Compiler Design September 21 Class Meeting Department of Computer Science San Jose State University Fall 2015 Instructor: Ron Mak
CS 153: Concepts of Compiler Design October 7 Class Meeting Department of Computer Science San Jose State University Fall 2015 Instructor: Ron Mak
CS 153: Concepts of Compiler Design October 10 Class Meeting Department of Computer Science San Jose State University Fall 2015 Instructor: Ron Mak
CS 153: Concepts of Compiler Design September 30 Class Meeting Department of Computer Science San Jose State University Fall 2015 Instructor: Ron Mak
CS 152: Programming Language Paradigms April 7 Class Meeting Department of Computer Science San Jose State University Spring 2014 Instructor: Ron Mak
CCSA 221 Programming in C CHAPTER 11 POINTERS ALHANOUF ALAMR 1.
CS 153: Concepts of Compiler Design October 12 Class Meeting Department of Computer Science San Jose State University Fall 2015 Instructor: Ron Mak
CS 153: Concepts of Compiler Design September 23 Class Meeting Department of Computer Science San Jose State University Fall 2015 Instructor: Ron Mak
CS 152: Programming Language Paradigms May 12 Class Meeting Department of Computer Science San Jose State University Spring 2014 Instructor: Ron Mak
CS 153: Concepts of Compiler Design September 28 Class Meeting Department of Computer Science San Jose State University Fall 2015 Instructor: Ron Mak
Lecture 9 Symbol Table and Attributed Grammars
CS 432: Compiler Construction Lecture 9
CS 153: Concepts of Compiler Design September 14 Class Meeting
Run-Time Environments Chapter 7
Constructing Precedence Table
CS 326 Programming Languages, Concepts and Implementation
CS 153: Concepts of Compiler Design October 17 Class Meeting
CS 153: Concepts of Compiler Design October 5 Class Meeting
CS 153: Concepts of Compiler Design September 7 Class Meeting
CS 153: Concepts of Compiler Design October 3 Class Meeting
CS 153: Concepts of Compiler Design November 28 Class Meeting
CMPE 152: Compiler Design December 5 Class Meeting
CMPE 152: Compiler Design February 6 Class Meeting
CMPE 152: Compiler Design September 25 Class Meeting
Implementing Subprograms
CMPE 152: Compiler Design September 4 Class Meeting
CS 3304 Comparative Languages
CMPE 152: Compiler Design August 30 Class Meeting
CMPE 152: Compiler Design September 18 Class Meeting
CMPE 152: Compiler Design September 13 Class Meeting
CMPE 152: Compiler Design October 2 Class Meeting
CMPE 152: Compiler Design October 4 Class Meeting
CMPE 152: Compiler Design September 11/13 Lab
CMPE 152: Compiler Design October 4 Class Meeting
CMPE 152: Compiler Design August 21/23 Lab
CMPE 152: Compiler Design September 20 Class Meeting
CMPE 152: Compiler Design September 27 Class Meeting
CS 153: Concepts of Compiler Design November 6 Class Meeting
UNIT V Run Time Environments.
CS 432: Compiler Construction Lecture 11
CMPE 152: Compiler Design February 28 Class Meeting
CMPE 152: Compiler Design January 29 Class Meeting
CMPE 152: Compiler Design February 12 Class Meeting
CMPE 152: Compiler Design February 7 Class Meeting
CMPE 152: Compiler Design February 21/26 Lab
Symbol Table 薛智文 (textbook ch#2.7 and 6.5) 薛智文 96 Spring.
Run Time Environments 薛智文
CMPE 152: Compiler Design February 28 / March 5 Lab
COMPILERS Semantic Analysis
CMPE 152: Compiler Design February 21 Class Meeting
CMPE 152: Compiler Design February 26 Class Meeting
CMPE 152: Compiler Design March 7 Class Meeting
CMPE 152: Compiler Design March 5 Class Meeting
CMPE 152: Compiler Design April 16 Class Meeting
Implementing Subprograms
CMPE 152: Compiler Design March 19 Class Meeting
CMPE 152: Compiler Design March 7/12 Lab
CMPE 152: Compiler Design May 2 Class Meeting
CMPE 152: Compiler Design August 27 Class Meeting
CMPE 152: Compiler Design September 17 Class Meeting
CMPE 152: Compiler Design February 7 Class Meeting
CMPE 152: Compiler Design September 26 Class Meeting
CMPE 152: Compiler Design September 19 Class Meeting
Presentation transcript:

CMPE 152: Compiler Design March 7 Class Meeting Department of Computer Engineering San Jose State University Spring 2019 Instructor: Ron Mak www.cs.sjsu.edu/~mak

The Interpreter The back end executes the source program. Chapter 12 The Interpreter The back end executes the source program. Uses the symbol tables and the parse trees built by the front end parser. One symbol table per main program, procedure, and function for that routine’s local identifiers. The symbol table is pointed to by the routine name’s symbol table entry.

The Interpreter, cont’d One parse tree per main program, procedure, and function. For that routine’s compound statement. Pointed to by the symbol table entry for the routine’s name. The interpreter never sees the original source program. Only the symbol tables and parse trees.

Runtime Memory Management The interpreter must manage the memory that the source program uses during run time. Up until now, we’ve used the hack of storing values computed during run time into the symbol table. Why is this a bad idea? This will fail miserably if the source program has recursive procedure and function calls.

Symbol Table Stack vs. Runtime Stack The front end parser builds symbol tables and manages the symbol table stack as it parses the source program. The parser pushes and pops symbol tables as it enters and exits nested scopes. The back end executor manages the runtime stack as it executes the source program. The executor pushes and pops activation records as it calls and returns from procedures and functions. These are similar concepts, so don’t confuse them!

Reminders A VARIABLE node in the parse tree contains a reference to the variable name’s symbol table entry. Set in the front end by method VariableParser::parse() The method that takes two parameters. A symbol table entry contains a reference to its parent symbol table. The symbol table that contains the entry.

Reminders, cont’d Each symbol table has a nesting level field. Therefore, at run time, for a given VARIABLE node, the executor can determine the nesting level of the variable.

Runtime Activation Records An activation record (AKA stack frame) maintains information about the currently executing routine a procedure a function the main program itself

Runtime Activation Records, cont’d In particular, an activation record contains the routine’s local memory. values of local variables values of formal parameters This local memory is a memory map. Key: The name of the local variable or formal parameter. Value: The current value of the variable or parameter. Local memory is a hash table!

Runtime Activation Records, cont’d PROGRAM main1; PROCEDURE proc2a; PROCEDURE proc3; BEGIN ... END; BEGIN {proc2a} proc3; PROCEDURE proc2b; proc2a; BEGIN {main1} proc2b; END. In this example, the names of the routines indicate their nesting levels. AR: proc3 Call a routine: Push its activation record onto the runtime stack. Return from a routine: Pop off its activation record. AR: proc2a AR: proc2b AR: main1 RUNTIME STACK main1  proc2b  proc2a  proc3

Runtime Access to Local Variables PROGRAM main1; VAR j : integer; PROCEDURE proc2b; BEGIN j := 14; END; BEGIN {main1} j := 55; proc2b; END. Accessing local values is simple, because the currently executing routine’s activation record is on top of the runtime stack. AR: proc2b j 14 AR: main1 j 55 main1  proc2b RUNTIME STACK

Runtime Access to Nonlocal Variables PROGRAM main1; VAR i, j : integer; PROCEDURE proc2a; VAR m : integer; PROCEDURE proc3; VAR j : integer BEGIN j := i + m; END; BEGIN {proc2a} i := 11; m := j; proc3; PROCEDURE proc2b; VAR j, m : integer; j := 14; m := 5; proc2a; BEGIN {main1} i := 33; j := 55; proc2b; END. Each parse tree node for a variable contains the variable’s symbol table entry as its VALUE attribute. Each symbol table entry has the variable’s nesting level n. To access the value of a variable at nesting level n, the value must come from the topmost activation record at level n. Search the runtime stack from top to bottom for the topmost activation record at level n. AR: proc3 j 66 AR: proc2a m 55 AR: proc2b j m 14 5 AR: main1 i j 33 11 55 RUNTIME STACK main1  proc2b  proc2a  proc3

The Runtime Display A vector called the runtime display makes it easier to access nonlocal values. This has nothing to do with video displays!

The Runtime Display, cont’d Element n of the display always points to the topmost activation record at scope nesting level n on the runtime stack. The display must be updated as activation records are pushed onto and popped off the runtime stack.

The Runtime Display, cont’d Whenever a new activation record at level n is pushed onto the stack, it links to the previous topmost activation record at level n. This link helps to restore the runtime stack as activation records are popped off when returning from procedures and functions.

Runtime Access to Nonlocal Variables PROGRAM main1; VAR i, j : integer; PROCEDURE proc2a; VAR m : integer; PROCEDURE proc3; VAR j : integer BEGIN j := i + m; END; BEGIN {proc2a} i := 11; m := j; proc3; PROCEDURE proc2b; VAR j, m : integer; j := 14; m := 5; proc2a; BEGIN {main1} i := 33; j := 55; proc2b; END. AR: proc3 j AR: proc2a m 3 2 AR: proc2b j m 1 RUNTIME DISPLAY AR: main1 i j The runtime display allows faster access to nonlocal values. RUNTIME STACK main1  proc2b  proc2a  proc3

Recursive Calls PROGRAM main1 FUNCTION func2 FUNCTION func3 PROCEDURE proc2 PROCEDURE proc3 AR: proc2 AR: func3 AR: proc3 AR: func2 AR: proc3 3 2 AR: proc2 1 AR: main1 RUNTIME DISPLAY RUNTIME STACK main1  proc2  proc3  func2  proc3  func3  proc2

Allocating an Activation Record The activation record for a routine (procedure, function, or the main program) needs one or more “data cells” to store the value of each of the routine’s local variables and formal parameters. TYPE arr = ARRAY[1..3] OF integer; ... PROCEDURE proc(i, j : integer; VAR x, y : real; VAR a : arr; b : arr); VAR k : integer; z : real; AR: proc i x k j y z a b

Allocating an Activation Record, cont’d TYPE arr = ARRAY[1..3] OF integer; ... PROCEDURE proc(i, j : integer; VAR x, y : real; VAR a : arr; b : arr); VAR k : integer; z : real; AR: proc i x k j y z a b Obtain the names and types of the local variables and formal parameters from the routine’s symbol table.

Allocating an Activation Record, cont’d TYPE arr = ARRAY[1..3] OF integer; ... PROCEDURE proc(i, j : integer; VAR x, y : real; VAR a : arr; b : arr); VAR k : integer; z : real; AR: proc i x k j y z a b Whenever we call a procedure or function: Create an activation record. Push the activation record onto the runtime stack. Allocate the memory map of data cells based on the symbol table. No more storing runtime values in the symbol table!

Passing Parameters During a Call PROGRAM main; TYPE arr = ARRAY[1..3] OF integer; VAR index, count : integer; epsilon, delta : real; triplet : arr; PROCEDURE proc(i, j : integer; VAR x, y : real; VAR a : arr; b : arr); ... BEGIN {main} proc(index + 2, count, epsilon, delta, triplet, triplet); END. AR: proc i x 12 j y 84 a b 10 20 30 index count epsilon delta AR: main triplet 10 84 -3.1 0.07 20 30 RUNTIME STACK Value parameters: A copy of the value is passed. VAR parameters: A reference to the actual parameter is passed.

Executing Procedure and Function Calls Chapter 12

Class CallDeclaredExecutor Method execute() Create a new activation record based on the called routine’s symbol table. Execute the actual parameter expressions. Initialize the memory map of the new activation record. The symbol table entry of the name of the called routine points to the routine’s symbol table. Copy values of actual parameters passed by value. Set pointers to actual parameters passed by reference.

Class CallDeclaredExecutor cont’d Method execute() cont’d Push the new activation record onto the runtime stack. Access the root of the called routine’s parse tree. The symbol table entry of the name of the called routine points to the routine’s parse tree. Execute the routine. Pop the activation record off the runtime stack.

Class CallDeclaredExecutor Method execute_actual_parms() Obtain the formal parameter cell in the new activation record: wci::backend::interpreter::executors::CallDeclaredExecutor.cpp Cell formalCell = newAr.getCell(formalId.getName());

Class CallDeclaredExecutor Method execute_actual_parms() cont’d Value parameter: wci::backend::interpreter::executors::CallDeclaredExecutor.cpp Object cell_value = expression_executor.execute(actual_node); assignment_executor.assign_value(actual_node, formal_id,                                  formal_cell, formal_typespec,                                  cell_value, value_typespec); Set a copy of the value of the actual parameter into the memory cell for the formal parameter.

Class CallDeclaredExecutor Method executeActualParms() cont’d VAR (reference) parameter: Method ExpressionExecutor.executeVariable() executes the parse tree for an actual parameter and returns the reference to the value. wci::backend::interpreter::executors::CallDeclaredExecutor.cpp Cell *actual_cell =     expression_executor.execute_variable(actual_node); formal_cell->set_value(actual_cell); Set a reference to the actual parameter into the memory cell for the formal parameter.

Class CellImpl Since a memory cell can contain a value of any type or a reference, we implement it simply as a boost::any. wci::Object.h #include <boost/any.hpp> #define Object boost::any wci::backend::interpreter::memoryimpl::CellImpl.cpp Object CellImpl::get_value() const { return cell_value; } void CellImpl::set_value(Object new_value) { cell_value = new_value; }

Runtime Error Checking Range error Assign a value to a variable with a subrange type. Verify the value is within range Not less than the minimum value and not greater than the maximum value. Method StatementExecutor.check_range() Division by zero error Before executing a division operation, check that the divisor’s value is not zero.

Pascal Interpreter Now we can execute entire Pascal programs! Demo

Midterm Review: Question 1 The parser builds data structures consisting of symbol table entry objects (STEO) and type specification objects (TSO). How are these structures used at compile time? STEO: Store information about locally-declared identifiers. TSO: Represent type information. Both: Assign types to variables. Both: Do type checking in statements and expressions.

Midterm Review: Question 1, cont’d How does the interpreter use these structures at run time? STEO: Create the memory map for each activation record that’s pushed onto the runtime stack. STEO: Get the values of defined and enumeration constants. TSO: Do runtime range checking for subranges. TSO: Get the data types of array indexes and elements.

Midterm Review: Question 2 How does the symbol table stack … … allow a variable declared in an enclosing scope to be redeclared in the local scope? Push a new symbol table onto the symbol table stack for the local scope. Enter the variable’s name into the local table. … prevent a variable already declared in the local scope from being redeclared in the local scope? First check the local symbol table to see whether the variable’s name is already entered into the table.

Midterm Review: Question 2, cont’d How does the symbol table stack … … allow two record types defined in the same procedure to declare fields with the same names? Push a separate symbol table for each record type onto the symbol table stack when the parser is parsing the record type specification. Pop it off when the parser is done parsing the specification.

Midterm Review: Question 3 Explain the role of synchronization sets during parsing. Each synchronization set tells the parser what tokens to look for at a particular point of the source program. Some members of the set are tokens that are syntactically valid at that point, and other members are there to allow the parser to recover from syntax errors.

Midterm Review: Question 4 Some programming languages use parentheses to enclose array subscripts and to enclose arguments to function calls. Suppose Pascal did the same. Consider the assignment statement: x := arr(i, 2*j) Describe how the Pascal parser could (or could not) determine whether it is parsing a call to function arr or an access to an element of array arr.

Midterm Review: Question 4, cont’d x := arr(i, 2*j) By the time the parser is parsing the assignment statement, it would have already parsed the declaration of arr as either an array or a function. Therefore, when the parser encounters arr in the assignment statement, it looks in the symbol table to see how arr was declared.

Midterm Review: Question 5 Suppose Pascal has an exponentiation operator **, so that n**4 represents the mathematical expression n4. Exponentiation has a higher operator precedence level than the multiplicative operators. Therefore, n**i*j is evaluated as (n**i)*j. Furthermore, exponentiation is right-associative, so that n**i**j**k is evaluated as n**(i**(j**k)).

Midterm Review: Question 5 What modifications to the expression, simple expression, term, and factor syntax diagrams are required to accommodate the ** operator? Redraw only the diagrams that change. (Not all the diagrams may need to change, and you may need to add new diagrams.)

Midterm Review: Question 5, cont'd

Midterm Review: Question 5, cont'd

Midterm Review: Question 5, cont'd Draw the parse tree for the assignment statement r := a**i*j**(n-1)**k You may assume the existence of a node type for the ** operator. r := (a**i) * (j** ((n-1)**k)) := r * ** ** a i j ** - k n 1

Midterm Review: Question 6 Given the Pascal program structure and call chain: PROGRAM main; PROCEDURE procA; PROCEDURE procB; PROCEDURE procC; PROCEDURE procD; PROCEDURE procE; main  procD  procE  procE  procA  procB  procC  procB  procC  procD AR: main AR: procD AR: procE AR: procA AR: procB AR: procC RUNTIME STACK Draw the runtime stack, activation records, and runtime display at the end of the call chain. Show the display pointers and the activation record links. 1 2 3 RUNTIME DISPLAY 4

Midterm Review: Question 7 Suppose Pascal had a LOOP-AGAIN statement. For example: Like the REPEAT-UNTIL statement, the LOOP-AGAIN statement can contain any number of statements that will be repeatedly executed. Any one or more (or none) of the contained statements can be a WHEN-LEAVE statement which will cause a break out of the loop if its Boolean expression evaluates to true. A WHEN-LEAVE statement can only appear inside of a LOOP-AGAIN statement. LOOP k := k + 1; WHEN k > 10 LEAVE; j := 2*k AGAIN

Midterm Review: Question 7, cont'd Draw syntax diagrams for the LOOP-AGAIN and WHEN-LEAVE statements. You may assume that diagrams already exist for “statement” and “expression” and that LOOP, AGAIN, WHEN, and LEAVE are reserved words. LOOP k := k + 1; WHEN k > 10 LEAVE; j := 2*k AGAIN

Midterm Review: Question 7, cont'd Using only the existing node types defined in class ICodeNodeTypeImpl, draw the parse tree for the LOOP-AGAIN statement shown on the previous page. LOOP k := k + 1; WHEN k > 10 LEAVE; j := 2*k AGAIN