367 lines
11 KiB
C
367 lines
11 KiB
C
#include <stdarg.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include <stdint.h>
|
|
|
|
#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 CGNode CGNode;
|
|
|
|
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
|
|
*/
|
|
//-------------------------------------------------------------
|
|
extern FILE *cg_flag;
|
|
typedef struct CGNode {
|
|
TableNode *tn;
|
|
int address;
|
|
CGNode *next;
|
|
}CGNode;
|
|
|
|
int generate();
|
|
CGNode *getNextCG(CGNode *cg);
|
|
int getAddress(CGNode *cg);
|
|
TableNode *getTNofCG(CGNode *cg);
|
|
int generateLabel(Instruction *instruction);
|
|
int generateAdd(Instruction *instruction);
|
|
int generateSub(Instruction *instruction);
|
|
int generateMult(Instruction *instruction);
|
|
int generateDiv(Instruction *instruction);
|
|
int generateMod(Instruction *instruction);
|
|
int generateOr(Instruction *instruction);
|
|
int generateAnd(Instruction *instruction);
|
|
int generateNeg(Instruction *instruction);
|
|
int generateNot(Instruction *instruction);
|
|
int generateDiv(Instruction *instruction);
|
|
int generateAssign(Instruction *instruction); // is this for something like x = 1?
|
|
int generateGoto(Instruction *instruction);
|
|
int generateCondGoto(Instruction *instruction);
|
|
int generateIfTrue(Instruction *instruction);
|
|
int generateIfFalse(Instruction *instruction);
|
|
int generateLessThan(Instruction *instruction);
|
|
int generateEqualTo(Instruction *instruction);
|
|
int generateCall(Instruction *instruction);
|
|
int generateReturn(Instruction *instruction);
|
|
int generateCopyRight(Instruction *instruction);
|
|
int generateCopyLeft(Instruction *instruction);
|
|
int generateAddressOf(Instruction *instruction);
|
|
int generateParam(Instruction *instruction); |