#include #include #include #include #include #include #include #define SIZE_INT 4 #define SIZE_ADDR 8 #define SIZE_CHAR 1 #define SIZE_BOOL 4 //TODO: Ask Carl what this size should be struct TableNode; typedef struct TFList TFList; typedef struct Constant_Stack { struct TableNode *theType; void *theValue; struct Constant_Stack *next; bool isConst; } Constant_Stack; typedef struct { int size; } primitive_info; typedef struct { int numofdimensions; struct TableNode *typeofarray; } array_info; typedef struct { int numofelements; struct SymbolTable *recordScope; int total_size; int *offsets; } record_info; typedef struct { int startlinenumber; bool regularoras; } function_declaration_info; typedef struct { struct TableNode *parameter; struct TableNode *returntype; } function_type_info; typedef union { primitive_info *PrimAdInfo; array_info *ArrayAdInfo; record_info *RecAdInfo; function_declaration_info *FunDecAdInfo; function_type_info *FunTypeAdInfo; } AdInfo; typedef struct ListOfTable { struct SymbolTable *table; struct ListOfTable *next; } ListOfTable; //Table node to store typedef struct TableNode { struct TableNode *theType; int tag; char *theName; AdInfo *additionalinfo; struct TableNode *next; } TableNode; typedef struct SymbolTable { TableNode *entries; struct SymbolTable *Parent_Scope; struct ListOfTable *Children_Scope; int Line_Number; int Column_Number; } SymbolTable; typedef enum { TYPE_STRING = 1, TYPE_ARRAY_TYPE = 2, TYPE_RECORD_TYPE = 3, TYPE_FUNCTION_DECLARATION = 4, TYPE_FUNCTION_TYPE = 5, TYPE_PRIMITIVE = 6, TYPE_ALL_ELSE = 7, TYPE_UNDEFINED = 8, TYPE_RECORD = 9, TYPE_ARRAY = 10, TYPE_SYSTEM_DEFINED = 11, TYPE_PRIMITIVE_TYPE = 12 } types; AdInfo *CreatePrimitiveInfo(int size); int getPrimSize(TableNode *definition); AdInfo *CreateArrayInfo(int dim, TableNode *type); int getNumArrDim(TableNode *definition); TableNode *getArrType(TableNode *definition); AdInfo *CreateRecordInfo(int length, SymbolTable *recordScope); int getRecLength(TableNode *definition); SymbolTable *getRecList(TableNode *definition); TableNode *setRecSize(TableNode *tn, int n); int getRecSize(SymbolTable *tn); AdInfo *CreateFunctionDeclarationInfo(int line, bool asorregular); int getStartLine(TableNode *definition); TableNode *setStartLine(TableNode *tn, int start); bool getAsKeyword(TableNode *definition); TableNode *setAsKeyword(TableNode *tn, bool as); AdInfo *CreateFunctionTypeInfo(TableNode *parameter, TableNode *returntype); TableNode *getParameter(TableNode *definition); TableNode *getReturn(TableNode *definition); SymbolTable *CreateScope(SymbolTable *ParentScope, int Line, int Column); SymbolTable *init(SymbolTable *start); TableNode *populateTypeAndInfo(TableNode *tn, TableNode *type, AdInfo *info); int getAdInfoType(TableNode *tn); TableNode *CreateEntry(SymbolTable *table, int tag, TableNode *typeOf, char *id, AdInfo *ad); char *getType(TableNode *tn); char *getName(TableNode *tn); int getLine(SymbolTable *st); int getColumn(SymbolTable *st); TableNode *getTypeEntry(TableNode *tn); TableNode *addName(TableNode *tn, char *str); SymbolTable *setLineNumber(SymbolTable *st, int line); SymbolTable *setColumnNumber(SymbolTable *st, int column); TableNode *table_lookup(SymbolTable *table, char *x); TableNode *look_up(SymbolTable *table, char *x); void print_symbol_table(SymbolTable *table, FILE *file_ptr); SymbolTable *getAncestor(SymbolTable *table); SymbolTable *removeEntry(SymbolTable *scope, char *search); bool typeCheck(char *firstID, char *secondID); SymbolTable *getParent(SymbolTable *st); ListOfTable *getChildren(SymbolTable *st); SymbolTable *getFirstChild(ListOfTable *lt); ListOfTable *getRestOfChildren(ListOfTable *lt); TableNode *getFirstEntry(SymbolTable *st); TableNode *getNextEntry(TableNode *tn); TableNode *printTableNode(TableNode *tn); void printdebug_impl(char *file, int line, const char *format, ...); #define printdebug(format, ...) \ printdebug_impl(__FILE__, __LINE__, format, ##__VA_ARGS__) extern int yylex(void); extern char *yytext; extern int yyleng; extern int yychar; extern SymbolTable *cur; extern int line_number; extern int column_number; extern FILE *yyin; extern bool DEBUG; extern int temp2_count; extern TableNode *funprime; extern TableNode *arrayprim; extern TableNode *integ; extern TableNode *addr; extern TableNode *chara; extern TableNode *stri; extern TableNode *boo; extern TableNode *recprime; extern TableNode *funtypeprime; extern TableNode *undefined; extern Constant_Stack *head; extern char *COLOR_RED; extern char *COLOR_GREEN; extern char *COLOR_ORANGE; extern char *COLOR_BLUE; extern char *COLOR_PURPLE; extern char *COLOR_CYAN; extern char *COLOR_LIGHTGRAY; extern char *COLOR_DARKGRAY; extern char *COLOR_LIGHTRED; extern char *COLOR_LIGHTGREEN; extern char *COLOR_YELLOW; extern char *COLOR_LIGHTBLUE; extern char *COLOR_LIGHTPURPLE; extern char *COLOR_LIGHTCYAN; extern char *COLOR_WHITE; //_____________________________________________________________ // these are from page 364 typedef enum { E_LABEL = 10000, // this is not in the book E_ADD, // 1 from the list E_SUB, // 1 E_MUL, // 1 E_DIV, // 1 E_MOD, // 1 E_OR, // 1 E_AND, // 1 E_NEG, // 2 E_NOT, // 2 E_ASSIGN, // 3 E_GOTO, // 4 E_COND_GOTO, // 5 I don't thik I need this because we could just follow the < or the = and just assume that it's a cond got E_IF_X_TRUE, // 5 E_IF_X_FALSE, // 5 E_LESS_THAN, // 6 rule 1 + 5 E_EQUAL_TO, // 6 rule 1 + 5 E_CALL, // 7 E_PARAM, // 7 E_RETURN, // 7 E_INDEX_COPY_RIGHT, // 8 this is x = y[i] E_INDEX_COPY_LEFT, // 8 x[i] = y E_ADDRESS_OF, // 9 x = &y E_DEREF_RIGHT, // 9 x = *y E_DEREF_LEFT // 9 x* = y } Op; typedef enum { NODE = 11000, // TableNode INTEGER, // int STRING, // char * CHARACTER, // char ADDRESS, // void * BOOLEAN // bool } Discriminant; typedef union { TableNode * node; int integer; char * string; char character; void * address; bool Boolean; } TNConstUnion; typedef struct { Discriminant d; TNConstUnion * tnc_union; } TNodeOrConst; typedef struct Instruction Instruction; typedef struct Instruction { Op opcode; TableNode * result; TNodeOrConst * operand1; TNodeOrConst * operand2; int label; int index; Instruction * prev; Instruction * next; } Instruction; typedef struct TFList { Instruction * i; TFList * next; } TFList; TFList * make_list(Instruction * i); // - makelist(i) function to create instruction lists void merge(TFList * l1, TFList * l2); // - merge(p1,p2) function to concatenate lists void backpatch(TFList * l, int label); // - backpatch(p,i) function to fill in jump targets //int temp_count; //int label_count; //bool code_gen; //Instruction * begin; //Instruction * current; //char * temp; TNodeOrConst * tn_or_const(Discriminant d, void * tnc); void emit_binary_op(Op op, TableNode * result, TNodeOrConst * arg1, TNodeOrConst * arg2); void emit_unary_op(Op op, TableNode * result, TNodeOrConst * arg); void emit_assignment(TableNode * target, TNodeOrConst * source); void emit_as_file(FILE * out_file, Instruction * instr_arr); void emit_label(int label); void emit_jump(int label); void emit_conditional_jump(Op condition, int label, ...); void emit_function_start(int name); void emit_parameter(TNodeOrConst * param); void emit_function_call(TableNode * result, int param_count, TNodeOrConst * name); void emit_return(TNodeOrConst * value); void emit_reserve(TableNode * result, TNodeOrConst * size); void emit_release(TableNode * pointer); void emit_field_access(char* result, char* record, char* field); void emit_array_access(Op op, TableNode * result, TNodeOrConst * array, TNodeOrConst * index); void emit_bounds_check(TNodeOrConst * index, TNodeOrConst * arr); // * Implement instruction array storage for backpatching /* Track 2: Control Flow & Boolean Expressions * Implement backpatching infrastructure: * Create truelist and falselist attributes for Boolean expressions * Create control flow emission functions: * Add Bison actions for control structures: - if-then-else with backpatching - while loops with backpatching * Implement short-circuit Boolean operations (&&, ||, !) * Add marker (M) nonterminal for recording instruction positions */ /* Track 3: Functions & Complex Types * Implement function-related emission: * Add Bison actions for the 'as' clause * Create memory layout calculation functions: - calculate_record_size(Record_Type* type) → returns bytes needed - calculate_array_size(Array_Type* type, int dimensions[]) → returns total bytes - calculate_field_offset(Record_Type* type, char* field_name) → returns offset * Add Bison actions for arrays and records */ /* Track 4: Memory Access & Integration * Implement array and record access code: - emit_field_access(char* result, char* record, char* field) - emit_array_access(char* result, char* array, char* index, char* dimension) * Add array dimension access (a._1, a._2, etc.) * Implement bounds checking emission: - emit_bounds_check(char* index, char* size, char* error_label) * Create the code generation driver function * Implement common error handling * Document the complete intermediate instruction set * Build integration test suite covering all language features * Implement row-major/column-major array layout calculation */