CONTEXT VM changes (from the SRM) // machine_types.h // type of 32 bit integers typedef int int_type; // type of 32 bit floats typedef float float_type; typedef float word_type; Instruction changes: Floating point versions of instructions: FADD, FSUB, FMUL, FDIV BFEQ, BFGEZ, BFGTZ, BFLEZ, BFLTZ, FLW, FSW, PFLT, RFLT FMUL and FDIV are 3 register operations FDIV does not do a modulo calculation Conversion instructions: CVT -- converts int to a float RND =- rounds float to an int FLOAT Language differences from PL/0: - no constant declarations, only vars - no procedures - { ... } is a scope ::= ::= { } ::= float ; | bool ; ::= '{' { } '}' | = ; | if ( ) | read ; | write ; LEXICAL GRAMMAR FOR FLOAT LITERALS DIGIT [0-9] SIGN (-|\+) EXPONENTMARKER [eE] NUMBER {NUMBERPART}{EXPONENTPART}? MANTISSA [.]({DIGIT})* NUMBERPART {SIGN}?{DIGIT}+{MANTISSA}? EXPONENTPART {EXPONENTMARKER}{SIGN}?{DIGIT}+ ENHANCED ASTS AS AN IR // changes in // file ast.h #include "type_exp.h" // (possibly signed) floats typedef struct { file_location *file_loc; const char *text; type_exp_e type; word_type value; } number_t; // expr ::= expr op expr // op ::= == | != | < | <= | + | - | * | / typedef struct { file_location *file_loc; type_exp_e type; struct expr_s *expr1; token_t op; struct expr_s *expr2; } binary_op_expr_t; // ... IDENTIFIER USES IN ASTs // E ::= x typedef struct { // name of a constant or variable const char *name; // set during static analysis, // includes info for lexical addr id_use *idu; } ident_t; // S ::= read x typedef struct { AST *ident; } read_t; // S ::= assign x E typedef struct { AST *ident; AST *exp; } assign_t; ID_USE STRUCTURES typedef struct { id_attrs *attrs; unsigned int levelsOutward; } id_use; ID ATTRIBUTES // attributes of idents typedef struct { file_location file_loc; var_type vt; // type // offset from beginning of scope unsigned int loc_offset; } id_attrs; // where: typedef enum {float_t, bool_t} var_type; void scope_check_beginStmt(AST *stmt) { symtab_enter_scope(); // <******* scope_check_varDecls( stmt->data.begin_stmt.vds); AST_list stmts = stmt->data.begin_stmt.stmts; while (!ast_list_is_empty(stmts)) { scope_check_stmt( ast_list_first(stmts)); stmts = ast_list_rest(stmts); } symtab_leave_scope(); // <******** } GENERATING CODE Done in the file gen_code.c - Functions arranged to walk the ASTs - All return a code_seq Useful files: ast.h id_attrs.h id_use.h code.h STEPS FOR CODE GENERATION 1. start with the base cases 2. Write simplest tests possible 3. Design code sequences for the nonterminals involved 4. Write code for each node of the AST 5. Test it: a. check the output machine code b. check the VM's execution EXPRESSIONS What are the base cases? A very simple test: What code sequence do we want? GENERATING CODE Where does execution start? What is the AST for our program? Where do we generate those code sequences? Let's write it! NESTED SCOPES Example in FLOAT: # $Id$ float x; { float y; { float z; z = 0; y = 1; x = 2; } } What kind of code sequence for this?