diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..504b122 --- /dev/null +++ b/.clang-format @@ -0,0 +1,6 @@ +BasedOnStyle: Google +IndentWidth: 4 +ColumnLimit: 0 +AllowShortStringsOnSingleLine: true +BreakStringLiterals: false +ReflowComments: false diff --git a/Grammar-FE-t-NoTask b/Grammar-FE-t-NoTask deleted file mode 100644 index 1ad478e..0000000 --- a/Grammar-FE-t-NoTask +++ /dev/null @@ -1,35 +0,0 @@ -* Dev - Sprint1-TokenLocationLogic-NoTask - Sprint1-TokenizeConstantsAndLiterals-FE-t#03 - Sprint2-BlockHandlingGrammar-FE-t#34 - Sprint2-CombineGrammarAndMakeAndRunner-BE-NoTask# - Sprint2-NewFormatPlusGrammar-FE-t#NoTask - Sprint2-PrintOutErrorTokenPositions-NoTask - Sprint2-Symbol_Table_Setup-FE-t#32 - Token_Error_Logic-No_Task - main - remotes/origin/Dev - remotes/origin/HEAD -> origin/main - remotes/origin/Sprint1-BasicProgSetup-FE-t#06 - remotes/origin/Sprint1-BasicProgSetupFix-t#06 - remotes/origin/Sprint1-HelpInput-FE-t#18 - remotes/origin/Sprint1-TokenLocationLogic-NoTask - remotes/origin/Sprint1-TokenizeConstantsAndLiterals-FE-t#03 - remotes/origin/Sprint1-TokenizeID_MainFunction-FE-t#04 - remotes/origin/Sprint1-TokenizeOperators-FE-t#08 - remotes/origin/Sprint1-Type/Keywards-FE-t#07 - remotes/origin/Sprint1-punctuation/grouping-FE-t#09 - remotes/origin/Sprint2-AssignableAndMemory-FE-t#39 - remotes/origin/Sprint2-BlockHandlingGrammar-FE-t#34 - remotes/origin/Sprint2-CombineGrammarAndMakeAndRunner-BE-NoTask# - remotes/origin/Sprint2-CommandLineHandling-FE-t#33 - remotes/origin/Sprint2-CompoundStmntGrmmr-FE-t#36 - remotes/origin/Sprint2-FunctionDefinition-FE-t#38 - remotes/origin/Sprint2-Infrastructure-FE-t#30 - remotes/origin/Sprint2-NewFormatPlusGrammar-FE-t#NoTask - remotes/origin/Sprint2-PrintOutErrorTokenPositions-NoTask - remotes/origin/Sprint2-SymbolTableOperations-FE-t#29 - remotes/origin/Sprint2-Symbol_Table_Setup-FE-t#32 - remotes/origin/Sprint2-addingTests-t#00 - remotes/origin/Token_Error_Logic-No_Task - remotes/origin/main diff --git a/Makefile b/Makefile index fe8f769..6fefed1 100644 --- a/Makefile +++ b/Makefile @@ -1,59 +1,104 @@ +# ----- Definitions ----- CC := gcc FLEX := flex +BISON = bison + +CFLAGS := -ggdb +BISONFLAGS := -d + LEX := src/lexicalStructure.lex +YACC := src/grammar.y EXE := alpha -CFLAGS := -YACC := bison + +OBJS := tmp/runner.o tmp/symbol_table.o tmp/grammar.tab.o tmp/lex.yy.o tmp/intermediate_code.o tmp/codegen.o TESTS-S1 := $(wildcard tests/sprint1/test/*.alpha) TESTS-S2 := $(wildcard tests/sprint2/test/*.alpha) +TESTS-S3 := $(wildcard tests/sprint3/test/*.alpha) +TESTS-S4 := $(wildcard tests/sprint4/test/*.alpha) +# ---------- -compiler: clean runner -tmp/grammar.tab.c: src/grammar.y + +# ----- Targets ----- +all: compiler + +compiler: clean tmp $(OBJS) + $(CC) $(CFLAGS) -o $(EXE) $(OBJS) + +clean: + rm -f $(EXE) + rm -rf out + rm -rf tmp + rm -f *.s + rm -f *.out + +tmp: mkdir -p tmp - $(YACC) -d src/grammar.y - mv grammar.tab.c tmp/ - mv grammar.tab.h tmp/ -tmp/lex.yy.c: src/lexicalStructure.lex tmp/grammar.tab.c +tmp/grammar.tab.c tmp/grammar.tab.h: $(YACC) + $(BISON) $(BISONFLAGS) -o tmp/grammar.tab.c $(YACC) + +tmp/lex.yy.c tmp/flex.h: $(LEX) tmp/grammar.tab.h $(FLEX) -o tmp/lex.yy.c $(LEX) - mv flex.h tmp/ + mv flex.h tmp/flex.h +# ----------- -tmp/runner.o: src/runner.c src/runner.h tmp/flex.h - $(CC) $(CFLAGS) -o tmp/runner.o -c src/runner.c + + +# ----- Create Objs ----- +tmp/grammar.tab.o: tmp/grammar.tab.c + $(CC) $(CFLAGS) -c tmp/grammar.tab.c -o tmp/grammar.tab.o + +tmp/lex.yy.o: tmp/lex.yy.c + $(CC) $(CFLAGS) -c tmp/lex.yy.c -o tmp/lex.yy.o tmp/symbol_table.o: src/symbol_table.c src/symbol_table.h - $(CC) $(CFLAGS) -o tmp/symbol_table.o -c src/symbol_table.c + $(CC) $(CFLAGS) -c src/symbol_table.c -o tmp/symbol_table.o -runner: tmp/lex.yy.c tmp/runner.o tmp/symbol_table.o - $(CC) $(CFLAGS) -o $(EXE) tmp/runner.o tmp/grammar.tab.c tmp/lex.yy.c +tmp/intermediate_code.o: src/intermediate_code.c src/intermediate_code.h + $(CC) $(CFLAGS) -c src/intermediate_code.c -o tmp/intermediate_code.o -debug: CFLAGS += -DDEBUG=1 -debug: clean compiler +tmp/codegen.o: src/codegen.c src/codegen.h + $(CC) $(CFLAGS) -c src/codegen.c -o tmp/codegen.o -test: test-s1 test-s2 +tmp/runner.o: src/runner.c src/runner.h tmp/flex.h tmp/grammar.tab.h + $(CC) $(CFLAGS) -c src/runner.c -o tmp/runner.o +# ----------- + + + +# ----- Tests ----- +test: + chmod +x ./check.sh + chmod +x ./test.sh + $(foreach test, $(TESTS-S1), (./$(EXE) -tok -debug $(test) || true);) + ./test.sh sp2 + ./test.sh sp3 + ./test.sh sp4 + ./check.sh test-s1: chmod +x ./check.sh - $(foreach test, $(TESTS-S1), ./$(EXE) -tok $(test);) - ./check.sh + chmod +x ./test.sh + $(foreach test, $(TESTS-S1), (./$(EXE) -tok -debug $(test) || true);) + ./check.sh sp1 test-s2: chmod +x ./check.sh - $(foreach test, $(TESTS-S2), ./$(EXE) -tok $(test);) - ./check.sh - $(foreach test, $(TESTS-S2), ./$(EXE) $(test);) + chmod +x ./test.sh + ./test.sh sp2 + ./check.sh sp2 -clean: - rm -f *.o - rm -f lex.yy.c - rm -f $(EXE) - rm -f flex.h - rm -f *.tok - rm -f grammar.tab.c - rm -f grammar.tab.h - rm -f *.st - rm -rf out - rm -rf tmp - rm -f parser \ No newline at end of file +test-s3: + chmod +x ./check.sh + chmod +x ./test.sh + ./test.sh sp3 + ./check.sh sp3 + +test-s4: + chmod +x ./check.sh + chmod +x ./test.sh + ./test.sh sp4 + ./check.sh sp4 +# ----------- \ No newline at end of file diff --git a/check.sh b/check.sh index b8b138c..cf7c946 100755 --- a/check.sh +++ b/check.sh @@ -5,23 +5,63 @@ # The Translators - Spring 2025 # TOK_DIR="out" +NOCOLOR='\033[0m' +RED='\033[0;31m' +GREEN='\033[0;32m' +ORANGE='\033[0;33m' +BLUE='\033[0;34m' +PURPLE='\033[0;35m' +CYAN='\033[0;36m' +LIGHTGRAY='\033[0;37m' +DARKGRAY='\033[1;30m' +LIGHTRED='\033[1;31m' +LIGHTGREEN='\033[1;32m' +YELLOW='\033[1;33m' +LIGHTBLUE='\033[1;34m' +LIGHTPURPLE='\033[1;35m' +LIGHTCYAN='\033[1;36m' +WHITE='\033[1;37m' + +compare_files() { + local file="$1" + local filename=$(basename -- "$file") + filename="${filename%.*}" + local num=${filename:2:1} + local exp="./tests/sprint$num/expected/$filename.expected" + + if [[ -f "$exp" ]]; then + diff -q "$file" "$exp" > /dev/null + if [[ $? -eq 0 ]]; then + echo -e "${GREEN}[✔] ${PURPLE}$filename ${WHITE}passed.${NOCOLOR}" + elif [[ ! -s "$file" ]]; then + echo -e "${RED}[✘] ${PURPLE}$filename ${WHITE}failed with an empty file. (did it segfault?)${NOCOLOR}" + else + echo -e "\n${RED}[✘] ${PURPLE}$file ${WHITE}failed with an unexpected value...${NOCOLOR}" + diff --color=always "$file" "$exp" + echo -e "" + fi + else + echo -e "${ORANGE}[-] ${PURPLE}$filename ${WHITE}does not have an expected value.${NOCOLOR}" + fi +} if [[ ! -d "$TOK_DIR" ]]; then - echo "Directory $TOK_DIR does not exist." + echo -e "${RED}[ERROR] ${YELLOW}Directory $TOK_DIR does not exist.${NOCOLOR}" exit 1 fi -echo -e "\n" -for file in "$TOK_DIR"/*; do - filename=$(basename -- "$file") - filename="${filename%.*}" - num=${filename:2:1} - exp="./tests/sprint$num/expected/$filename.expected" - - if [[ -f "$exp" ]]; then - echo -e "--------------------------------------------" - echo -e "Checking $file...\n" - diff --color=always "$file" "$exp" - echo -e "--------------------------------------------\n" - fi -done \ No newline at end of file +if [[ $# -eq 0 ]]; then + for file in "$TOK_DIR"/*; do + compare_files "$file" + done +elif [[ $# -eq 1 ]]; then + prefix="$1" + for file in "$TOK_DIR"/"$prefix"*; do + if [[ -f "$file" ]]; then + compare_files "$file" + fi + done +else + echo -e "${LIGHTBLUE}Usage: $0 [sp#]${NOCOLOR}" + exit 1 +fi \ No newline at end of file diff --git a/runner b/runner deleted file mode 100755 index 2e82053..0000000 Binary files a/runner and /dev/null differ diff --git a/src/codegen.c b/src/codegen.c new file mode 100644 index 0000000..250d2a4 --- /dev/null +++ b/src/codegen.c @@ -0,0 +1,618 @@ +/* Code Generator */ +/* The Translators - Spring 2025 */ + +#include "codegen.h" + +int generate(){ + offset = 0; + Instruction *i = begin; + while (i != NULL) { + switch(getOp(i)) { + case E_LABEL: + generateLabel(i); + break; + case E_ADD: + generateAdd(i); + break; + case E_SUB: + generateSub(i); + break; + case E_MUL: + generateMult(i); + break; + case E_DIV: + generateDiv(i); + break; + case E_MOD: + generateMod(i); + break; + case E_OR: + generateOr(i); + break; + case E_AND: + generateAnd(i); + break; + case E_NEG: + generateNeg(i); + break; + case E_NOT: + generateNot(i); + break; + case E_ASSIGN: + generateAssign(i); + break; + case E_GOTO: + generateGoto(i); + break; + case E_IF_X_TRUE: + generateIfTrue(i); + break; + case E_IF_X_FALSE: + generateIfFalse(i); + break; + case E_LESS_THAN: + generateLessThan(i); + break; + case E_EQUAL_TO: + generateEqualTo(i); + break; + case E_CALL: + generateCall(i); + break; + case E_PARAM: + generateParam(i); + break; + case E_RETURN: + generateReturn(i); + break; + case E_INDEX_COPY_RIGHT: + generateCopyRight(i); + break; + case E_INDEX_COPY_LEFT: + generateCopyLeft(i); + break; + case E_ADDRESS_OF: + generateAddressOf(i); + break; + default: + ; + } + i = i->next; + } + return -1; +} + +CGNode *getNextCG(CGNode *cg) { + if (cg == NULL) { + return NULL; + } + return cg->next; +} + +int getAddress(CGNode *cg) { + if (cg == NULL) { + return -1; + } + + return currentsp - cg->address; +} + +TableNode *getTNofCG(CGNode *cg) { + if (cg == NULL) { + return NULL; + } + return cg->tn; +} + +CGNode *findCG(TableNode *tn) { + CGNode *cg = cgList; + while (cg != NULL) { + if (getTNofCG(cg) == tn) { + return cg; + } + cg = getNextCG(cg); + } + return NULL; +} + +CGNode *addCG(TableNode *tn, int sp) { + CGNode *cg = calloc(1, sizeof(CGNode)); + cg->tn = tn; + offset += 4; // <- quick fix getPrimSize(getTypeEntry(tn)) + cg->address = offset; + cg->next = cgList; + cgList = cg; + return cg; +} + + +int generateLabel(Instruction *inst) { + fprintf(cg_flag, ".L%d:\n", getLabel(inst)); + return 0; +} +int generateAdd(Instruction *inst) { + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *cg = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateAdd failed, NULL operand"); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + + + CGNode *op1CG = findCG(getTN(op1)); + CGNode *op2CG = findCG(getTN(op1)); + if (op1CG == NULL) { + printdebug("generateAdd failed, %s is not initialized/in CG", getName(getTN(op1))); + return -1; + } + + if (op2CG == NULL) { + printdebug("generateAdd failed, %s is not initialized/in CG", getName(getTN(op2))); + return -1; + } + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#addition start\n", getAddress(op1CG)); + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op2CG)); + fprintf(cg_flag, "\taddl\t%%edx, %%eax\n"); + fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\t#addition end\n", getAddress(cg)); + return 0; +} + +int generateSub(Instruction *instruction) { + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(instruction); + TNodeOrConst *op2 = getOperand2(instruction); + CGNode *cg = findCG(getResult(instruction)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateSub failed, NULL operand"); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(instruction), offset); + } + + CGNode *op1CG = findCG(getTN(op1)); + CGNode *op2CG = findCG(getTN(op2)); + if (op1CG == NULL) { + printdebug("generateSub failed, op1 is not constant but not in CGlist"); + return -1; + } + + if (op2CG == NULL) { + printdebug("generateAdd failed, %s is not initialized/in CG", getName(getTN(op2))); + return -1; + } + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#subtraction start\n", getAddress(op1CG)); + fprintf(cg_flag, "\tsubl\t%d(%%rbp), %%eax\n", getAddress(op2CG)); + fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\t#subtraction end\n", getAddress(cg)); + return 0; +} + +int generateMult(Instruction *inst){ + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *cg = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateMult failed, NULL operand"); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + CGNode *op1CG = findCG(getTN(op1)); + CGNode *op2CG = findCG(getTN(op2)); + if (op1CG == NULL) { + printdebug("generateMult failed, op1 is not constant but not in CGlist"); + return -1; + } + + if (op2CG == NULL) { + printdebug("generateMult failed, %s is not initialized/in CG", getName(getTN(op2))); + return -1; + } + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#multiplication start\n", getAddress(op1CG)); + fprintf(cg_flag, "\timull\t%d(%%rbp), %%eax\n", getAddress(op2CG)); + fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\t#multiplication end\n", getAddress(cg)); + return 0; +} + +int generateDiv(Instruction *inst) { + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *cg = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateDiv failed, NULL operand"); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + + CGNode *op1CG = findCG(getTN(op1)); + CGNode *op2CG = findCG(getTN(op2)); + if (op1CG == NULL) { + printdebug("generateDiv failed, op1 is not constant but not in CGlist"); + return -1; + } + + if (op2CG == NULL) { + printdebug("generateDiv failed, %s is not initialized/in CG", getName(getTN(op2))); + return -1; + } + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#division start\n", getAddress(op1CG)); //moves dividend into eax + fprintf(cg_flag, "\tcltd\n"); //sign extends the dividend in eax + fprintf(cg_flag, "\tidivl\t%d(%%rbp)\n", getAddress(op2CG));//divides edx by value accessed from stack + fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\t#division end\n", getAddress(cg)); //stores result + return 0; +} + +int generateMod(Instruction *inst) { + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *cg = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateMod failed, NULL operand"); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + CGNode *op1CG = findCG(getTN(op1)); + CGNode *op2CG = findCG(getTN(op2)); + if (op1CG == NULL) { + printdebug("generateMod failed, op1 is not constant but not in CGlist"); + return -1; + } + + if (op2CG == NULL) { + printdebug("generateMod failed, %s is not initialized/in CG", getName(getTN(op2))); + return -1; + } + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#mod start\n", getAddress(op1CG)); //moves dividend into eax + fprintf(cg_flag, "\tcltd\n"); //sign extends the dividend in eax + fprintf(cg_flag, "\tidivl\t%d(%%rbp)\n", getAddress(op2CG));//divides edx by value accessed from stack + fprintf(cg_flag, "\tmovl\t%%edx, %d(%%rbp)\t#mod end\n", getAddress(cg)); //stores result from edx (remainder) + return 0; +} + +int generateOr(Instruction *inst) { + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *cg = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateOr failed, NULL operand"); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + + CGNode *op1CG = findCG(getTN(op1)); + CGNode *op2CG = findCG(getTN(op2)); + if (op1CG == NULL) { + printdebug("generateOr failed, op1 is not constant but not in CGlist"); + return -1; + } + + if (op2CG == NULL) { + printdebug("generateOr failed, %s is not initialized/in CG", getName(getTN(op2))); + return -1; + } + + int label = label_gen(); + + fprintf(cg_flag, "\tcmpl\t$0, %d(%%rbp)\t#start or\n", getAddress(op1CG)); + fprintf(cg_flag, "\tjne\t.L%dor2\n", label); + + fprintf(cg_flag, "\tcmpl\t$0, %d(%%rbp)\n", getAddress(op2CG)); + fprintf(cg_flag, "\tje\t.L%dor3\n", label); + + fprintf(cg_flag, ".L%dor2:\n", label); + fprintf(cg_flag, "\tmovl\t$1, %%eax\n"); + fprintf(cg_flag, "\tjmp\t.L%dor4\n", label); + + fprintf(cg_flag, ".L%dor3:\n", label); + fprintf(cg_flag, "\tmovl\t$0, %%eax\n"); + + fprintf(cg_flag, ".L%dor4:\n", label); + fprintf(cg_flag, "\tmovb\t%%al, %d(%%rbp)\n", getAddress(cg)); + fprintf(cg_flag, "\tandb\t$1, %d(%%rbp)\t#or end\n", getAddress(cg)); //stores result + return 0; +} + +int generateAnd(Instruction *inst) { + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *cg = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("%sgenerateAnd failed, NULL operand", COLOR_RED); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + + CGNode *op1CG = findCG(getTN(op1)); + CGNode *op2CG = findCG(getTN(op2)); + if (op1CG == NULL) { + printdebug("generateAnd failed, op1 is not constant but not in CGlist"); + return -1; + } + + if (op2CG == NULL) { + printdebug("generateAnd failed, %s is not initialized/in CG", getName(getTN(op2))); + return -1; + } + int label = label_gen(); + + fprintf(cg_flag, "\tcmpl\t$0, %d(%%rbp)\t#start and\n", getAddress(op1CG)); + fprintf(cg_flag, "\tje\t.L%dor2\n", label); + + fprintf(cg_flag, "\tcmpl\t$0, %d(%%rbp)\n", getAddress(op2CG)); + fprintf(cg_flag, "\tje\t.L%dor2\n", label); + + fprintf(cg_flag, "\tmovl\t$1, %%eax\n"); + fprintf(cg_flag, "\tjmp\t.L%dor3\n", label); + + fprintf(cg_flag, ".L%dor2:\n", label); + fprintf(cg_flag, "\tmovl\t$0, %%eax\n"); + + fprintf(cg_flag, ".L%dor3:\n", label); + fprintf(cg_flag, "\tmovb\t%%al, %d(%%rbp)\n", getAddress(cg)); + fprintf(cg_flag, "\tandb\t$1, %d(%%rbp)\t#and end\n", getAddress(cg)); //stores result + return 0; +} +int generateNeg(Instruction *inst) { + TNodeOrConst *op1 = getOperand1(inst); + CGNode *cg = findCG(getResult(inst)); + + if (op1 == NULL) { + printdebug("generateNeg failed, NULL operand"); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + + CGNode *op1CG = findCG(getTN(op1)); + if (op1CG == NULL) { + printdebug("generateNeg failed, op1 is not constant but not in CGlist"); + return -1; + } + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#negation start\n", getAddress(op1CG)); + fprintf(cg_flag, "\tnegl\t%%eax\n"); + fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\t#negation end\n", getAddress(cg)); + return 0; +} +int generateNot(Instruction *inst) { + TNodeOrConst *op1 = getOperand1(inst); + CGNode *cg = findCG(getResult(inst)); + + if (op1 == NULL) { + printdebug("generateNot failed, NULL operand"); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + + CGNode *op1CG = findCG(getTN(op1)); + if (op1CG == NULL) { + printdebug("generateNot failed, op1 is not constant but not in CGlist"); + return -1; + } + + fprintf(cg_flag, "\tmovzbl\t%d(%%rbp), %%eax\t#not start\n", getAddress(op1CG)); + fprintf(cg_flag, "\ttestl\t%%eax, %%eax\n"); + fprintf(cg_flag, "\tsetne\t%%al\n"); + fprintf(cg_flag, "\txorl\t$1, %%eax\n"); + fprintf(cg_flag, "\tmovzbl\t%%al, %%eax\n"); + fprintf(cg_flag, "\tmovb\t%%al, %d(%%rbp)\n", getAddress(cg)); + fprintf(cg_flag, "\tandb\t$1, %d(%%rbp)\t#not end\n", getAddress(cg)); + return 0; +} + +int generateAssign(Instruction *inst) { + TNodeOrConst *op1 = getOperand1(inst); + CGNode *cg = findCG(getResult(inst)); + + + if (op1 == NULL) { + printdebug("generateAssign failed, NULL operand"); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + + + //add option for constant assignment (should be easy) + if (isConst(op1) == true) { + fprintf(cg_flag, "\tmovl\t$%d, %d(%%rbp)\t#constant assign\n", getConst(op1), getAddress(cg)); + return 0; + } + + CGNode *op1CG = findCG(getTN(op1)); + if (op1CG == NULL) { + printf("failed here\n"); + printdebug("generateAssign failed, op1 is not constant but not in CGlist"); + return -1; + } + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#assign start\n", getAddress(op1CG)); + fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\t#assign end\n", getAddress(cg)); + return 0; +} + +int generateGoto(Instruction *instruction){ + return -1; +} + +int generateCondGoto(Instruction *instruction) { + return -1; +} + +int generateIfTrue(Instruction *instruction){ + return -1; + // might just be a goto for where to go if something is true, or returning if something is true, or checking if true and writing goto if thats the case +} + +int generateIfFalse(Instruction *instruction){ + return -1; +} + +int generateLessThan(Instruction *inst){ + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *cg = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("%sgenerateLessThan failed, NULL operand", COLOR_RED); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + + CGNode *op1CG = findCG(getTN(op1)); + CGNode *op2CG = findCG(getTN(op2)); + if (op1CG == NULL) { + printdebug("generateLessThan failed, op1 is not constant but not in CGlist"); + return -1; + } + + if (op2CG == NULL) { + printdebug("generateLessThan failed, %s is not initialized/in CG", getName(getTN(op2))); + return -1; + } + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#less than start\n", getAddress(op1CG)); + fprintf(cg_flag, "\tcmpl\t%d(%%rbp), %%eax\n", getAddress(op2CG)); + fprintf(cg_flag, "\tsetl\t%%al\n"); + fprintf(cg_flag, "\tmovb\t%%al, %d(%%rbp)\t#less than end\n", getAddress(cg)); + return 0; +} + +int generateEqualTo(Instruction *inst){ + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *cg = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("%sgenerateLessThan failed, NULL operand", COLOR_RED); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + + CGNode *op1CG = findCG(getTN(op1)); + CGNode *op2CG = findCG(getTN(op2)); + if (op1CG == NULL) { + printdebug("generateLessThan failed, op1 is not constant but not in CGlist"); + return -1; + } + + if (op2CG == NULL) { + printdebug("generateLessThan failed, %s is not initialized/in CG", getName(getTN(op2))); + return -1; + } + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#equal to start\n", getAddress(op1CG)); + fprintf(cg_flag, "\tcmpl\t%d(%%rbp), %%eax\n", getAddress(op2CG)); + fprintf(cg_flag, "\tsete\t%%al\n"); + fprintf(cg_flag, "\tmovb\t%%al, %d(%%rbp)\t#equal to end\n", getAddress(cg)); + return 0; +} +int generateCall(Instruction *instruction){ + return -1; + //will want to store parameters and then update the offset by adding 8? for stack pointer stuff, can then print call subroutine name, followed by movl of the result into the result's cg +} +int generateReturn(Instruction *instruction){ + return -1; + //will movl the result into the appropriate register and move the stack pointer/offset stuff back to correct value +} +int generateCopyRight(Instruction *instruction){ + return -1; +} +int generateCopyLeft(Instruction *instruction){ + return -1; +} +int generateAddressOf(Instruction *instruction){ + return -1; +} +int generateParam(Instruction *instruction){ + //need to check if op1 is null, then add it to the appropriate register/cg node. need a way to keep track of this, maybe just have global count of params generated + return -1; +} \ No newline at end of file diff --git a/src/codegen.h b/src/codegen.h new file mode 100644 index 0000000..3203a52 --- /dev/null +++ b/src/codegen.h @@ -0,0 +1,60 @@ +/* Code Generator */ +/* The Translators - Spring 2025 */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "intermediate_code.h" +#include "symbol_table.h" + +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); +CGNode *findCG(TableNode *tn); +CGNode *addCG(TableNode *tn, int sp); +int generateLabel(Instruction *inst); +int generateAdd(Instruction *inst); +int generateSub(Instruction *instruction); +int generateMult(Instruction *inst); +int generateDiv(Instruction *inst); +int generateMod(Instruction *inst); +int generateOr(Instruction *inst); +int generateAnd(Instruction *inst); +int generateNeg(Instruction *inst); +int generateNot(Instruction *inst); +int generateAssign(Instruction *inst); +int generateGoto(Instruction *instruction); +int generateCondGoto(Instruction *instruction); +int generateIfTrue(Instruction *instruction); +int generateIfFalse(Instruction *instruction); +int generateLessThan(Instruction *inst); +int generateEqualTo(Instruction *inst); +int generateCall(Instruction *instruction); +int generateReturn(Instruction *instruction); +int generateCopyRight(Instruction *instruction); +int generateCopyLeft(Instruction *instruction); +int generateAddressOf(Instruction *instruction); +int generateParam(Instruction *instruction); + +extern int label_count; +extern Instruction *begin; +extern Instruction *current; + +extern int offset; +extern int currentsp; +extern CGNode *cgList; \ No newline at end of file diff --git a/src/grammar.h b/src/grammar.h new file mode 100644 index 0000000..2b7b03c --- /dev/null +++ b/src/grammar.h @@ -0,0 +1,32 @@ +/* Syntax Analyzer with Bison (3.8.2) */ +/* The Translators - Spring 2025 */ + +#pragma once + +#include "../src/codegen.h" +#include "../src/intermediate_code.h" +#include "../src/symbol_table.h" +extern FILE *asc_flag; +extern bool tc_flag; +extern void insert_code_line(char * error_message, int line_number); + +typedef enum { + ERROR_RUNTIME = 1, + ERROR_SYNTAX = 2, + ERROR_TYPE = 3, + ERROR_UNDEFINED = 4 +} ErrorType; + +int token_tracker; +TableNode *tn; + +void yyerror(const char *err); +void throw_error(ErrorType error_type, const char *format, ...); + +int label_count; +Instruction *begin; +Instruction *current; + +int offset; +int currentsp; +CGNode *cgList; \ No newline at end of file diff --git a/src/grammar.y b/src/grammar.y index 3e9bc44..7060c94 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -1,45 +1,58 @@ /* Syntax Analyzer with Bison (3.8.2) */ /* The Translators - Spring 2025 */ +// ----- THIS FILE MUST BE FORMATTED CORRECTLY FOR READABILITY ----- // + +// ✏️ FORMATTING RULES: +// 1️⃣ Use 4 spaces for indentation. +// 2️⃣ Grammar rules (terminals and nonterminals) should always be on their own line. +// 3️⃣ Grammar rules and C-blocks should always begin 8 spaces in. +// 4️⃣ Rule end-markers (;, |) should always be 4 spaces in. +// 5️⃣ C-blocks should always be clearly defined and follow clang formatting rules. +// 6️⃣ 1-line if/for/while statements must be wrapped in curly braces. +// 7️⃣ Comments should always be above rules +// 8️⃣ DO NOT USE TABS. EVER. + +// Please ask Scarlett if you are unsure of how to format something. Thanks! 😀 + %{ - #include - #include "../src/symbol_table.c" - #include - extern int yylex(void); - void yyerror(const char *err); - extern char* yytext; - extern int yyleng; - extern int yychar; - extern SymbolTable * cur; - //char* cur_value; - //char* cur_type; - int token_tracker; - extern int line_number; - extern int column_number; - extern FILE * yyin; + #include "../src/grammar.h" %} -//%define api.location.type {location_t} -%locations + %union { - int integ; - char * words; + int integ; + char* words; + char letter; + void* tn; } +%locations -%type id_or_types -%type types + +%type idlist +%type assignable +%type expression +%type constant +%type id_or_types +%type types +%type sblock +%type compound_statement +%type simple_statement +%type statement_list +%type argument_list +%type ablock %token ID 101 -%token T_INTEGER 201 -%token T_ADDRESS 202 -%token T_BOOLEAN 203 -%token T_CHARACTER 204 -%token T_STRING 205 +%token T_INTEGER 201 +%token T_ADDRESS 202 +%token T_BOOLEAN 203 +%token T_CHARACTER 204 +%token T_STRING 205 %token C_INTEGER 301 -%token C_NULL 302 -%token C_CHARACTER 303 -%token C_STRING 304 -%token C_TRUE 305 -%token C_FALSE 306 +%token C_NULL 302 +%token C_CHARACTER 303 +%token C_STRING 304 +%token C_TRUE 305 +%token C_FALSE 306 %token WHILE 401 %token IF 402 %token THEN 403 @@ -89,176 +102,1119 @@ %precedence RESERVE RELEASE - %% program: - prototype_or_definition_list - ; + prototype_or_definition_list + | error { yyerrok; } + ; + + prototype_or_definition_list: - prototype prototype_or_definition_list - | definition prototype_or_definition_list - | prototype - | definition - ; + prototype prototype_or_definition_list + | definition prototype_or_definition_list + | prototype + | definition + | error { yyerrok; } + ; + + prototype: - L_PAREN EXTERNAL R_PAREN FUNCTION ID COLON ID; + L_PAREN EXTERNAL R_PAREN FUNCTION ID COLON ID + + | error { yyerrok; } + + ; + + definition: - TYPE ID COLON dblock - | TYPE ID COLON constant ARROW ID - | function_declaration - | TYPE ID COLON id_or_types ARROW id_or_types - | ID parameter ASSIGN sblock - ; + TYPE ID COLON + { + + printdebug("Currently see a record definition for %s", $2); + tn = CreateEntry(getAncestor(cur),TYPE_RECORD_TYPE, recprime, $2, CreateRecordInfo(0, cur = CreateScope(cur, 0, 0))); + printdebug("Created a new scope"); + //if (look_up(cur, $2) == undefined) { + // printdebug("rec not found"); + //} + } + dblock + { + //We are scanning through the dblock scope to get the length of the dblock (num of elements) from getRecSize + //and then putting it in the entry that we created above. + setRecSize(look_up(getParent(cur), $2), getRecSize(cur)); + //putting in all the offsets + setRecOffsetInfo(cur, look_up(getParent(cur),$2)); + printdebug("Moving up a scope after seeing a record definition"); + cur = getParent(cur); + } + + | TYPE ID COLON C_INTEGER ARROW id_or_types + { + printdebug("Currently see a array definition of name %s,storing type %s, of dimensions %d", $2, getName((TableNode*)$6), $4); + CreateEntry(cur,TYPE_ARRAY_TYPE, arrayprim, $2, CreateArrayInfo($4, (TableNode*)$6)); + printdebug("%sID: %s, dimensions: %d, typeOfArray: %s", COLOR_GREEN, $2, $4, getName((TableNode*)$6)); + } + + | function_declaration + + | TYPE ID COLON id_or_types ARROW id_or_types + { + printdebug("Currently see a function type definition of name %s,parameter type %s, of return type %s", $2, getName((TableNode*)$4), getName((TableNode*)$6)); + CreateEntry(cur,TYPE_FUNCTION_TYPE,funtypeprime,$2,CreateFunctionTypeInfo((TableNode*)$4 ,(TableNode*)$6)); + } + + | ID { + printdebug("see function def rule 1\n"); + TableNode *node = table_lookup(getAncestor(cur), $1); + if (node == undefined) { + printdebug("Undefined node declared."); + }else if(getAdInfoType(node) != TYPE_FUNCTION_DECLARATION){ + throw_error(ERROR_SYNTAX, "Not a valid function declaration."); + } + else { + printdebug("setting as keyword to true"); + setStartLine(node, @1.first_line); + setAsKeyword(node, true); + } + cur = CreateScope(cur, 0, 0); + printdebug("Created a new scope"); + } L_PAREN { + TableNode * parameter = getParameter(getTypeEntry(table_lookup(getAncestor(cur), $1))); + //TableNode *parameter = getParameter(table_lookup(getAncestor(cur), getType(table_lookup(getAncestor(cur), $1)))); + printdebug("type of parameter: %s", getName(parameter)); + if (parameter == undefined) { + throw_error(ERROR_TYPE, "Undefined parameter in function definition."); + }else if(getAdInfoType(parameter) != TYPE_RECORD_TYPE){ + int type_of_param_type = getAdInfoType(parameter);//this is an enum value defined in symbol_table.h + if( type_of_param_type == TYPE_UNDEFINED + || type_of_param_type == TYPE_FUNCTION_DECLARATION + || type_of_param_type == TYPE_ARRAY + || type_of_param_type == TYPE_PRIMITIVE + || type_of_param_type == TYPE_ALL_ELSE + || type_of_param_type == TYPE_SYSTEM_DEFINED + || type_of_param_type == TYPE_RECORD + || type_of_param_type == TYPE_STRING){ // note that strings are actually arrays so this is unused + throw_error(ERROR_TYPE, "Invalid type (%s) of parameter in function definition.", getAdInfo(parameter)); + type_of_param_type = TYPE_UNDEFINED; // setting tag as undefined in these cases + } + if(type_of_param_type == TYPE_UNDEFINED){ + CreateEntry(cur,type_of_param_type, undefined, NULL, NULL); + } else { + if(type_of_param_type == TYPE_FUNCTION_TYPE){ + CreateEntry(cur, TYPE_FUNCTION_DECLARATION, parameter,NULL, getAdInfo(parameter)); + } + if(type_of_param_type == TYPE_ARRAY_TYPE){ + CreateEntry(cur, TYPE_ARRAY, parameter,NULL, getAdInfo(parameter)); + } + if(type_of_param_type == TYPE_PRIMITIVE_TYPE){ + CreateEntry(cur, TYPE_PRIMITIVE, parameter,NULL, getAdInfo(parameter)); + } + } + } else { + printdebug("record found"); + for (TableNode* entry = getFirstEntry(getRecList(parameter)); entry!= NULL; entry = getNextEntry(entry)){ + int type_of_param_type = getAdInfoType(entry); + if( type_of_param_type == TYPE_UNDEFINED + || type_of_param_type == TYPE_FUNCTION_TYPE + || type_of_param_type == TYPE_ARRAY_TYPE + || type_of_param_type == TYPE_PRIMITIVE_TYPE + || type_of_param_type == TYPE_ALL_ELSE + || type_of_param_type == TYPE_SYSTEM_DEFINED + || type_of_param_type == TYPE_RECORD_TYPE + || type_of_param_type == TYPE_STRING){ // note that strings are actually arrays so this is unused + throw_error(ERROR_TYPE, "Invalid type (%s) of parameter in function definition.", getAdInfo(entry)); + type_of_param_type = TYPE_UNDEFINED; // setting tag as undefined in these cases + }else{ + printdebug("type of parameter correctly being passed in to AS function definition is %s which is valid", getType(entry)); + } + if(type_of_param_type == TYPE_UNDEFINED){ + printdebug("undefined type of parameter inside record"); + CreateEntry(cur,type_of_param_type, undefined, NULL, NULL); + } else { + if(type_of_param_type == TYPE_FUNCTION_DECLARATION){ + printdebug("function declaration of parameter inside record"); + CreateEntry(cur, TYPE_FUNCTION_DECLARATION, getTypeEntry(entry),NULL, getAdInfo(entry)); + } + if(type_of_param_type == TYPE_ARRAY){ + printdebug("array type of parameter inside record"); + CreateEntry(cur, TYPE_ARRAY, getTypeEntry(entry),NULL, getAdInfo(entry)); + } + if(type_of_param_type == TYPE_PRIMITIVE){ + printdebug("primitive type of parameter inside record"); + CreateEntry(cur, TYPE_PRIMITIVE, getTypeEntry(entry),NULL, getAdInfo(entry)); + } + /*printdebug("creating entry of type %s for function", getType(entry)); + CreateEntry(cur, getTypeEntry(entry), "undefined", NULL);*/ + } + } + } + //counter = 0; + printdebug("Created a new scope after seeing a function definition"); + } idlist R_PAREN ASSIGN sblock { + TableNode *expected = getReturn(getTypeEntry(look_up(cur, $1))); + if ($8 == undefined) { + throw_error(ERROR_TYPE, "Expected %s as return type but got undefined (possibly NULL). Differing return types in function.", getName(expected)); + } else if ($8 != expected) { + throw_error(ERROR_TYPE, "Expected %s as return type but got %s. Differing return types in function.", getName(expected), getName($8)); + } else { + printdebug("CORRECT RETURN TYPE!!!"); + } + } + + ; function_declaration: - FUNCTION ID COLON ID - | EXTERNAL FUNCTION ID COLON ID - ; + FUNCTION ID COLON ID + { + if(getAdInfoType(look_up(cur, $4))==TYPE_FUNCTION_TYPE){ + CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $4), $2, CreateFunctionDeclarationInfo(-1, false)); + } + else{ + throw_error(ERROR_TYPE, "Function declatation (%s) is not a valid function type", $2); + CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $4), $2, CreateFunctionDeclarationInfo(-1, false)); + + } + } + + | EXTERNAL FUNCTION ID COLON ID + { + if(getAdInfoType(look_up(cur, $5))==TYPE_FUNCTION_TYPE){ + CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $5), $3, CreateFunctionDeclarationInfo(-1, false)); + } + else{ + throw_error(ERROR_TYPE, "Function declatation (%s) is not a valid function type", $3); + CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $5), $3, CreateFunctionDeclarationInfo(-1, false)); + + } + } + + ; + -parameter: - L_PAREN ID R_PAREN - | AS L_PAREN idlist R_PAREN - ; idlist: - ID COMMA idlist - | ID - ; + ID + { + printdebug("idlist rule 1 ID: %s", $1); + TableNode *entry = getFirstEntry(cur); + while((getName(entry) != getName(undefined))){ + entry = getNextEntry(entry); + } + if (entry == NULL){ + printdebug("mismatch in number of parameters passed to function"); + } + else if(entry->theName == NULL){ + addName(entry, $1); + printdebug("name added to entry of type %s is %s in function parameter scope",getType(entry), $1); + } else { + printdebug("undefined types passed in to function scope. Improper."); + addName(entry, $1); + } + printTableNode(entry); + //while (strcmp(getName(entry),"undefined") != 0) { + // entry = getNextEntry(entry); + //} + //if (getNextEntry(entry) == NULL) { + // printdebug("too many parameters at line %d column %d", @1.first_line, @1.first_column); + //} + //addName(entry, $1); + //printdebug("name added to entry is %s", $1); + //printTableNode(entry); + } + COMMA idlist + { + $$ = $4 + 1; + } + + | ID + { printdebug("idlist rule 2 ID: %s", $1); + TableNode *entry = getFirstEntry(cur); + while((getName(entry) != getName(undefined))){ + entry = getNextEntry(entry); + } + if (entry == NULL){ + printdebug("mismatch in number of parameters passed to function"); + } + else if(entry->theName == NULL){ + addName(entry, $1); + printdebug("name added to entry of type %s is %s in function parameter scope",getType(entry), $1); + } else { + printdebug("undefined types passed in to function scope. Improper."); + addName(entry, $1); + } + printTableNode(entry); + printdebug("Name of entry is now %s", getName(entry)); + printdebug("Type of entry is %s", getType(entry)); + printdebug("tag is %d", getAdInfoType(entry)); + } + + | error { yyerrok; } + + ; + sblock: - L_BRACE {cur = CreateScope(cur,@1.first_line,@1.first_column);} statement_list {cur = getParent(cur);} R_BRACE - | L_BRACE {cur = CreateScope(cur,@1.first_line,@1.first_column);} dblock {printf("seen sblock with dblock\n");} statement_list {cur = getParent(cur);} R_BRACE - ; + L_BRACE + { + if (getLine(cur) != 0) { + cur = CreateScope(cur,@1.first_line,@1.first_column); + printdebug("Created a new scope"); + } else { + setLineNumber(cur, @1.first_line); + setColumnNumber(cur,@1.first_line); + } + } + statement_list + { + //$$ = $3; + printdebug("Moving up a scope after seeing sblock"); + cur = getParent(cur); + } + R_BRACE + {$$ = $3;} + + | L_BRACE + { + if (getLine(cur) != 0) { + cur = CreateScope(cur,@1.first_line,@1.first_column); + printdebug("Created a new scope when seeing an L brace"); + } else { + setLineNumber(cur, @1.first_line); + setColumnNumber(cur,@1.first_line); + printdebug("Did not create a new scope when saw L Brace, set line number to %d", @1.first_line); + } + } + dblock + { + printdebug("seen sblock with dblock"); + } + statement_list + { + printdebug("Moving up a scope after seeing sblock with dblock"); + cur = getParent(cur); + //$$ = $5; + + } + R_BRACE + {$$ = $5;} + + | error { yyerrok; } + + ; + + dblock: - L_BRACKET declaration_list R_BRACKET; + + L_BRACKET + { + if (getLine(cur) == 0) { + setLineNumber(cur, @1.first_line); + setColumnNumber(cur,@1.first_line); + printdebug("Did not create a new scope when saw dblock, set line number to %d instead", @1.first_line); + } else{ + //cur = CreateScope(cur,@1.first_line,@1.first_column); // <----- What is this? + printdebug("Created a new scope when seeing a dblock"); + } + } + declaration_list R_BRACKET + + | error { yyerrok; } + + ; + + declaration_list: - declaration SEMI_COLON declaration_list - | declaration - ; + declaration SEMI_COLON declaration_list + | declaration + + | error { yyerrok; } + + ; + + declaration: - id_or_types COLON ID {CreateEntry(cur,$1,$3); } - ; + id_or_types COLON ID + { + printdebug("ID/TYPE: %s, ID: %s", getName((TableNode*)$1), $3) ; + int d = getAdInfoType((TableNode*)$1); + if(d == TYPE_UNDEFINED) { + throw_error(ERROR_TYPE, "Undefined type passed in declaration list"); + printdebug("Undefined type passed in declaration list"); + CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1)); + } + else if(d == TYPE_FUNCTION_TYPE) { + printdebug("invalid (function) type passed in declaration list in dblock", @2.first_line, @2.first_column); + d = TYPE_FUNCTION_DECLARATION; + CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1)); + } + else if(d == TYPE_ARRAY_TYPE){ + printdebug("array variable at line %d and column %d", @2.first_line, @2.first_column); + d = TYPE_ARRAY; + CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1)); + } + else if(d == TYPE_RECORD_TYPE){ + printdebug("record variable at line %d and column %d", @2.first_line, @2.first_column); + d = TYPE_RECORD; + CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1)); + } + else if(d == TYPE_PRIMITIVE_TYPE){ + printdebug("primitive variable at line %d and column %d", @2.first_line, @2.first_column); + d = TYPE_PRIMITIVE; + CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1)); + }else { + throw_error(ERROR_TYPE, "%s is being defined with an undefined type", $3); + CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1)); + } + } + + | error { yyerrok; } + + ; + + id_or_types: - ID {printf("string of id in id_or_type is %s\n",$1);} {$$ = $1;} - | types {printf("string of type in id_or_type is %s\n",$1);} {$$ = $1;} - ; + ID + { + printdebug("string of id is %s in ID pattern of id_or_type rule.", $1); + $$ = table_lookup(getAncestor(cur), $1); + } + + | types + { + printdebug("string of type is %s in types pattern of id_or_type rule.",getName((TableNode*)$1)); + $$ = (TableNode*)$1; + } + + | error { yyerrok; } + + ; + + statement_list: - compound_statement statement_list - | compound_statement - | simple_statement SEMI_COLON statement_list - | simple_statement SEMI_COLON - ; +compound_statement statement_list { + if ($1 == undefined && $2 != undefined) { + $$ = $2; + } else if ($1 != undefined && $2 == undefined) { + $$ = $1; + } else if ($1 == $2) { + $$ = $1; + } else { + printdebug("differing return types within same function at line %d, column %d", @1.first_line, @1.first_column); + $$ = undefined; + } +} + | compound_statement { + $$ = $1; + } + | simple_statement SEMI_COLON statement_list{ + if ($1 == undefined && $3 != undefined) { + $$ = $3; + } else if ($1 != undefined && $3 == undefined) { + $$ = $1; + } else if ($1 == $3) { + $$ = $1; + } else { + printdebug("differing return types within same function at line %d, column %d", @1.first_line, @1.first_column); + $$ = undefined; + } + } + | simple_statement SEMI_COLON { + $$ = $1; + } + + ; + + compound_statement: - WHILE L_PAREN expression R_PAREN sblock - | IF L_PAREN expression R_PAREN THEN sblock ELSE sblock - | sblock //{printf("seen a compound statement rule\n");} - ; +WHILE L_PAREN expression R_PAREN sblock { + $$ = $5; +} + | IF L_PAREN expression R_PAREN THEN sblock ELSE sblock { + if ($6 == undefined && $8 != undefined) { + $$ = $8; + } else if ($6 != undefined && $8 == undefined) { + $$ = $6; + } else if ($6 == $8) { + $$ = $6; + } else { + printdebug("differing return types within same function at line %d, column %d", @1.first_line, @1.first_column); + $$ = undefined; + } + } + + | sblock { + $$ = $1; + } + + ; + + simple_statement: - assignable ASSIGN expression - | RETURN expression - ; + assignable ASSIGN expression + { printdebug("simple statement"); + TableNode* node; + if((getAdInfoType((TableNode*)$1) == TYPE_FUNCTION_DECLARATION)|| + (getAdInfoType((TableNode*)$1) == TYPE_ARRAY)|| + (getAdInfoType((TableNode*)$1) == TYPE_RECORD)|| + (getAdInfoType((TableNode*)$1) == TYPE_PRIMITIVE)){ + + node = ((TableNode*)$1); + } else{ + printdebug("Invalid type passed to assignable."); + node = undefined; + } -assignable: - ID - | assignable ablock - | assignable rec_op ID - ; -rec_op : - DOT + if(getAdInfoType(node) == getAdInfoType((TableNode*)$3)){ + emit_assignment($1, tn_or_const(NODE, $3)); + printdebug("%s[☺] Passed type check; %s = %s", COLOR_GREEN, getName(node), getName((TableNode*)$3)); + } else { + throw_error(ERROR_TYPE, "%s != %s", getName(node), getName((TableNode*)$3)); + } -expression: + $$ = undefined; + } - constant {printf("constant expression\n");} - | SUB_OR_NEG expression %prec UMINUS {printf("negative expression\n");} - | NOT expression {printf("not expression\n");} - | expression ADD expression {printf("add expression\n");} - | expression SUB_OR_NEG expression {printf("subtract expression\n");} - | expression MUL expression {printf("multiply expression\n");} - | expression DIV expression {printf("division expression\n");} - | expression REM expression {printf("remainder expression\n");} - | expression AND expression {printf("and expression\n");} - | expression OR expression {printf("or expression\n");} - | expression LESS_THAN expression {printf("less than expression\n");} - | expression EQUAL_TO expression {printf("equals check expression\n");} - | assignable {printf("assignable expression\n");} - | L_PAREN expression R_PAREN {printf("paren expression\n");} - | memOp assignable - ; + + | RETURN expression {$$ = getTypeEntry((TableNode*)$2);} + + | error { yyerrok; } + + ; + + + +rec_op: + DOT + + | error { yyerrok; } + + ; ablock: - L_PAREN argument_list R_PAREN - ; + L_PAREN argument_list R_PAREN + { + $$ = $2; + printdebug("ablock is %d", $$); + } + + | error { yyerrok; } + + ; + + argument_list: - expression COMMA argument_list - | expression - ; + //NEED TO EMIT PARAMETERS HERE. MAYBE USE STACK STRUCTURE + expression COMMA argument_list + { + CreateEntry(cur,getAdInfoType((TableNode*)$1), (TableNode*)$1, getName((TableNode*)$1), NULL); + $$ = $3 + 1; + printdebug("[ARGUMENT_LIST] argument list is %d", $$); + } + + | expression + { + CreateEntry(cur,getAdInfoType((TableNode*)$1),(TableNode*)$1, getName((TableNode*)$1), NULL); + $$ = 1; printdebug("[ARGUMENT_LIST] argument list is %d", $$); + } + + | error { yyerrok; } + + ; + + +// will ALWAYS be a TYPE +expression: + constant + { + printdebug("constant expression"); + $$ = (TableNode*)$1; + } + + | SUB_OR_NEG expression %prec UMINUS + { + printdebug("negative expression"); + if(getTypeEntry((TableNode*)$2) == integ) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); + emit_unary_op(E_NEG,node,tn_or_const(NODE,$2)); + //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) + //result of unary operation + $$ = node; + } else { + $$=undefined; + throw_error(ERROR_TYPE, "%s != %s", getName(getTypeEntry((TableNode*)$2)), getName(integ)); + } + } + + | NOT expression + { + printdebug("not expression"); + if(getTypeEntry((TableNode*)$2) == boo) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); + emit_unary_op(E_NOT,node,tn_or_const(NODE,$2)); + //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) + //result of unary operation + $$ = node; + } else { + $$=undefined; + throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$2), getName(boo)); + } + } + + | expression ADD expression + { + printdebug("add expression"); + if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); + emit_binary_op(E_ADD,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); + $$ = node; + } else { + $$=undefined; + throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); + } + } + + | expression SUB_OR_NEG expression + { + printdebug("sub or neg expression"); + if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); + emit_binary_op(E_SUB,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); + + $$ = node; + } else { + $$=undefined; + throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); + } + } + + | expression MUL expression + { + printdebug("multiply expression"); + if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); + emit_binary_op(E_MUL,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); + $$ = node; + } else { + $$=undefined; + throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); + } + } + + | expression DIV expression + { + printdebug("divide expression"); + if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); + emit_binary_op(E_DIV,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); + $$ = node; + } else { + $$=undefined; + throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); + } + } + + | expression REM expression + { + printdebug("remainder expression"); + if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); + emit_binary_op(E_MOD,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); + $$ = node; + } else { + $$=undefined; + throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); + } + } + + | expression AND expression + { + printdebug("AND"); + if((getTypeEntry((TableNode*)$1)==getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == boo) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); + emit_binary_op(E_AND,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); + $$ = node; + } else { + $$=undefined; + throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); + } + } + + | expression OR expression + { + printdebug("OR"); + if((getTypeEntry((TableNode*)$1)==getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == boo) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); + emit_binary_op(E_OR,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); + $$ = node; + } else { + $$=undefined; + throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); + } + } + + | expression LESS_THAN expression + { + printdebug("less than expression"); + if(getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3) && getTypeEntry((TableNode*)$1)==integ) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); + emit_binary_op(E_LESS_THAN,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); + $$ = node; + } else { + $$=undefined; + throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); + } + } + + | expression EQUAL_TO expression + { + printdebug("equals check expression"); + if(getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3) && getTypeEntry((TableNode*)$1) != undefined) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); + emit_binary_op(E_EQUAL_TO,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); + $$ = node; + + } else { + $$ = undefined; + throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); + } + } + + | assignable + { + $$ = $1; + } + + | L_PAREN expression R_PAREN + { + printdebug("paren expression. current type is %s",getType((TableNode*)$2)); + $$=$2; + } + + | memOp assignable + { + int d = getAdInfoType((TableNode*)$2); + if(d == TYPE_ARRAY ||d == TYPE_RECORD) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, addr, temp, NULL); + //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) + $$ = node; + } else { + throw_error(ERROR_TYPE, "Invalid memOp expression (%s).", getName((TableNode*)$2)); + $$=undefined; + } + } + + | error { yyerrok; } + + ; + +//UPDATED $$ for tablenodes to this point + +// prolly right, check back with me later +// add array case +// include type check for ablock in arrays - ablock is always the int of the elements in array/rec +assignable: + ID + { + TableNode* pass = look_up(cur,$1); + if(pass == undefined){ + throw_error(ERROR_TYPE, "Undefined variable %s", $1); + } + $$ = pass; + printdebug("[ASSIGNABLE - RULE 1] assignable = type: %s | ID = %s", getType(pass), getName(pass)); + } + + | assignable + { + printdebug("%sBeginning rule 2 of assignable.", COLOR_CYAN); + cur = CreateScope(cur, -1,-1); + } + //we have to consider emmissions in ablocks + ablock + { + //int type = getAdInfoType(look_up(getParent(cur), getName((TableNode*)$1))); + int type = getAdInfoType(getTypeEntry((TableNode*)$1)); + printdebug("%stype is %d", COLOR_PURPLE, type); + printdebug("%s", getName((TableNode*)$1)); + + if (type == TYPE_FUNCTION_TYPE) { + printdebug("%sEntering function call", COLOR_LIGHTGREEN); + if (look_up(getParent(cur), getType((TableNode*)$1))->additionalinfo->FunDecAdInfo->regularoras) { + printdebug("as function"); + //char *funtype = getType(look_up(cur, $1)); + //printdebug("%s", getType(look_up(cur, getName((TableNode*)$1)))); + + + + TableNode * typeNode = getTypeEntry((TableNode*)$1); + TableNode *param = getParameter(typeNode); + printTableNode(param); + + if (getAdInfoType(param) == TYPE_RECORD_TYPE) { + SymbolTable *recList = getRecList(param); + TableNode *lastCheckedRef = getFirstEntry(recList); + TableNode *lastCheckedAct = getFirstEntry(cur); + while (getNextEntry(lastCheckedRef) != NULL) { + lastCheckedRef = getNextEntry(lastCheckedRef); + } + + if ($3 != getRecLength(param)) { + printdebug("expected %d arguments but got %d", getRecLength(param), $3); + } + //this isn't very efficient, but will hopefully work + while (lastCheckedAct != NULL && lastCheckedRef != NULL) { + if (getTypeEntry(lastCheckedRef) != getTypeEntry(lastCheckedAct)) { + printdebug("expected %s. expression in function call got %s. at line %d and column %d",getType(lastCheckedRef), getName(lastCheckedAct), @3.first_line, @3.first_column); + + } + lastCheckedAct = getNextEntry(lastCheckedAct); + TableNode *tn = getFirstEntry(recList); + + if (tn != lastCheckedRef) { + while (getNextEntry(tn) != lastCheckedRef) { + tn = getNextEntry(tn); + } + lastCheckedRef = tn; + } else {break;} + } + } else { + if (strcmp(getName(param), getName(getFirstEntry(cur))) != 0) { + printdebug("expected %s expression in function call but got %s", getName(param), getName(getFirstEntry(cur))); + } + + if (getNextEntry(getFirstEntry(cur)) != NULL) { + printdebug("expected 1 parameter, but got multiple in function call"); + } + } + } else { + char *expected = getName(getParameter(look_up(getParent(cur), getType((TableNode*)$1)))); + char *actual = getType(getFirstEntry(cur)); + if (strcmp(expected, actual) != 0) { + printdebug("expected %s expression in function call but got %s at line %d and column %d",expected, actual, @3.first_line, @3.first_column); + } + if ($3 != 1) { + printdebug("expected 1 argument but got %d", $3); + } + } + printTableNode(getReturn(getTypeEntry((TableNode*)$1))); + // + char* temp = temp_var_gen(); + TableNode* typeNode2 = getReturn(getTypeEntry($1)); + int t = -1; + if(getAdInfoType(typeNode2) == TYPE_PRIMITIVE_TYPE){ + t = TYPE_PRIMITIVE; + } + else if(getAdInfoType(typeNode2) == TYPE_ARRAY_TYPE){ + t = TYPE_ARRAY; + } + else if(getAdInfoType(typeNode2) == TYPE_RECORD_TYPE){ + t = TYPE_RECORD; + } + else if(getAdInfoType(typeNode2) == TYPE_FUNCTION_TYPE){ + t = TYPE_FUNCTION_DECLARATION; + }else{ + t= TYPE_UNDEFINED; + printdebug("CHANGE ME [TYPE CHECK] Undefined type stored in record. improper."); + } + TableNode* node = CreateEntry(cur,t, typeNode2, temp, NULL); + $$ = node; + //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK for function call) + printdebug("[ASSIGNABLE - RULE 2] assignable = type: %s | name_func = %s", getName(typeNode2), getName((TableNode*)$1)); + + } else if (type == TYPE_ARRAY_TYPE) { + printdebug("%sEntering array call", COLOR_LIGHTGREEN); + if (getNumArrDim(look_up(getParent(cur), getType((TableNode*)$1))) != $2) { + printdebug("expected %d arguments but had %d at line %d and column %d\n", getNumArrDim(look_up(cur, getName((TableNode*)$1))), $2, @2.first_line, @2.first_column); + } + + char* temp = temp_var_gen(); + TableNode* typeNode2 = getArrType(look_up(getAncestor(cur), getType((TableNode*)$1))); + int t = -1; + if(getAdInfoType(typeNode2) == TYPE_PRIMITIVE_TYPE){ + t = TYPE_PRIMITIVE; + } + else if(getAdInfoType(typeNode2) == TYPE_ARRAY_TYPE){ + t = TYPE_ARRAY; + } + else if(getAdInfoType(typeNode2) == TYPE_RECORD_TYPE){ + t = TYPE_RECORD; + } + else if(getAdInfoType(typeNode2) == TYPE_FUNCTION_TYPE){ + t = TYPE_FUNCTION_DECLARATION; + }else{ + t= TYPE_UNDEFINED; + printdebug("CHANGE ME [TYPE CHECK] Undefined type stored in record. improper."); + } + TableNode* node = CreateEntry(cur,t, typeNode2, temp, NULL); + //emit assign here + //emit_array_access(char* node, char* array, ...) + $$ = node; + printdebug("[ASSIGNABLE - RULE 2] assignable = type: %s | name_func = %s", getType((TableNode*)$1), getName((TableNode*)$1)); + } + cur = getParent(cur); + } + + | assignable rec_op ID + { + if(getAdInfoType((TableNode*)$1) != TYPE_RECORD_TYPE){ + printdebug("CHANGE ME [TYPE CHECK]Invalid type passed to record access"); + } + else if(undefined != table_lookup(getRecList(table_lookup(getAncestor(cur), getName(getTypeEntry((TableNode*)$1)))), $3)) { + + TableNode* type = table_lookup(getRecList(table_lookup(getAncestor(cur), getName(getTypeEntry((TableNode*)$1)))), $3); + char* temp = temp_var_gen(); + int t = -1; + if(getAdInfoType(type) == TYPE_PRIMITIVE_TYPE){ + t = TYPE_PRIMITIVE; + } + else if(getAdInfoType(type) == TYPE_ARRAY_TYPE){ + t = TYPE_ARRAY; + } + else if(getAdInfoType(type) == TYPE_RECORD_TYPE){ + t = TYPE_RECORD; + } + else if(getAdInfoType(type) == TYPE_FUNCTION_TYPE){ + t = TYPE_FUNCTION_DECLARATION; + }else{ + t= TYPE_UNDEFINED; + printdebug("CHANGE ME [TYPE CHECK] Undefined type stored in record. improper."); + } + + TableNode* node = CreateEntry(cur,t, type, temp, NULL); + //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) + //emit_field_access(char* node, char* record, $3) + $$=node; + }else{ + printdebug("CHANGE ME [TYPE CHECK] undefined type (Field Access Lookup failed)"); + $$=undefined; + } + printdebug("[ASSIGNABLE - RULE 3] record = name: %s | field = %s", getName((TableNode*)($1)), getName((TableNode*)$3)); + } + + | error { yyerrok; } + + ; + memOp: - RESERVE {printf("reserve expression\n");} - | RELEASE {printf("release expression\n");} - ; + RESERVE + { + printdebug("reserve expression"); + } + + | RELEASE + { + printdebug("release expression"); + } + + | error { yyerrok; } + + ; constant: - C_STRING - | C_INTEGER - | C_NULL - | C_CHARACTER - | C_TRUE - | C_FALSE - ; + C_STRING + { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, stri, temp, NULL); + emit_assignment(node, tn_or_const(STRING,$1)); + printdebug("string of C_STRING in constant is %s", $1); + $$ = node; + } -types: - T_STRING {printf("string of T_STRING in types is %s\n",$1);} {$$ = $1;} - | T_INTEGER {printf("string of T_INTEGER in types is %s\n",$1);} {$$ = $1;} - | T_ADDRESS {printf("string of T_ADDRESS in types is %s\n",$1);} {$$ = $1;} - | T_CHARACTER {printf("string of T_CHARACTER in types is %s\n",$1);} {$$ = $1;} - | T_BOOLEAN {printf("string of T_BOOLEAN in types is %s\n",$1);} {$$ = $1;} - ; + | C_INTEGER + { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); + emit_assignment(node, tn_or_const(INTEGER,&$1)); + printdebug("number of C_INTEGER in constant is %d", $1); + $$ = node; + } + + | C_NULL + { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, addr, temp, NULL); + emit_assignment(node, tn_or_const(ADDRESS,$1)); + printdebug("string of C_NULL in constant is NULL"); + $$ = node; + } + + | C_CHARACTER + { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, chara, temp, NULL); + emit_assignment(node, tn_or_const(CHARACTER,&$1)); + printdebug("string of C_CHARACTER in constant is %s",$1); + $$ = node; + } + + | C_TRUE + { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); + uint_least8_t b = 1; + emit_assignment(node, tn_or_const(BOOLEAN,&b)); + printdebug("string of C_TRUE in constant is true"); + $$ = node; + } + + | C_FALSE + { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); + uint_least8_t b = 0; + emit_assignment(node, tn_or_const(BOOLEAN,&b)); + printdebug("string of C_FALSE in constant is false"); + $$ = node; + } + + ; + + + +types: + T_INTEGER + { + $$ = $1; + printdebug("string of T_INTEGER in types is %s",getName((TableNode*)$1)); + } + + | T_ADDRESS + { + $$ = $1; + printdebug("string of T_ADDRESS in types is %s",getName((TableNode*)$1)); + } + + | T_CHARACTER + { + $$ = $1; + printdebug("string of T_CHARACTER in types is %s",getName((TableNode*)$1)); + } + + | T_BOOLEAN + { + $$ = $1; + printdebug("string of T_BOOLEAN in types is %s",getName((TableNode*)$1)); + } + ; %% -void yyerror(const char *err) { - fprintf(stderr, "ERROR: %s at token %s at line number %d,column number %d\n", err,yytext,yylloc.first_line,yylloc.first_column); -} -/* -int main(int argc, char * argv[]) { - token_tracker = 1; - cur=CreateScope(NULL,1,1); - //int a; - FILE * fp; - if(argc > 1){ - fp = fopen(argv[1], "r"); - yyin = fp; - } else { - fp = stdin; - yyin = fp; + + +void throw_error(ErrorType error_type, const char *format, ...) { + int line = yylloc.first_line; + int column = yylloc.first_column; + + char * error_name = ""; + + switch (error_type) { + case ERROR_RUNTIME: + error_name = malloc(strlen("RUNTIME") + 1); + strcpy(error_name, "RUNTIME"); + break; + case ERROR_SYNTAX: + error_name = malloc(strlen("SYNTAX") + 1); + strcpy(error_name, "SYNTAX"); + break; + case ERROR_TYPE: + error_name = malloc(strlen("TYPE") + 1); + strcpy(error_name, "TYPE"); + break; + case ERROR_UNDEFINED: + error_name = malloc(strlen("UNDEFINED") + 1); + strcpy(error_name, "UNDEFINED"); + break; + } + + if (asc_flag) { + /* yyerror(""); */ + int needed = snprintf(NULL, 0, " LINE (%d:%d) ** %s ERROR: ", line, column, error_name); + char *error_message = malloc(needed + 1); + snprintf(error_message, needed + 1, " LINE (%d:%d) ** %s ERROR: ", line, column, error_name); + + va_list args; + va_start(args, format); + va_list args_copy; + va_copy(args_copy, args); + int needed2 = vsnprintf(NULL, 0, format, args_copy) + 1; + va_end(args_copy); + + char *error_message2 = malloc(needed2); + if (error_message2 == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + va_end(args); + return; } - yyparse(); - //while ((a = yyparse() != EOF){ - // token_tracker++; - //printf("%d = a: yytext = %s: yychar = %d, token number: %d\n", a, yytext, yychar,token_tracker); - //if(yytext[0] == '\n'){ - FILE* f = fdopen(1,"w"); - print_symbol_table(getAncestor(cur),f); - fclose(f); - // break; - //} - //} - return 0; -} */ + + vsnprintf(error_message2, needed2, format, args); + va_end(args); + + int total_needed = needed + needed2 + 2; + char *total_error_message = malloc(total_needed); + if (total_error_message == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + free(error_message); + free(error_message2); + return; + } + + snprintf(total_error_message, total_needed, "%s%s\n\n", error_message, error_message2); + if (tc_flag) { + insert_code_line(total_error_message, line); + } else { + if (error_type != ERROR_TYPE) { + insert_code_line(total_error_message, line); + } + } + + free(error_message); + free(error_message2); + free(total_error_message); + } +} + +void yyerror(const char *err) { + int line = yylloc.first_line; + int column = yylloc.first_column; + + // Grammar Fallback Case + if (strcmp(err, "syntax error") == 0) { + if (asc_flag != NULL) { + int needed = snprintf(NULL, 0, " LINE (%d:%d) ** SYNTAX ERROR: Incorrect syntax at token '%s'\n\n", line, column, yytext); + char *error_message = malloc(needed + 1); + snprintf(error_message, needed + 1, " LINE (%d:%d) ** SYNTAX ERROR: Incorrect syntax at token '%s'\n\n", line, column, yytext); + insert_code_line(error_message, line); + } + else { + fprintf(stderr, " LINE (%d:%d) ** SYNTAX ERROR: Incorrect syntax at token %s\n", line, column, yytext); + } + } +} diff --git a/src/intermediate_code.c b/src/intermediate_code.c new file mode 100644 index 0000000..9948115 --- /dev/null +++ b/src/intermediate_code.c @@ -0,0 +1,400 @@ +/* Intermediate Code */ +/* The Translators - Spring 2025 */ + +#include "intermediate_code.h" + +// TODO: this is here to bring your attention to the comment bellow. +// check if start is NULL if it is assign it to the start globle variable +// otherwise make it next of current and set cur to your instruction. +TNodeOrConst* getOperand1(Instruction* i) { + return i->operand1; +} + +TNodeOrConst* getOperand2(Instruction* i) { + return i->operand2; +} + +TableNode* getResult(Instruction* i) { + return i->result; +} + +Op getOp(Instruction* i) { + return i->opcode; +} + +int getLabel(Instruction* i) { + return i->label; +} + +int get_index(Instruction* i) { + return i->index; +} + +void set_label(Instruction* i, int label) { + i->label = label; +} + +bool isConst(TNodeOrConst* tnc) { + return tnc->d != NODE; +} + +TNodeOrConst* tn_or_const(Discriminant d, void* tnc) { + TNodeOrConst* count = calloc(1, sizeof(*count)); + count->d = d; + count->tnc_union = calloc(1, sizeof(*count->tnc_union)); + switch (d) { + case NODE: + count->tnc_union->node = tnc; + break; + case ADDRESS: + count->tnc_union->address = tnc; + break; + case STRING: + count->tnc_union->string = tnc; + break; + case INTEGER: + count->tnc_union->integer = *(int*)tnc; + break; + case CHARACTER: + count->tnc_union->character = *(char*)tnc; + break; + case BOOLEAN: + count->tnc_union->Boolean = *(uint_least8_t*)tnc; + break; + } + return count; +} + +static void emit_helper(void) { + Instruction* inst = calloc(1, sizeof(*inst)); + if (begin == NULL) { + begin = current = inst; + current->index = 1; + } else { + current->next = inst; + inst->prev = current; + inst->index = current->index + 1; + current = inst; + } +} + +void emit_binary_op(Op op, TableNode* result, TNodeOrConst* arg1, TNodeOrConst* arg2) { + emit_helper(); + current->opcode = op; + // TODO: create temp and remove result from param list + current->result = result; + current->operand1 = arg1; + current->operand2 = arg2; +} + +void emit_unary_op(Op op, TableNode* result, TNodeOrConst* arg) { + emit_helper(); + current->opcode = op; + current->result = result; + current->operand1 = arg; +} + +void emit_assignment(TableNode* target, TNodeOrConst* source) { + emit_helper(); + current->opcode = E_ASSIGN; + current->result = target; + current->operand1 = source; +} + +char* get_string(TNodeOrConst* tc) { + char* s; + switch (tc->d) { + case NODE: + return getName(tc->tnc_union->node); + case ADDRESS: + return strdup("null"); + case STRING: + return tc->tnc_union->string; + case INTEGER: + s = calloc(10, sizeof(char)); + sprintf(s, "%d", tc->tnc_union->integer); + return s; + case CHARACTER: + s = calloc(2, sizeof(char)); + sprintf(s, "%c", tc->tnc_union->character); + return s; + case BOOLEAN: + if (tc->tnc_union->Boolean) { + return strdup("true"); + } + return strdup("false"); + } +} + +void emit_as_file(FILE* out_file, Instruction* i) { + if (i == NULL) { + return; + } + switch (i->opcode) { + case E_LABEL: + break; + // this is a terrible one to start with + // fprintf(out_file, "%04.d: %d ", i->index, i->label); + case E_ADD: + fprintf(out_file, "%4.d: %s = %s + %s\n", + i->index, getName(i->result), + get_string(i->operand1), + get_string(i->operand2)); + break; + case E_SUB: + fprintf(out_file, "%4.d: %s = %s - %s\n", + i->index, getName(i->result), + get_string(i->operand1), + get_string(i->operand2)); + break; + case E_MUL: + fprintf(out_file, "%4.d: %s = %s * %s\n", + i->index, getName(i->result), + get_string(i->operand1), + get_string(i->operand2)); + break; + case E_DIV: + fprintf(out_file, "%4.d: %s = %s / %s\n", + i->index, getName(i->result), + get_string(i->operand1), + get_string(i->operand2)); + break; + case E_MOD: + fprintf(out_file, "%4.d: %s = %s %% %s\n", + i->index, getName(i->result), + get_string(i->operand1), + get_string(i->operand2)); + break; + case E_OR: + fprintf(out_file, "%4.d: %s = %s | %s\n", + i->index, getName(i->result), + get_string(i->operand1), + get_string(i->operand2)); + break; + case E_AND: + fprintf(out_file, "%4.d: %s = %s & %s\n", + i->index, getName(i->result), + get_string(i->operand1), + get_string(i->operand2)); + break; + case E_NEG: + fprintf(out_file, "%4.d: %s = -%s\n", + i->index, getName(i->result), + get_string(i->operand1)); + break; + case E_NOT: + fprintf(out_file, "%4.d: %s = !%s\n", + i->index, getName(i->result), + get_string(i->operand1)); + break; + case E_ASSIGN: + fprintf(out_file, "%4.d: %s = %s\n", + i->index, getName(i->result), + get_string(i->operand1)); + break; + case E_GOTO: + // are we ever going to use this? + // yes we do look at bounds checking + case E_IF_X_TRUE: + fprintf(out_file, "%4.d: if %s goto %d\n", + i->index, get_string(i->operand1), + i->label); + break; + case E_IF_X_FALSE: + fprintf(out_file, "%4.d: if %s false goto %d\n", + i->index, get_string(i->operand1), + i->label); + break; + case E_LESS_THAN: + fprintf(out_file, "%4.d: if %s < %s goto %d\n", + i->index, get_string(i->operand1), + get_string(i->operand2), i->label); + break; + case E_EQUAL_TO: + fprintf(out_file, "%4.d: if %s = %s goto %d\n", + i->index, get_string(i->operand1), + get_string(i->operand2), i->label); + break; + case E_CALL: + fprintf(out_file, "%4.d: call %s %s\n", + i->index, get_string(i->operand1), + get_string(i->operand2)); + break; + + case E_PARAM: + fprintf(out_file, "%4.d: param %s \n", + i->index, get_string(i->operand1)); + break; + case E_RETURN: + + case E_INDEX_COPY_RIGHT: + case E_INDEX_COPY_LEFT: + + case E_ADDRESS_OF: + + case E_DEREF_RIGHT: + case E_DEREF_LEFT: + } + + emit_as_file(out_file, i->next); +} + +void emit_label(int label) { + emit_helper(); + current->opcode = E_LABEL; + current->label = label; +} + +void emit_jump(int label) { + emit_helper(); + current->opcode = E_GOTO; + current->label = label; +} + +void emit_conditional_jump(Op condition, int label, ...) { + // when this instruction is a conditional jump then the imput looks like (Op, int, TNodeOrConst *). + // when the inst is a cond with a Relational operation then the input looks like (Op, int, TNodeOrConst *, TNodeOrConst *) + emit_helper(); + va_list argptr; + va_start(argptr, label); + current->opcode = condition; + current->label = label; + TNodeOrConst* n1; + TNodeOrConst* n2; + switch (condition) { + case E_IF_X_TRUE: + case E_IF_X_FALSE: + n1 = va_arg(argptr, TNodeOrConst*); + current->operand1 = n1; + break; + case E_LESS_THAN: + case E_EQUAL_TO: + n1 = va_arg(argptr, TNodeOrConst*); + n2 = va_arg(argptr, TNodeOrConst*); + current->operand1 = n1; + current->operand2 = n2; + break; + } + va_end(argptr); +} + +void emit_function_start(TNodeOrConst * name) { + emit_helper(); + current->opcode = E_LABEL; // I think this is right TODO: ask + current->operand1 = name; + // this is probabaly a func declaration +} + +void emit_parameter(TNodeOrConst* param) { + emit_helper(); + current->opcode = E_PARAM; + current->operand1 = param; +} + +void emit_function_call(TableNode* result, int param_count, TNodeOrConst* name) { + emit_helper(); + current->opcode = E_CALL; + current->operand1 = tn_or_const(INTEGER, ¶m_count); + current->operand2 = name; + current->result = result; +} + +void emit_return(TNodeOrConst* value) { + emit_helper(); + current->opcode = E_RETURN; + current->operand1 = value; +} + +void emit_reserve(TableNode* result, TNodeOrConst* size) { + emit_parameter(size); + emit_function_call(result, 1, tn_or_const(NODE, look_up(cur, "reserve"))); +} + +void emit_release(TableNode* pointer) { + emit_parameter(tn_or_const(NODE, pointer)); + emit_function_call(pointer, 1, tn_or_const(NODE, look_up(cur, "release"))); +} + +void emit_deref_right() { + return; +} + +void emit_deref_left() { + return; +} + +void emit_field_access(char* result, char* record, char* field) { + emit_helper(); +} + +void emit_array_access(Op op, TableNode* result, TNodeOrConst* array, TNodeOrConst* index) { + emit_helper(); + current->opcode; + current->result = result; + current->operand1 = array; + current->operand2 = index; + // TODO: Still don't know what to do with the dimentions +} + +void emit_bounds_check(TNodeOrConst* index, TNodeOrConst* arr) { + /* + {[string: 5] + . + . + s:= reserve s(5); + s(0) := 'H'; + s(1) := 'e'; + . + . + s._0 num of dims Known at compile time + s._1 size Known at run time + s._1 int | 1 byte + +-------+---+---+---+---+---+ + | 5 | H | e | l | l | o | + +-------+---+---+---+---+---+ + size + ^ + | + p + s._0 ok + s._1 ok + s._2 not ok + t_0 is index + t_1 = *(int *)p = s._1 + if t_0 < 0 GOTO ERROR + if t_0 < s._1 GOTO access array + GOTO ERROR + */ + //emit_conditional_jump(E_LESS_THAN, ); + //emit_conditional_jump(E_LESS_THAN, ); + //emit_jump(); + /* We need a label ERROR to jump to + */ +} + +/*// * Implement temp variable generator function that produces unique names (t1, t2, etc.) +char * temp_var_gen(){ + char * ret = calloc(9, sizeof(*ret)); + sprintf(ret, "$t%d", temp_count); + temp_count++; + return ret; +} +*/ +int label_gen(){ + label_count++; + return label_count; +} + +TableNode* getTN(TNodeOrConst* tnc) { + if (tnc->d == NODE) { + return tnc->tnc_union->node; + } + return NULL; +} + +int getConst(TNodeOrConst* tnc) { + if (tnc->d == INTEGER) { + return tnc->tnc_union->integer; + } + return -1; +} \ No newline at end of file diff --git a/src/intermediate_code.h b/src/intermediate_code.h new file mode 100644 index 0000000..c1efb76 --- /dev/null +++ b/src/intermediate_code.h @@ -0,0 +1,124 @@ +/* Intermediate Code */ +/* The Translators - Spring 2025 */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "symbol_table.h" + +// 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; + +TNodeOrConst* getOperand1(Instruction* i); +TNodeOrConst* getOperand2(Instruction* i); +TableNode* getResult(Instruction* i); +Op getOp(Instruction* i); +int getLabel(Instruction* i); +int get_index(Instruction* i); +void set_label(Instruction* i, int label); +bool isConst(TNodeOrConst* tnc); +TNodeOrConst* tn_or_const(Discriminant d, void* tnc); +static void emit_helper(void); +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); +char* get_string(TNodeOrConst* tc); +void emit_as_file(FILE* out_file, Instruction* i); +void emit_label(int label); +void emit_jump(int label); +void emit_conditional_jump(Op condition, int label, ...); +void emit_function_start(TNodeOrConst * 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_deref_right(); +void emit_deref_left(); +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); +int label_gen(); +TableNode* getTN(TNodeOrConst* tnc); +int getConst(TNodeOrConst* tnc); + +extern int label_count; +extern Instruction* begin; +extern Instruction* current; + +extern int offset; +extern int currentsp; +extern CGNode* cgList; \ No newline at end of file diff --git a/src/lexicalStructure.h b/src/lexicalStructure.h new file mode 100644 index 0000000..bdd0db7 --- /dev/null +++ b/src/lexicalStructure.h @@ -0,0 +1,34 @@ +/* Lexical Analyzer with Flex (1.6.0) */ +/* The Translators - Spring 2025 */ + +#pragma once + +#include "../src/symbol_table.h" +#include "../tmp/grammar.tab.h" + +extern SymbolTable *cur; +extern FILE *tok_flag; +extern TableNode *funprime; +extern TableNode *funtypeprime; +extern TableNode *arrayprim; +extern TableNode *recprime; +extern TableNode *integ; +extern TableNode *addr; +extern TableNode *chara; +extern TableNode *stri; +extern TableNode *boo; +extern TableNode *undefined; +extern void incr(int lnum, int cnum, int tok); +extern void print_tok(int tok); + +int line_number = 1; +int column_number = 1; +int yycolumn = 1; + +#define YY_USER_ACTION { \ + yylloc.first_line = yylineno; \ + yylloc.last_line = yylineno; \ + yylloc.first_column = yycolumn; \ + yylloc.last_column = yycolumn + yyleng - 1; \ + yycolumn += yyleng; \ +} diff --git a/src/lexicalStructure.lex b/src/lexicalStructure.lex index eac2840..cd1b56e 100644 --- a/src/lexicalStructure.lex +++ b/src/lexicalStructure.lex @@ -4,26 +4,9 @@ %option noyywrap %option header-file="flex.h" %option yylineno -%{ - #include - #include "../tmp/grammar.tab.h" - #include "../src/symbol_table.h" - #ifndef DEBUG - #define DEBUG 0 - #endif - extern SymbolTable * cur; - extern FILE* tok_flag; - extern void incr(int lnum,int cnum, int tok); - extern void print_tok(int tok); - int line_number = 1, column_number = 1; - int yycolumn = 1; - #define YY_USER_ACTION { \ - yylloc.first_line = yylineno; \ - yylloc.last_line = yylineno; \ - yylloc.first_column = yycolumn; \ - yylloc.last_column = yycolumn + yyleng - 1; \ - yycolumn += yyleng; } +%{ + #include "../src/lexicalStructure.h" %} STARCOM [^\*]|\*+[^\)\*]+ @@ -36,63 +19,63 @@ SCHAR \\n|\\t|\\\"|[^\"\n\\] %% -"integer" {if(DEBUG) {printf( "T_INTEGER: %s (%d)\n", yytext, T_INTEGER);} else {if(tok_flag != NULL){print_tok(T_INTEGER);}incr(line_number,column_number,T_INTEGER);yylval.words = strdup(yytext);return T_INTEGER;}} -"address" {if(DEBUG) {printf( "T_ADDRESS: %s (%d)\n", yytext, T_ADDRESS);} else {if(tok_flag != NULL){print_tok(T_ADDRESS);}incr(line_number,column_number,T_ADDRESS);yylval.words = strdup(yytext);return T_ADDRESS;}} -"Boolean" {if(DEBUG) {printf( "T_BOOLEAN: %s (%d)\n", yytext, T_BOOLEAN);} else {if(tok_flag != NULL){print_tok(T_INTEGER);}incr(line_number,column_number,T_INTEGER);yylval.words = strdup(yytext);return T_BOOLEAN;}} -"character" {if(DEBUG) {printf( "T_CHARACTER: %s (%d)\n", yytext, T_CHARACTER);} else {if(tok_flag != NULL){print_tok(T_CHARACTER);}incr(line_number,column_number,T_CHARACTER);yylval.words = strdup(yytext);return T_CHARACTER;}} +"integer" { if(tok_flag != NULL) {print_tok(T_INTEGER);} incr(line_number,column_number,T_INTEGER); yylval.tn = integ; return T_INTEGER; } +"address" { if(tok_flag != NULL) {print_tok(T_ADDRESS);} incr(line_number,column_number,T_ADDRESS); yylval.tn = addr; return T_ADDRESS; } +"Boolean" { if(tok_flag != NULL) {print_tok(T_INTEGER);} incr(line_number,column_number,T_INTEGER); yylval.tn = boo; return T_BOOLEAN; } +"character" { if(tok_flag != NULL) {print_tok(T_CHARACTER);} incr(line_number,column_number,T_CHARACTER); yylval.tn = chara; return T_CHARACTER; } -"while" {if(DEBUG) {printf( "WHILE: %s (%d)\n", yytext, WHILE);} else {if(tok_flag != NULL){print_tok(WHILE);}incr(line_number,column_number,WHILE);return WHILE;}} -"if" {if(DEBUG) {printf( "IF: %s (%d)\n", yytext, IF);} else {if(tok_flag != NULL){print_tok(IF);}incr(line_number,column_number,IF);return IF;}} -"then" {if(DEBUG) {printf( "THEN: %s (%d)\n", yytext, THEN);} else {if(tok_flag != NULL){print_tok(THEN);}incr(line_number,column_number,THEN);return THEN;}} -"else" {if(DEBUG) {printf( "ELSE: %s (%d)\n", yytext, ELSE);} else {if(tok_flag != NULL){print_tok(ELSE);}incr(line_number,column_number,ELSE);return ELSE;}} -"type" {if(DEBUG) {printf( "TYPE: %s (%d)\n", yytext, TYPE);} else {if(tok_flag != NULL){print_tok(TYPE);}incr(line_number,column_number,TYPE);return TYPE;}} -"function" {if(DEBUG) {printf( "FUNCTION: %s (%d)\n", yytext, FUNCTION);} else {if(tok_flag != NULL){print_tok(FUNCTION);}incr(line_number,column_number,FUNCTION);return FUNCTION;}} -"return" {if(DEBUG) {printf( "RETURN: %s (%d)\n", yytext, RETURN);} else {if(tok_flag != NULL){print_tok(RETURN);}incr(line_number,column_number,RETURN);return RETURN;}} -"external" {if(DEBUG) {printf( "EXTERNAL: %s (%d)\n", yytext, EXTERNAL);} else {if(tok_flag != NULL){print_tok(EXTERNAL);}incr(line_number,column_number,EXTERNAL);return EXTERNAL;}} -"as" {if(DEBUG) {printf( "AS: %s (%d)\n", yytext, AS);} else {if(tok_flag != NULL){print_tok(AS);}incr(line_number,column_number,AS);return AS;}} +"while" { if(tok_flag != NULL) {print_tok(WHILE);} incr(line_number,column_number,WHILE); return WHILE; } +"if" { if(tok_flag != NULL) {print_tok(IF);} incr(line_number,column_number,IF); return IF; } +"then" { if(tok_flag != NULL) {print_tok(THEN);} incr(line_number,column_number,THEN); return THEN; } +"else" { if(tok_flag != NULL) {print_tok(ELSE);} incr(line_number,column_number,ELSE); return ELSE; } +"type" { if(tok_flag != NULL) {print_tok(TYPE);} incr(line_number,column_number,TYPE); return TYPE; } +"function" { if(tok_flag != NULL) {print_tok(FUNCTION);} incr(line_number,column_number,FUNCTION); return FUNCTION; } +"return" { if(tok_flag != NULL) {print_tok(RETURN);} incr(line_number,column_number,RETURN); return RETURN; } +"external" { if(tok_flag != NULL) {print_tok(EXTERNAL);} incr(line_number,column_number,EXTERNAL); return EXTERNAL; } +"as" { if(tok_flag != NULL) {print_tok(AS);} incr(line_number,column_number,AS); return AS; } -"release" {if(DEBUG) {printf( "RELEASE: %s (%d)\n", yytext, RELEASE);} else {if(tok_flag != NULL){print_tok(RELEASE);}incr(line_number,column_number,RELEASE);return RELEASE;}} -"reserve" {if(DEBUG) {printf( "RESERVE: %s (%d)\n", yytext, RESERVE);} else {if(tok_flag != NULL){print_tok(RESERVE);}incr(line_number,column_number,RESERVE);return RESERVE;}} +"release" { if(tok_flag != NULL) {print_tok(RELEASE);} incr(line_number,column_number,RELEASE); return RELEASE; } +"reserve" { if(tok_flag != NULL) {print_tok(RESERVE);} incr(line_number,column_number,RESERVE); return RESERVE; } -"+" {if(DEBUG) {printf( "ADD: %s (%d)\n", yytext, ADD);} else {if(tok_flag != NULL){print_tok(ADD);}incr(line_number,column_number,ADD);return ADD;}} -"-" {if(DEBUG) {printf( "SUB_OR_NEG: %s (%d)\n", yytext, SUB_OR_NEG);} else {if(tok_flag != NULL){print_tok(SUB_OR_NEG);}incr(line_number,column_number,SUB_OR_NEG);return SUB_OR_NEG;}} -"*" {if(DEBUG) {printf( "MUL: %s (%d)\n", yytext, MUL);} else {if(tok_flag != NULL){print_tok(MUL);}incr(line_number,column_number,MUL);return MUL;}} -"/" {if(DEBUG) {printf( "DIV: %s (%d)\n", yytext, DIV);} else {if(tok_flag != NULL){print_tok(DIV);}incr(line_number,column_number,DIV);return DIV;}} -"%" {if(DEBUG) {printf( "REM: %s (%d)\n", yytext, REM);} else {if(tok_flag != NULL){print_tok(REM);}incr(line_number,column_number,REM);return REM;}} -"<" {if(DEBUG) {printf( "LESS_THAN: %s (%d)\n", yytext, LESS_THAN);} else {if(tok_flag != NULL){print_tok(LESS_THAN);}incr(line_number,column_number,LESS_THAN);return LESS_THAN;}} -"=" {if(DEBUG) {printf( "EQUAL_TO: %s (%d)\n", yytext, EQUAL_TO);} else {if(tok_flag != NULL){print_tok(EQUAL_TO);}incr(line_number,column_number,EQUAL_TO);return EQUAL_TO;}} -":=" {if(DEBUG) {printf( "ASSIGN: %s (%d)\n", yytext, ASSIGN);} else {if(tok_flag != NULL){print_tok(ASSIGN);}incr(line_number,column_number,ASSIGN);return ASSIGN;}} -"!" {if(DEBUG) {printf( "NOT: %s (%d)\n", yytext, NOT);} else {if(tok_flag != NULL){print_tok(NOT);}incr(line_number,column_number,NOT);return NOT;}} -"&" {if(DEBUG) {printf( "AND: %s (%d)\n", yytext, AND);} else {if(tok_flag != NULL){print_tok(AND);}incr(line_number,column_number,AND);return AND;}} -"|" {if(DEBUG) {printf( "OR: %s (%d)\n", yytext, OR);} else {if(tok_flag != NULL){print_tok(OR);}incr(line_number,column_number,OR);return OR;}} -"." {if(DEBUG) {printf( "DOT: %s (%d)\n", yytext, DOT);} else {if(tok_flag != NULL){print_tok(DOT);}incr(line_number,column_number,DOT);return DOT;}} +"+" { if(tok_flag != NULL) {print_tok(ADD);} incr(line_number,column_number,ADD); return ADD; } +"-" { if(tok_flag != NULL) {print_tok(SUB_OR_NEG);} incr(line_number,column_number,SUB_OR_NEG); return SUB_OR_NEG; } +"*" { if(tok_flag != NULL) {print_tok(MUL);} incr(line_number,column_number,MUL); return MUL; } +"/" { if(tok_flag != NULL) {print_tok(DIV);} incr(line_number,column_number,DIV); return DIV; } +"%" { if(tok_flag != NULL) {print_tok(REM);} incr(line_number,column_number,REM); return REM; } +"<" { if(tok_flag != NULL) {print_tok(LESS_THAN);} incr(line_number,column_number,LESS_THAN); return LESS_THAN; } +"=" { if(tok_flag != NULL) {print_tok(EQUAL_TO);} incr(line_number,column_number,EQUAL_TO); return EQUAL_TO; } +":=" { if(tok_flag != NULL) {print_tok(ASSIGN);} incr(line_number,column_number,ASSIGN); return ASSIGN; } +"!" { if(tok_flag != NULL) {print_tok(NOT);} incr(line_number,column_number,NOT); return NOT; } +"&" { if(tok_flag != NULL) {print_tok(AND);} incr(line_number,column_number,AND); return AND; } +"|" { if(tok_flag != NULL) {print_tok(OR);} incr(line_number,column_number,OR); return OR; } +"." { if(tok_flag != NULL) {print_tok(DOT);} incr(line_number,column_number,DOT); return DOT; } -";" {if(DEBUG) {printf( "SEMI_COLON: %s (%d)\n", yytext, SEMI_COLON);} else {if(tok_flag != NULL){print_tok(SEMI_COLON);}incr(line_number,column_number,SEMI_COLON);return SEMI_COLON;}} -":" {if(DEBUG) {printf( "COLON: %s (%d)\n", yytext, COLON);} else {if(tok_flag != NULL){print_tok(COLON);}incr(line_number,column_number,COLON);return COLON;}} -"," {if(DEBUG) {printf( "COMMA: %s (%d)\n", yytext, COMMA);} else {if(tok_flag != NULL){print_tok(COMMA);}incr(line_number,column_number,COMMA);return COMMA;}} -"->" {if(DEBUG) {printf( "ARROW: %s (%d)\n", yytext, ARROW);} else {if(tok_flag != NULL){print_tok(ARROW);}incr(line_number,column_number,ARROW);return ARROW;}} +";" { if(tok_flag != NULL) {print_tok(SEMI_COLON);} incr(line_number,column_number,SEMI_COLON); return SEMI_COLON; } +":" { if(tok_flag != NULL) {print_tok(COLON);} incr(line_number,column_number,COLON); return COLON; } +"," { if(tok_flag != NULL) {print_tok(COMMA);} incr(line_number,column_number,COMMA); return COMMA; } +"->" { if(tok_flag != NULL) {print_tok(ARROW);} incr(line_number,column_number,ARROW); return ARROW; } -{DIGIT}+ {if(DEBUG) {printf( "C_INTEGER: %s (%d)\n", yytext, C_INTEGER);} else {if(tok_flag != NULL){print_tok(C_INTEGER);}incr(line_number,column_number,C_INTEGER);yylval.integ = atoi(yytext);return C_INTEGER;}} -'{CHAR}' {if(DEBUG) {printf( "C_CHARACTER: %s (%d)\n", yytext, C_CHARACTER);} else {if(tok_flag != NULL){print_tok(C_CHARACTER);}incr(line_number,column_number,C_CHARACTER);return C_CHARACTER;}} -\"{SCHAR}*\" {if(DEBUG) {printf( "C_STRING: %s (%d)\n", yytext, C_STRING);} else {if(tok_flag != NULL){print_tok(C_STRING);}incr(line_number,column_number,C_STRING);return C_STRING;}} -{COMMENT} {if(DEBUG) {printf( "COMMENT: %s (%d)\n", yytext, COMMENT);} else {if(tok_flag != NULL){print_tok(COMMENT);}incr(line_number,column_number,COMMENT);/*return COMMENT;*/}} +{DIGIT}+ {if(tok_flag != NULL){print_tok(C_INTEGER);}incr(line_number,column_number,C_INTEGER);yylval.integ = atoi(yytext)/*words = strdup("integer")*/;return C_INTEGER;} +'{CHAR}' {if(tok_flag != NULL){print_tok(C_CHARACTER);}incr(line_number,column_number,C_CHARACTER);char* token = strdup(yytext)/*yylval.tn = chara*/;yylval.letter = token[1];return C_CHARACTER;} +\"{SCHAR}*\" {if(tok_flag != NULL){print_tok(C_STRING);}incr(line_number,column_number,C_STRING);int k = strlen(yytext);yytext[k-1] = '\0';yylval.words = strdup(&yytext[1]);return C_STRING;} +{COMMENT} {if(tok_flag != NULL){print_tok(COMMENT);}incr(line_number,column_number,COMMENT);/*return COMMENT;*/} -"(" {if(DEBUG) {printf( "L_PAREN: %s (%d)\n", yytext, L_PAREN);} else {if(tok_flag != NULL){print_tok(L_PAREN);}incr(line_number,column_number,L_PAREN);return L_PAREN;}} -")" {if(DEBUG) {printf( "R_PAREN: %s (%d)\n", yytext, R_PAREN);} else {if(tok_flag != NULL){print_tok(R_PAREN);}incr(line_number,column_number,R_PAREN);return R_PAREN;}} -"[" {if(DEBUG) {printf( "L_BRACKET: %s (%d)\n", yytext, L_BRACKET);} else {if(tok_flag != NULL){print_tok(L_BRACKET);}incr(line_number,column_number,L_BRACKET);return L_BRACKET;}} -"]" {if(DEBUG) {printf( "R_BRACKET: %s (%d)\n", yytext, R_BRACKET);} else {if(tok_flag != NULL){print_tok(R_BRACKET);}incr(line_number,column_number,R_BRACKET);return R_BRACKET;}} -"{" {if(DEBUG) {printf( "L_BRACE: %s (%d)\n", yytext, L_BRACE);} else {if(tok_flag != NULL){print_tok(L_BRACE);}incr(line_number,column_number,L_BRACE);return L_BRACE;}} -"}" {if(DEBUG) {printf( "R_BRACE: %s (%d)\n", yytext, R_BRACE);} else {if(tok_flag != NULL){print_tok(R_BRACE);}incr(line_number,column_number,R_BRACE);return R_BRACE;}} +"(" { if(tok_flag != NULL) {print_tok(L_PAREN);} incr(line_number,column_number,L_PAREN); return L_PAREN; } +")" { if(tok_flag != NULL) {print_tok(R_PAREN);} incr(line_number,column_number,R_PAREN); return R_PAREN; } +"[" { if(tok_flag != NULL) {print_tok(L_BRACKET);} incr(line_number,column_number,L_BRACKET); return L_BRACKET; } +"]" { if(tok_flag != NULL) {print_tok(R_BRACKET);} incr(line_number,column_number,R_BRACKET); return R_BRACKET; } +"{" { if(tok_flag != NULL) {print_tok(L_BRACE);} incr(line_number,column_number,L_BRACE); return L_BRACE; } +"}" { if(tok_flag != NULL) {print_tok(R_BRACE);} incr(line_number,column_number,R_BRACE); return R_BRACE; } -"true" {if(DEBUG) {printf( "C_TRUE: %s (%d)\n", yytext, C_TRUE);} else {if(tok_flag != NULL){print_tok(C_TRUE);}incr(line_number,column_number,C_TRUE);yylval.words = strdup(yytext);return C_TRUE;}} -"false" {if(DEBUG) {printf( "C_FALSE: %s (%d)\n", yytext, C_FALSE);} else {if(tok_flag != NULL){print_tok(C_FALSE);}incr(line_number,column_number,C_FALSE);yylval.words = strdup(yytext);return C_FALSE;}} -"null" {if(DEBUG) {printf( "C_NULL: %s (%d)\n", yytext, C_NULL);} else {if(tok_flag != NULL){print_tok(C_NULL);}incr(line_number,column_number,C_NULL);yylval.words = strdup(yytext);return C_NULL;}} +"true" { if(tok_flag != NULL) {print_tok(C_TRUE);} incr(line_number,column_number,C_TRUE); yylval.tn = boo; return C_TRUE; } +"false" { if(tok_flag != NULL) {print_tok(C_FALSE);} incr(line_number,column_number,C_FALSE); yylval.tn = boo; return C_FALSE; } +"null" { if(tok_flag != NULL) {print_tok(C_NULL);} incr(line_number,column_number,C_NULL); yylval.tn = addr; return C_NULL; } -{ID} {if(DEBUG) {printf( "ID: %s (%d)\n", yytext, ID);} else {if(tok_flag != NULL){print_tok(ID);}incr(line_number,column_number,ID);yylval.words = strdup(yytext); return ID;}} +{ID} { if(tok_flag != NULL) {print_tok(ID);} incr(line_number,column_number,ID); yylval.words = strdup(yytext); return ID; } -\n {yycolumn=1;incr(line_number,column_number,0);} -\t {incr(line_number,column_number,0);} -" " {incr(line_number,column_number,0);} -. {incr(line_number,column_number,0);} +\n { yycolumn = 1; incr(line_number,column_number,0); } +\t { incr(line_number,column_number,0); } +" " { incr(line_number,column_number,0); } +. { incr(line_number,column_number,0); } %% diff --git a/src/runner.c b/src/runner.c index 2110d23..a74c424 100644 --- a/src/runner.c +++ b/src/runner.c @@ -4,203 +4,331 @@ #include "runner.h" int main(int argc, char *argv[]) { - if (argc == 1) { - fprintf(stderr, INVALID); - return -1; - } + if (argc == 1) { + fprintf(stderr, INVALID); + return -1; + } - else if (argc == 2) { - if (is_help(argv[1])) { - return 0; - } else if (is_alpha_file(argv[1], strlen(argv[1])) == 0) { - no_flag = SET_FLAG; - alpha_file = fopen(argv[1], "r"); - } else { - fprintf(stderr, INVALID); - return -1; - } + else if (argc == 2) { + if (is_help(argv[1])) { + return 0; + } else if (is_alpha_file(argv[1], strlen(argv[1])) == 0) { + no_flag = SET_FLAG; + alpha_file = fopen(argv[1], "r"); + } else { + fprintf(stderr, INVALID); + return -1; } + } - else { - if (is_alpha_file(argv[argc - 1], strlen(argv[argc - 1])) != 0) { - fprintf(stderr, INVALID); - return -1; - } else { - for (int i = 1; i < argc - 1; i++) { - if (check_flag(argv[i], argv[argc - 1]) != 0) { - fprintf(stderr, "INVALID FLAG(S): Use -help to view valid inputs \n"); - return -1; - } - } - alpha_file = fopen(argv[argc - 1], "r"); + else { + if (is_alpha_file(argv[argc - 1], strlen(argv[argc - 1])) != 0) { + fprintf(stderr, INVALID); + return -1; + } else { + for (int i = 1; i < argc - 1; i++) { + if (check_flag(argv[i], argv[argc - 1]) != 0) { + fprintf(stderr, INVALID); + return -1; } + } + alpha_file = fopen(argv[argc - 1], "r"); } - return run(alpha_file); + } + return run(alpha_file); } int check_flag(char *arg, char *alpha) { - if (strcmp("-tok", arg) == 0) { - if (tok_flag == NULL) { - return new_file(arg, alpha); - } - fprintf(stderr, "FLAGS REPEAT\n"); - return -1; - } else if (strcmp("-st", arg) == 0) { - if (st_flag == NULL) { - return new_file(arg, alpha); - } - fprintf(stderr, "FLAGS REPEAT\n"); - return -1; - } else { - fprintf(stderr, "INVALID FLAG: Use -help for valid inputs\n"); - return -1; + if (strcmp("-tok", arg) == 0) { + if (tok_flag == NULL) { + return new_file(arg, alpha); } -} - -void incr(int lnum,int cnum, int tok){ - //if (tok == COMMENT) { - for (int i = 0; i < yyleng; i++) { - if (yytext[i] == '\n') { - line_number++; - column_number = 0; - } - column_number++; - } -// }else{ -// column_number += yyleng; -// } -} -void print_tok(int tok){ -fprintf(tok_flag, "%d %d %3d \"%s\"\n", line_number, column_number,tok, yytext); -} -int run(FILE *alpha) { - int token; - top = cur = CreateScope(NULL, 1, 1); - - // If file is not found - if (alpha == NULL) { - fprintf(stderr, "INPUT FILE NOT FOUND\n"); - return -1; + fprintf(stderr, "FLAGS REPEAT\n"); + return -1; + } else if (strcmp("-st", arg) == 0) { + if (st_flag == NULL) { + return new_file(arg, alpha); } - yyin = alpha; - - // TOK FLAG - if (tok_flag != NULL) { - while (0 != (token = yylex())) { - //if (tok_flag != NULL) { - // fprintf(tok_flag, "%d %d %3d \"%s\"\n", line_number, column_number, - // token, yytext); - //} - /*if (token == COMMENT) { - for (int i = 0; i < yyleng; i++) { - if (yytext[i] == '\n') { - line_number++; - column_number = 0; - } - column_number++; - } - continue; - } - if (token == 1999) { - printf( - "On line number %d and column number %d we have an invalid " - "character:%s\n", - line_number, column_number, yytext); - } - column_number += yyleng; */ - } - fclose(tok_flag); - - if (yyin != NULL) { - fclose(yyin); - } - return 0; + fprintf(stderr, "FLAGS REPEAT\n"); + return -1; + } else if (strcmp("-asc", arg) == 0) { + if (asc_flag == NULL) { + return new_file(arg, alpha); } - - if (st_flag != NULL) { - // output symbol table, file pointer is - // print_symbol_table(top,st_flag); + fprintf(stderr, "FLAGS REPEAT\n"); + return -1; + } else if (strcmp("-tc", arg) == 0) { + if (tc_flag == false) { + tc_flag = true; + return 0; } - - yyparse(); - FILE *f = fdopen(1, "w"); - print_symbol_table(getAncestor(cur), f); - fclose(f); - - if (yyin != NULL) { - fclose(yyin); + fprintf(stderr, "FLAGS REPEAT\n"); + return -1; + } else if (strcmp("-ir", arg) == 0) { + if (ir_flag == NULL) { + return new_file(arg, alpha); } - + fprintf(stderr, "FLAGS REPEAT\n"); + return -1; + } else if (strcmp("-cg", arg) == 0) { + if (cg_flag == NULL) { + return new_file(arg, alpha); + } + fprintf(stderr, "FLAGS REPEAT\n"); + return -1; + } else if (strcmp("-debug", arg) == 0) { + DEBUG = true; return 0; + } else { + fprintf(stderr, "INVALID FLAG: Use -help for valid inputs\n"); + return -1; + } +} + +void incr(int lnum, int cnum, int tok) { + for (int i = 0; i < yyleng; i++) { + if (yytext[i] == '\n') { + line_number++; + column_number = 0; + } + column_number++; + } +} + +void print_tok(int tok) { + fprintf(tok_flag, "%d %d %3d \"%s\"\n", line_number, column_number, tok, yytext); +} + +int run(FILE *alpha) { + int token; + top = cur = init(CreateScope(NULL, 1, 1)); + + // If file is not found + if (alpha == NULL) { + fprintf(stderr, "INPUT FILE NOT FOUND\n"); + return -1; + } + + char *line; + int i = 1; + while ((line = file_read_line(alpha)) != NULL) { + CodeLine *code_line = malloc(sizeof(CodeLine)); + code_line->line_number = i; + code_line->line = malloc(strlen(line) + 1); + strcpy(code_line->line, line); + code_line->next = NULL; + code_line->is_error = false; + append_code_line(code_line); + free(line); + i++; + } + + fseek(alpha, 0, SEEK_SET); + + yyin = alpha; + yyparse(); + + if (tok_flag != NULL) { + while (0 != (token = yylex())) { + // Don't delete me 🥺 + } + fclose(tok_flag); + } + + if (st_flag != NULL) { + printdebug("[-st] Symbol Table is enabled."); + print_symbol_table(top, st_flag); + fclose(st_flag); + } + + if (asc_flag != NULL) { + printdebug("[-asc] Annotated Source Code is enabled."); + print_code_lines(); + fclose(asc_flag); + } + + if (tc_flag != false) { + printdebug("[-tc] Type checking is enabled."); + } + + if (ir_flag != NULL) { + printdebug("[-ir] Intermediate code is enabled."); + emit_as_file(ir_flag, begin); + fclose(ir_flag); + } + + if (cg_flag != NULL) { + printdebug("[-cg] Code generation is enabled."); + generate(); + fclose(cg_flag); + } + + if (yyin != NULL) { + fclose(yyin); + } + + return 0; } bool is_help(char *input) { - if (strcmp(input, "-help") == 0) { - printf("%s", HELP); - return true; - } + if (strcmp(input, "-help") == 0) { + printf("%s", HELP); + return true; + } - return false; + return false; } int new_file(char *arg, char *alpha) { - int type_len; - const char *basename = alpha; - const char *slash = strchr(alpha, '/'); + int type_len; + const char *basename = alpha; + const char *slash = strchr(alpha, '/'); - while (slash != NULL) { - basename = slash + 1; - slash = strchr(basename, '/'); - } + while (slash != NULL) { + basename = slash + 1; + slash = strchr(basename, '/'); + } - mkdir("./out", 0777); + mkdir("./out", 0777); - char *new_basename = calloc(strlen(basename) + 5, sizeof(char)); - strcpy(new_basename, "./out/"); - strcat(new_basename, basename); - basename = new_basename; + char *new_basename = calloc(strlen(basename) + 5, sizeof(char)); + strcpy(new_basename, "./out/"); + strcat(new_basename, basename); + basename = new_basename; - if (strcmp(arg, "-tok") == 0) { - type_len = TOK_LEN; - } else if (strcmp(arg, "-st") == 0) { - type_len = ST_LEN; - } else { - fprintf(stderr, "INVALID FLAG: Use -help to view valid inputs\n"); - return -1; - } + if (strcmp(arg, "-tok") == 0) { + type_len = TOK_LEN; + } else if (strcmp(arg, "-st") == 0) { + type_len = ST_LEN; + } else if (strcmp(arg, "-asc") == 0) { + type_len = ASC_LEN; + } else if (strcmp(arg, "-ir") == 0) { + type_len = IR_LEN; + } else if (strcmp(arg, "-cg") == 0) { + type_len = CG_LEN; + } else { + fprintf(stderr, INVALID); + return -1; + } - // calculate lengths - int basename_len = strlen(basename); - char *file_name = - calloc(basename_len - ALPHA_OFFSET + type_len + 2, sizeof(char)); + // calculate lengths + int basename_len = strlen(basename); + char *file_name = calloc(basename_len - ALPHA_OFFSET + type_len + 2, sizeof(char)); - // coy filename and add extension + // coy filename and add extension + if (strcmp(arg, "-cg") == 0) { + strncpy(file_name, basename, basename_len - ALPHA_OFFSET); + strcat(file_name, ".s"); + } else { strncpy(file_name, basename, basename_len - ALPHA_OFFSET); strcat(file_name, "."); strcat(file_name, arg + 1); + } - if (strcmp(arg, "-tok") == 0) { - tok_flag = fopen(file_name, "w"); - } else if (strcmp(arg, "-st") == 0) { - st_flag = fopen(file_name, "w"); - } - return 0; + if (strcmp(arg, "-tok") == 0) { + tok_flag = fopen(file_name, "w"); + } else if (strcmp(arg, "-st") == 0) { + st_flag = fopen(file_name, "w"); + } else if (strcmp(arg, "-asc") == 0) { + asc_flag = fopen(file_name, "w"); + } else if (strcmp(arg, "-ir") == 0) { + ir_flag = fopen(file_name, "w"); + } else if (strcmp(arg, "-cg") == 0) { + cg_flag = fopen(file_name, "w"); + } + return 0; } int is_alpha_file(char *alpha, int file_len) { - if (strcmp(".alpha", alpha + sizeof(char) * (file_len - ALPHA_OFFSET)) != 0) { - return -1; // not alpha file - } - return 0; // is alpha file + if (strcmp(".alpha", + alpha + sizeof(char) * (file_len - ALPHA_OFFSET)) != 0) { + return -1; // not alpha file + } + return 0; // is alpha file } -void enter_scope(int line, int column) { - cur = CreateScope(cur, line, column); -} -void exit_scope() { - if (cur->Parent_Scope == NULL) { - printf("Can't close top"); - return; +void insert_code_line(char * error_message, int line_number) { + CodeLine *error_line = malloc(sizeof(CodeLine)); + error_line->line_number = line_number; + error_line->line = malloc(strlen(error_message) + 1); + strcpy(error_line->line, error_message); + error_line->next = NULL; + error_line->is_error = true; + + if (error_line == NULL || code_head == NULL) return; + + int line = error_line->line_number; + CodeLine *current = code_head; + while (current != NULL) { + if (current->line_number == line) { + CodeLine *next_code_line = current->next; + current->next = error_line; + error_line->next = next_code_line; } - cur = cur->Parent_Scope; + current = current->next; + } } + +void append_code_line(CodeLine *code_line) { + if (code_line == NULL) return; + + if (code_head == NULL) { + code_head = code_line; + } else { + CodeLine *current = code_head; + while (current->next != NULL) { + current = current->next; + } + current->next = code_line; + } +} + +void print_code_lines() { + if (code_head == NULL) { + printf("No code lines to print.\n"); + return; + } + + CodeLine *current = code_head; + while (current != NULL) { + if (current->is_error) { + fprintf(asc_flag, "%s", current->line); + } else { + fprintf(asc_flag, "%03d: %s", current->line_number, current->line); + } + current = current->next; + } +} + +char *file_read_line(FILE *fp) { + if (fp == NULL) return NULL; + + size_t size = 128; + size_t len = 0; + char *str = malloc(size); + if (!str) return NULL; + + int c; + while ((c = fgetc(fp)) != EOF) { + if (len + 1 >= size) { + size *= 2; + char *new_buffer = realloc(str, size); + if (!new_buffer) { + free(str); + return NULL; + } + str = new_buffer; + } + + str[len++] = (char)c; + if (c == '\n') break; + } + + if (len == 0 && c == EOF) { + free(str); + return NULL; + } + + str[len] = '\0'; + return str; +} \ No newline at end of file diff --git a/src/runner.h b/src/runner.h index 9f66407..9971eed 100644 --- a/src/runner.h +++ b/src/runner.h @@ -1,18 +1,31 @@ /* Runner File - Compiles alpha Compiler */ /* The Translators - Spring 2025 */ +#pragma once + #define ALPHA_OFFSET 6 #define TOK_LEN 3 #define ST_LEN 2 -#define HELP \ - "HELP:\nHow to run the alpha compiler:\n./alpha [options] program\nValid " \ - "options:\n-tok output the token number, token, line number, and column " \ - "number for each of the tokens to the .tok file\n-st output the symbol " \ - "table for the program to the .st file\n-help print this message and exit " \ - "the alpha compiler\n" -#define SET_FLAG 1 // Used to set flags for arg types +#define ASC_LEN 3 +#define IR_LEN 2 +#define CG_LEN 1 +#define HELP \ + "HELP:\n" \ + " How to run the alpha compiler:\n" \ + " ./alpha [options] program\n" \ + "Valid options:\n" \ + " -tok output the token number, token, line number, and column number for each of the tokens to the .tok file\n" \ + " -st output the symbol table for the program to the .st file\n" \ + " -asc output the annotated source code for the program to the .asc file, including syntax errors\n" \ + " -tc run the type checker and report type errors to the .asc file\n" \ + " -ir run the intermediate representation generator, writing output to the .ir file\n" \ + " -cg run the (x86 assembly) code generator, writing output to the .s file\n" \ + " -debug produce debugging messages to stderr\n" \ + " -help print this message and exit the alpha compiler\n" + +#define SET_FLAG 1 // Used to set flags for arg types #define INVALID \ - "INVALID INPUT: Include a .alpha file or use -help for more inputs \n" + "INVALID INPUT: Include a .alpha file or use -help for more inputs \n" #include #include @@ -21,32 +34,78 @@ #include #include "../tmp/flex.h" -#include "symbol_table.h" -//#include "typedefs.h" #include "../tmp/grammar.tab.h" +#include "codegen.h" +#include "intermediate_code.h" +#include "symbol_table.h" -extern int line_number, column_number; +extern int line_number; +extern int column_number; extern char *yytext; extern FILE *yyin; -int arg; +extern bool DEBUG; SymbolTable *top; SymbolTable *cur; -// int main(int argc, char* argv[]); -char *is_tok(int argc, char *argv[]); -// int is_alpha_file(char *file, int file_len); -void enter_scope(int, int); -void exit_scope(void); - FILE *alpha_file; FILE *tok_flag = NULL; FILE *st_flag = NULL; +FILE *asc_flag = NULL; +FILE *ir_flag = NULL; +FILE *cg_flag = NULL; +bool tc_flag = false; +bool DEBUG = false; int no_flag = 0; +int arg; + +TableNode *funprime; +TableNode *arrayprim; +TableNode *integ; +TableNode *addr; +TableNode *chara; +TableNode *stri; +TableNode *boo; +TableNode *recprime; +TableNode *funtypeprime; +TableNode *undefined; +extern Instruction *begin; int main(int argc, char *argv[]); +int check_flag(char *arg, char *alpha); +void incr(int lnum, int cnum, int tok); +void print_tok(int tok); +int run(FILE *alpha); +bool is_help(char *input); int new_file(char *arg, char *alpha); int is_alpha_file(char *alpha, int file_len); -bool is_help(char *input); -int run(FILE *alpha); -int check_flag(char *arg, char *alpha); + +char *COLOR_RED = "\033[0;31m"; +char *COLOR_GREEN = "\033[0;32m"; +char *COLOR_ORANGE = "\033[0;33m"; +char *COLOR_BLUE = "\033[0;34m"; +char *COLOR_PURPLE = "\033[0;35m"; +char *COLOR_CYAN = "\033[0;36m"; +char *COLOR_LIGHTGRAY = "\033[0;37m"; +char *COLOR_DARKGRAY = "\033[1;30m"; +char *COLOR_LIGHTRED = "\033[1;31m"; +char *COLOR_LIGHTGREEN = "\033[1;32m"; +char *COLOR_YELLOW = "\033[1;33m"; +char *COLOR_LIGHTBLUE = "\033[1;34m"; +char *COLOR_LIGHTPURPLE = "\033[1;35m"; +char *COLOR_LIGHTCYAN = "\033[1;36m"; +char *COLOR_WHITE = "\033[1;37m"; + +typedef struct CodeLine { + char *line; + int line_number; + bool is_error; + struct CodeLine *next; +} CodeLine; + +CodeLine *code_head; + +char *file_read_line(FILE *fp); +void insert_code_line(char * error_message, int line_number); +void append_code_line(CodeLine *code_line); +void print_code_lines(); \ No newline at end of file diff --git a/src/symbol_table.c b/src/symbol_table.c index fa0e6bb..2fc926c 100644 --- a/src/symbol_table.c +++ b/src/symbol_table.c @@ -3,196 +3,1553 @@ #include "symbol_table.h" -#include -#include -#include -char * typey = "type"; -char * funy = "function"; -SymbolTable* CreateScope(SymbolTable* ParentScope, int Line, int Column) { - SymbolTable* table = (SymbolTable*)malloc(sizeof(SymbolTable)); - table->Line_Number = Line; - table->Column_Number = Column; - table->Parent_Scope = ParentScope; - table->Children_Scope = NULL; - table->entries = NULL; - if (ParentScope != NULL) { - if (ParentScope->Children_Scope == NULL) { - ListOfTable* newEntry = (ListOfTable*)malloc(sizeof(ListOfTable)); - newEntry->next = NULL; - // newEntry->prev = NULL; - newEntry->table = table; - ParentScope->Children_Scope = newEntry; - } else { - ListOfTable* newEntry = (ListOfTable*)malloc(sizeof(ListOfTable)); - // newEntry->prev = NULL; - newEntry->table = table; - ListOfTable* oldEntry = ParentScope->Children_Scope; - ParentScope->Children_Scope = newEntry; - newEntry->next = oldEntry; - } - } - return table; +Constant_Stack *head = NULL; +int temp2_count = 0; + +void printdebug_impl(char *file, int line, const char *format, ...) { + if (DEBUG) { + printf("%s<%s> [%d]%s ", COLOR_DARKGRAY, file, line, + COLOR_WHITE); + va_list args; + va_start(args, format); + vprintf(format, args); + va_end(args); + printf("\n"); + } } -//create entry just for things below top level scope -TableNode* CreateEntry(SymbolTable* table, char* typeOf, char* id) { +char *temp_var_gen() { + char *ret = calloc(9, sizeof(*ret)); + sprintf(ret, "$t%d", temp2_count); + temp2_count++; + return ret; +} -if(table ==NULL || table->Parent_Scope == NULL){ - printf("Null reference to table given for create entry or given top level scope which is invalid\n"); +Constant_Stack *Push(TableNode *type, void *value, bool isConst) { + if (type == NULL || type == undefined) { + printdebug( + "passed a NULL reference/undefined reference to " + "CreateConstantStack. Invalid."); return NULL; -} -TableNode* topDef = (table_lookup(getAncestor(table),typeOf)); -if(topDef == NULL){ - printf("This type is not defined at the top level\n"); - return NULL; -} - TableNode* newEntry = (TableNode*)malloc(sizeof(TableNode)); - newEntry->theType = topDef->theName; - newEntry->theName = id; - if (table->entries == NULL) { - table->entries = newEntry; - return newEntry; - } else { - TableNode* oldEntry = table->entries; - table->entries = newEntry; - newEntry->next = oldEntry; - return newEntry; - } + } + Constant_Stack *cs = (Constant_Stack *)malloc(sizeof(Constant_Stack)); + cs->theType = type; + cs->theValue = value; + cs->isConst = isConst; + if (head == NULL) { + head = cs; + cs->next = NULL; + } else { + cs->next = head; + head = cs; + } + return cs; } -//we use false for type defs and true for functions for parameter of typeOf -TableNode* Define(SymbolTable* table, bool typeOf, char* id) { -if(table ==NULL || table->Parent_Scope != NULL){ - printf("No valid table given for header defs\n"); - return NULL; -} - - - TableNode* newEntry = (TableNode*)malloc(sizeof(TableNode)); - -//possible issues with referencing text instead of heap -if(typeOf == 0){ - newEntry->theType = typey; -} -if (typeOf == 1){ - newEntry->theType = funy; -} -if(table_lookup(table,id) != NULL){ - printf("already defined at the top level, can't define duplicate names\n"); - return NULL; -} - newEntry->theName = id; - if (table->entries == NULL) { - table->entries = newEntry; - return newEntry; - } else { - TableNode* oldEntry = table->entries; - table->entries = newEntry; - newEntry->next = oldEntry; - return newEntry; - } - -} - -TableNode* table_lookup(SymbolTable* table, char* x) { - TableNode* entrie = table->entries; - for (; entrie != NULL; entrie = entrie->next) { - if (!strcmp(entrie->theName, x)) { - return entrie; - } - } +Constant_Stack *Pop() { + if (head == NULL) { + printf("cannot pop from an empty stack. Invalid.\n"); return NULL; + } + Constant_Stack *cs = head; + head = head->next; + printf("Popped something of type %s\n", getName(cs->theType)); + return cs; } -TableNode* look_up(SymbolTable* table, char* x) { - if (table == NULL) { + +Constant_Stack *Print_Stack() { + if (head == NULL) { + printdebug("cannot print an empty stack. Invalid."); + return NULL; + } + Constant_Stack *cs = head; + while (cs != NULL) { + if (cs->theValue == NULL) { + printf("Type: %s, Value: NULL", getName(cs->theType)); + } + if (cs->theType == stri) { + printf("Type: %s, Value: %s\n", getName(cs->theType), *(char *)(cs->theValue)); + } + if (cs->theType == integ) { + printf("Type: %s, Value: %d\n", getName(cs->theType), (int *)(cs->theValue)); + } + if (cs->theType == chara) { + printf("Type: %s, Value: %c\n", getName(cs->theType), *(char *)cs->theValue); + } + if (cs->theType == boo) { + if (*(bool *)cs->theValue == true) { + printf("Type: %s, Value: true\n", getName(cs->theType)); + } else { + printf("Type: %s, Value: false\n", getName(cs->theType)); + } + } + cs = cs->next; + } + return cs; +} + +// primitive additional info only stores the size of that type +AdInfo *CreatePrimitiveInfo(int size) { + AdInfo *info = (AdInfo *)malloc(sizeof(AdInfo)); + info->PrimAdInfo = (primitive_info *)malloc(sizeof(primitive_info)); + info->PrimAdInfo->size = size; + return info; +} + +// only gets the size of a primitive type +int getPrimSize(TableNode *definition) { + if (definition == NULL) { + printdebug( + "passed an NULL entry to getPrimSize function. Invalid."); + return -1; + } + if (definition == undefined) { + printdebug( + "passed an undefined entry to getPrimSize function. " + "Invalid."); + return -1; + } + if (definition->additionalinfo == NULL) { + printdebug("node has NULL additionalinfo. Invalid."); + return -1; + } + if (strcmp(getType(definition), "primitive") != 0) { + printdebug( + "not checking the size of a primitive -- invalid op"); + return 0; + } + return definition->additionalinfo->PrimAdInfo->size; +} + +// Only information stored in array info is the number of dimensions and the +// type stored in the array per professor, the actual size of the array is +// calculated at runtime so bounds checking only needs to be done then +AdInfo *CreateArrayInfo(int dim, TableNode *type) { + if (type == NULL) { + printdebug( + "passed a NULL reference to " + "CreateArrayInfo. Invalid."); + return NULL; + } + if (type == undefined) { + printdebug( + "passed an undefined reference to " + "CreateArrayInfo. Invalid."); + return NULL; + } + if (type == undefined) { + printdebug( + "passed a undefined type reference to " + "CreateArrayInfo. Invalid."); + return NULL; + } + AdInfo *info = (AdInfo *)malloc(sizeof(AdInfo)); + info->ArrayAdInfo = (array_info *)malloc(sizeof(array_info)); + info->ArrayAdInfo->numofdimensions = dim; + info->ArrayAdInfo->typeofarray = type; + // avoiding storing any types like below + // int* dimensionsizes = loc; + return info; +} +// This gets the number of dimensions from array info +int getNumArrDim(TableNode *definition) { + if (definition == NULL) { + printdebug( + "passed an NULL entry to getNumArrDim " + "function. Invalid."); + return -1; + } + if (definition == undefined) { + printdebug( + "passed an undefined entry to getNumArrDim " + "function. Invalid."); + return -1; + } + if (getAdInfoType(definition) != TYPE_ARRAY_TYPE) { + printdebug( + "passed an invalid node to getNumArrDim. Seeing tag %d in getNumArrDim. Invalid.", getAdInfoType(definition)); + return -1; + } + return definition->additionalinfo->ArrayAdInfo->numofdimensions; +} +// This gets the type stored in an array from arrtype. It returns a reference to +// the entry of that type +TableNode *getArrType(TableNode *definition) { + if (definition == NULL) { + printdebug( + "passed an NULL entry to getArrType " + "function. Invalid."); + return undefined; + } + if (definition == undefined) { + printdebug( + "passed an undefined entry to getArrType " + "function. Invalid."); + return undefined; + } + if (getAdInfoType(definition) != TYPE_ARRAY_TYPE) { + printdebug( + "passed an invalid node to getArrType. Seeing tag %d. Invalid.", getAdInfoType(definition)); + return undefined; + } + return definition->additionalinfo->ArrayAdInfo->typeofarray; +} + +// Record type currently stores the number of elements as well as the types, in +// order, of what make up that type in an array. Unfortunately this second part +// should probably instead be replaced by a reference to a scope in which those +// elements are found. +AdInfo *CreateRecordInfo(int length, SymbolTable *recordScope) { + AdInfo *info = (AdInfo *)malloc(sizeof(AdInfo)); + info->RecAdInfo = (record_info *)malloc(sizeof(record_info)); + info->RecAdInfo->numofelements = length; + // replace below with reference to a scope, not an array + info->RecAdInfo->recordScope = recordScope; + return info; +} +// This gets the number of elements that make up a record. +// Perhaps this may not be needed since we need to iterate over all elements +// anyways. + +int getRecTotal(TableNode *node) { + if (node == NULL) { + printdebug( + "passed a NULL node to getRecTotal. Invalid."); + return -1; + } + if (getAdInfoType(node) != TYPE_RECORD_TYPE) { + printdebug( + "passed an invalid node to getRecTotal. Invalid."); + return -1; + } + if (node->additionalinfo == NULL) { + printdebug( + "node has NULL additionalinfo. Invalid."); + return -1; + } + return node->additionalinfo->RecAdInfo->total_size; +} +TableNode *setRecOffsetInfo(SymbolTable *scope, TableNode *node) { + if (node == NULL) { + printdebug( + "passed a NULL node to setRecOffsetInfo. Invalid."); + return undefined; + } + if (scope == NULL) { + printdebug( + "passed an NULL scope to setRecOffsetInfo. Invalid."); + return undefined; + } + if (getFirstEntry(scope) == NULL) { + printdebug( + "passed an empty scope to setRecOffsetInfo. Invalid."); + return undefined; + } + TableNode *this = getFirstEntry(scope); + int largest = 0; + int k = getRecLength(node); + int total_size = 0; + int counter = 0; + int *offsets = (int *)calloc(2 * k, sizeof(int)); + if (getAdInfoType(this) == TYPE_FUNCTION_DECLARATION) { + offsets[counter] = 8; + total_size = total_size + offsets[counter]; + largest = 8; + counter++; + } else if ((getAdInfoType(this) == TYPE_RECORD)) { + offsets[counter] = 8; + total_size = total_size + offsets[counter]; + largest = offsets[counter]; + counter++; + } else if (getAdInfoType(this) == TYPE_PRIMITIVE) { + offsets[counter] = getPrimSize(getTypeEntry(this)); + total_size = total_size + offsets[counter]; + largest = offsets[counter]; + counter++; + } else if (getAdInfoType(this) == TYPE_ARRAY) { + offsets[counter] = 8; + total_size = total_size + offsets[counter]; + largest = offsets[counter]; + counter++; + } else { + printdebug( + "[TYPE CHECK] passed an invalid (first) parameter to a function definition. seeing %d. Type of entry is %s. Name attempted to pass is %s.", getAdInfoType(this), getType(this), getName(this)); + + return undefined; + } + this = getNextEntry(this); + while (this != NULL) { + if (getAdInfoType(this) == TYPE_FUNCTION_DECLARATION) { + int s = 8; + if (s > largest) { + largest = s; + } + //make sure current location is aligned properly + offsets[counter] = (total_size % s); + total_size = total_size + offsets[counter]; + counter++; + //add in the size of the entry and increment + offsets[counter] = s; + total_size = total_size + offsets[counter]; + counter++; + this = getNextEntry(this); + } else if (getAdInfoType(this) == TYPE_ARRAY) { + int s = 8; + if (s > largest) { + largest = s; + } + //make sure current location is aligned properly + offsets[counter] = (total_size % s); + total_size = total_size + offsets[counter]; + counter++; + //add in the size of the entry and increment + offsets[counter] = s; + total_size = total_size + offsets[counter]; + counter++; + this = getNextEntry(this); + } else if ((getAdInfoType(this) == TYPE_RECORD)) { + int s = 8; + if (s > largest) { + largest = s; + } + //make sure current location is aligned properly + printTableNode(this); + printTableNode(node); + offsets[counter] = (total_size % s); + total_size = total_size + offsets[counter]; + counter++; + //add in the size of the entry and increment + offsets[counter] = s; + total_size = total_size + offsets[counter]; + counter++; + this = getNextEntry(this); + } else if (getAdInfoType(this) == TYPE_PRIMITIVE) { + int s = getPrimSize(getTypeEntry(this)); + if (s > largest) { + largest = s; + } + //make sure current location is aligned properly + offsets[counter] = (total_size % s); + total_size = total_size + offsets[counter]; + counter++; + //add in the size of the entry and increment + offsets[counter] = s; + total_size = total_size + offsets[counter]; + counter++; + this = getNextEntry(this); + } else { + printdebug( + "[TYPE CHECK] passed an invalid parameter at position %d in record.", ((counter + 1) / 2)); + return undefined; + } + } + //make sure that size of whole structure is aligned with largest element in struct: + offsets[counter] = (total_size % largest); + total_size = total_size + offsets[counter]; + node->additionalinfo->RecAdInfo->offsets = offsets; + node->additionalinfo->RecAdInfo->total_size = total_size; + return node; +} + +int *getRecOffsets(TableNode *node) { + if (node == NULL) { + printdebug( + "passed a NULL node to getRecTotal. Invalid."); + return NULL; + } + if (getAdInfoType(node) != TYPE_RECORD_TYPE) { + printdebug( + "passed an invalid node to getRecTotal. Invalid."); + return NULL; + } + if (node->additionalinfo == NULL) { + printdebug( + "node has NULL additionalinfo. Invalid."); + return NULL; + } + return node->additionalinfo->RecAdInfo->offsets; +} +int getRecLength(TableNode *definition) { + if (definition == NULL) { + printdebug( + "passed an NULL entry to getRecLength " + "function. Invalid."); + return -1; + } + if (definition == undefined) { + printdebug( + "passed an undefined entry to getRecLength " + "function. Invalid."); + return -1; + } + if (strcmp(getType(definition), "record") != 0) { + printdebug( + "not checking the length of an record -- invalid op"); + return 0; + } + return definition->additionalinfo->RecAdInfo->numofelements; +} +// This gets the array. Needs to up be updated to get the scope instead +SymbolTable *getRecList(TableNode *definition) { + if (definition == NULL) { + printdebug( + "passed a NULL entry to getRecList " + "function. Invalid."); + return NULL; + } + if (definition == undefined) { + printdebug( + "passed an undefined entry to getRecList " + "function. Invalid."); + return NULL; + } + if (strcmp(getType(definition), "record") != 0) { + printdebug( + "not checking the list of types of a record -- invalid " + "op of type %s", + getType(definition)); + return NULL; + } + return definition->additionalinfo->RecAdInfo->recordScope; +} + +TableNode *setRecSize(TableNode *tn, int n) { + if (tn == NULL) { + printdebug("passed in NULL entry for setRecSize. Invalid"); + return undefined; + } + if (tn == undefined) { + printdebug("passed in undefined entry for setRecSize. Invalid"); + return undefined; + } + tn->additionalinfo->RecAdInfo->numofelements = n; + return tn; +} + +int getRecSize(SymbolTable *tn) { + if (tn == NULL) { + printdebug( + "passed in NULL SymbolTable for getRecSize. Invalid"); + return -1; + } + int s = 1; + TableNode *cur = getFirstEntry(tn); + if (cur != NULL) { + while (getNextEntry(cur) != NULL) { + s++; + cur = getNextEntry(cur); + } + return s; + } + return -1; +} + +// below function takes a bool to see if parameter should be decomposed or not +; // note that functions only take one input and have one output +// using "as" the input record can be decomposed to give the illusion of +// multiple inputs Below function also has the line number where the function is +// first defined +AdInfo *CreateFunctionDeclarationInfo(int line, bool asorregular) { + AdInfo *info = (AdInfo *)malloc(sizeof(AdInfo)); + info->FunDecAdInfo = (function_declaration_info *)malloc( + sizeof(function_declaration_info)); + info->FunDecAdInfo->startlinenumber = line; + info->FunDecAdInfo->regularoras = asorregular; + return info; +} +// gets the line at which the function was first defined. (Can be used to print +// out in table if needed) +int getStartLine(TableNode *definition) { + if (definition == NULL) { + printdebug( + "passed a NULL entry to getStartLine " + "function. Invalid."); + return -1; + } + if (definition == undefined) { + printdebug( + "passed an undefined entry to getStartLine " + "function. Invalid."); + return -1; + } + if (strcmp(getType(definition), "primitive function") != 0) { + printdebug( + "not checking the start line of a function -- invalid " + "op"); + return 0; + } + return definition->additionalinfo->FunDecAdInfo->startlinenumber; +} + +TableNode *setStartLine(TableNode *tn, int start) { + if (tn == NULL) { + printdebug( + "passing in a NULL entry to setStartLine. " + "invalid"); + return undefined; + } + if (tn == undefined) { + printdebug( + "passing in an undefined entry to setStartLine. " + "invalid"); + return undefined; + } + tn->additionalinfo->FunDecAdInfo->startlinenumber = start; + return tn; +} +// checks if "as" keyword was used for function definition. Either 0 or 1 for +// not used or used. +bool getAsKeyword(TableNode *definition) { + if (definition == NULL) { + printdebug( + "passed a NULL entry to getAsKeyword " + "function. Invalid."); + return false; + } + if (definition == undefined) { + printdebug( + "passed an undefined entry to getAsKeyword " + "function. Invalid."); + return false; + } + if (strcmp(getType(definition), "primitive function") != 0) { + printdebug( + "not checking if a function is called with as or " + "not (%s) -- " + "invalid op", + getType(definition)); + return 0; + } + return definition->additionalinfo->FunDecAdInfo->regularoras; +} + +TableNode *setAsKeyword(TableNode *tn, bool as) { + if (tn == NULL) { + printdebug( + "passing in a NULL entry to setAsKeyword. " + "invalid"); + return undefined; + } + if (tn == undefined) { + printdebug( + "passing in an undefined entry to setAsKeyword. " + "invalid"); + return undefined; + } + tn->additionalinfo->FunDecAdInfo->regularoras = as; + return tn; +} + +// stores the type of a function (parameter type and return type) +AdInfo *CreateFunctionTypeInfo(TableNode *parameter, TableNode *returntype) { + if (parameter == NULL) { + printdebug( + "passed a NULL parameter to " + "CreateFunctionTypeInfo. Invalid."); + return NULL; + } + if (parameter == undefined) { + printdebug( + "passed an undefined parameter to " + "CreateFunctionTypeInfo. Invalid."); + return NULL; + } + if (returntype == NULL) { + printdebug( + "passed a NULL return type to " + "CreateFunctionTypeInfo. Invalid."); + return NULL; + } + if (returntype == undefined) { + printdebug( + "passed an undefined return type to " + "CreateFunctionTypeInfo. Invalid."); + return NULL; + } + AdInfo *info = (AdInfo *)malloc(sizeof(AdInfo)); + info->FunTypeAdInfo = + (function_type_info *)malloc(sizeof(function_type_info)); + info->FunTypeAdInfo->parameter = parameter; + info->FunTypeAdInfo->returntype = returntype; + return info; +} +// returns parameter type of a function +TableNode *getParameter(TableNode *definition) { + if (definition == NULL) { + printdebug( + "passed a NULL entry to getParameter " + "function. Invalid."); + return undefined; + } + if (definition == undefined) { + printdebug( + "passed an undefined entry to getParameter " + "function. Invalid."); + return undefined; + } + if (definition->additionalinfo == NULL) { + printdebug( + "node has NULL additionalinfo. Invalid."); + return undefined; + } + if (strcmp(getType(definition), "primitive function type") != 0) { + printdebug( + "not checking the parameter of a function -- invalid op"); + return undefined; + } + return definition->additionalinfo->FunTypeAdInfo->parameter; +} +// returns return type of a function +TableNode *getReturn(TableNode *definition) { + if (definition == NULL) { + printdebug( + "passed a NULL entry to getReturn " + "function. Invalid."); + return undefined; + } + if (definition == undefined) { + printdebug( + "passed an undefined entry to getReturn " + "function. Invalid."); + return undefined; + } + if (strcmp(getType(definition), "primitive function type") != 0) { + printdebug( + "not checking the return of a function -- invalid op"); + return undefined; + } + if (definition->additionalinfo == NULL) { + printdebug( + "node has NULL additionalinfo. Invalid."); + return undefined; + } + return definition->additionalinfo->FunTypeAdInfo->returntype; +} + +// creates a new scope (not the top scope though) +SymbolTable *CreateScope(SymbolTable *ParentScope, int Line, int Column) { + SymbolTable *table = (SymbolTable *)malloc(sizeof(SymbolTable)); + table->Line_Number = Line; + table->Column_Number = Column; + table->Parent_Scope = ParentScope; + table->Children_Scope = NULL; + table->entries = NULL; + if (ParentScope != NULL) { + if (ParentScope->Children_Scope == NULL) { + ListOfTable *newEntry = + (ListOfTable *)malloc(sizeof(ListOfTable)); + newEntry->next = NULL; + // newEntry->prev = NULL; + newEntry->table = table; + ParentScope->Children_Scope = newEntry; + } else { + ListOfTable *newEntry = + (ListOfTable *)malloc(sizeof(ListOfTable)); + // newEntry->prev = NULL; + newEntry->table = table; + ListOfTable *oldEntry = ParentScope->Children_Scope; + ParentScope->Children_Scope = newEntry; + newEntry->next = oldEntry; + } + } + return table; +} + +// create entry just for things below top level scope +// This function defines the integer, address, character, and bool primitive +// types +SymbolTable *init(SymbolTable *start) { + if (start->Parent_Scope != NULL) { + printdebug( + "%s[FATAL] Cannot initialize a scope that is not " + "the parent scope", + COLOR_RED); + return NULL; + } + integ = (TableNode *)calloc(1, sizeof(TableNode)); + addr = (TableNode *)calloc(1, sizeof(TableNode)); + chara = (TableNode *)calloc(1, sizeof(TableNode)); + stri = (TableNode *)calloc(1, sizeof(TableNode)); + boo = (TableNode *)calloc(1, sizeof(TableNode)); + TableNode *reservetype = (TableNode *)calloc(1, sizeof(TableNode)); + TableNode *reserve = (TableNode *)calloc(1, sizeof(TableNode)); + TableNode *releasetype = (TableNode *)calloc(1, sizeof(TableNode)); + TableNode *release = (TableNode *)calloc(1, sizeof(TableNode)); + // TableNode* arr = (TableNode*)malloc(sizeof(SymbolTable)); + start->entries = integ; + integ->next = addr; + addr->next = chara; + chara->next = stri; + stri->next = boo; + boo->next = reservetype; + reservetype->next = reserve; + reserve->next = releasetype; + releasetype->next = release; + release->next = NULL; + + integ->theName = "integer"; + addr->theName = "address"; + chara->theName = "character"; + boo->theName = "Boolean"; + stri->theName = "string"; + reserve->theName = "reserve"; + reservetype->theName = "reserve type"; + releasetype->theName = "release type"; + release->theName = "release"; + // arr->theName= "array" + + // root TableNode that all are pointing to but not in table + // This is only to solve the issue that all entries must have a name and + // a type and the type must point to an actual table entry Again, this + // primitive table entry isn't in the top scope. It is outside the top + // scope and is only there to facilitate the fact that these are + // primitive + TableNode *prime = (TableNode *)malloc(sizeof(TableNode)); + prime->theName = "primitive"; + prime->theType = NULL; + prime->additionalinfo = NULL; + prime->next = NULL; + prime->tag = TYPE_SYSTEM_DEFINED; + + // not sure exatly how to get array types to look right so using a dummy + // Table Node below and updating the print symbol table function to + // access the additional information to print for array types, similar + // to function types when printing symbol table, if array is seen + arrayprim = (TableNode *)malloc(sizeof(TableNode)); + arrayprim->theName = "array"; + arrayprim->theType = NULL; + arrayprim->additionalinfo = NULL; + arrayprim->next = NULL; + prime->tag = TYPE_SYSTEM_DEFINED; + + // funprime = CreateEntry(NULL,NULL,strdup("function primitive"),NULL); + + // similar workaround to arrays above + funprime = (TableNode *)malloc(sizeof(TableNode)); + funprime->theName = "primitive function"; + funprime->theType = NULL; + funprime->additionalinfo = NULL; + funprime->next = NULL; + funprime->tag = TYPE_SYSTEM_DEFINED; + + // record + recprime = (TableNode *)malloc(sizeof(TableNode)); + recprime->theName = "record"; + recprime->theType = NULL; + recprime->additionalinfo = NULL; + recprime->next = NULL; + recprime->tag = TYPE_SYSTEM_DEFINED; + + funtypeprime = (TableNode *)malloc(sizeof(TableNode)); + funtypeprime->theName = "primitive function type"; + funtypeprime->theType = NULL; + funtypeprime->additionalinfo = NULL; + funtypeprime->next = NULL; + funtypeprime->tag = TYPE_SYSTEM_DEFINED; + + undefined = (TableNode *)malloc(sizeof(TableNode)); + undefined->theName = "undefined"; + undefined->theType = NULL; + undefined->additionalinfo = NULL; + undefined->next = NULL; + undefined->tag = TYPE_SYSTEM_DEFINED; + + // Undefined_function_type_info = CreateFunctionTypeInfo(undefined, + // undefined); + + integ->theType = prime; + addr->theType = prime; + chara->theType = prime; + stri->theType = arrayprim; + boo->theType = prime; + reserve->theType = reservetype; + reservetype->theType = funtypeprime; + releasetype->theType = funtypeprime; + release->theType = releasetype; + + // arr->theType=arrayprim; + + // filling in all the values for the additional info for initial types + // These numbers below for create primitive specifically are supposed to + // be the size of these primitive types. We can change these if needed + // to not be hard coded numbers as a reminder, stri below is defined as + // a one dimensional array of characters + integ->additionalinfo = CreatePrimitiveInfo(SIZE_INT); + addr->additionalinfo = CreatePrimitiveInfo(SIZE_ADDR); + chara->additionalinfo = CreatePrimitiveInfo(SIZE_CHAR); + stri->additionalinfo = CreateArrayInfo(1, chara); + boo->additionalinfo = CreatePrimitiveInfo(SIZE_BOOL); + reserve->additionalinfo = CreateFunctionDeclarationInfo(0, false); + reservetype->additionalinfo = CreateFunctionTypeInfo(integ, addr); + releasetype->additionalinfo = CreateFunctionTypeInfo(addr, integ); + release->additionalinfo = CreateFunctionDeclarationInfo(0, false); + + integ->tag = TYPE_PRIMITIVE_TYPE; // explicitly set the type for integ + addr->tag = TYPE_PRIMITIVE_TYPE; // explicitly set the type for addr + chara->tag = TYPE_PRIMITIVE_TYPE; // explicitly set the type for chara + stri->tag = TYPE_ARRAY_TYPE; // explicitly set the type for stri + boo->tag = TYPE_PRIMITIVE_TYPE; // explicitly set the type for boo + reserve->tag = TYPE_FUNCTION_DECLARATION; + reservetype->tag = TYPE_FUNCTION_TYPE; + releasetype->tag = TYPE_FUNCTION_TYPE; + release->tag = TYPE_FUNCTION_DECLARATION; + // addr->additionalinfo = CreatePrimitiveInfo(8); + + start->Line_Number = 1; + start->Column_Number = 1; + start->Parent_Scope = NULL; + start->Children_Scope = NULL; + + return start; +} +/* +TableNode* integ; +TableNode* addr; +TableNode* chara; +TableNode* stri; +TableNode* boo; +TableNode* recprime; +TableNode* funtypeprime; +*/ +TableNode *populateTypeAndInfo(TableNode *tn, TableNode *type, AdInfo *info) { + if (tn == NULL) { + printdebug( + "passed in an NULL table node to populateTypeAndInfo."); + return undefined; + } + if (tn == undefined) { + printdebug( + "passed in an undefined table node to populateTypeAndInfo"); + return undefined; + } + if (type == NULL) { + printdebug( + "passed in a NULL type reference to " + "populate a table node. Invalid."); + return undefined; + } + if (type == undefined) { + printdebug( + "passed in an undefined type reference to " + "populate a table node. Invalid."); + return undefined; + } + if (info == NULL) { + printdebug( + "passed in a NULL info reference to populate a table " + "node. Invalid."); + return undefined; + } + tn->theType = type; + tn->additionalinfo = info; + // returning reference to modified table node + return tn; +} + +AdInfo *getAdInfo(TableNode *tn) { + if (tn == NULL) { + printdebug("passed a NULL table entry to getAdInfo. Invalid."); + return NULL; + } + if (tn == undefined) { + printdebug( + "passed an undefined table entry to getAdInfo. Invalid."); + return NULL; + } + if (tn->additionalinfo == NULL) { + printdebug( + "no additional info found in the table node. Invalid."); + return NULL; + } + return tn->additionalinfo; +} + +// simplified getAdInfoType +int getAdInfoType(TableNode *tn) { + if (tn == NULL) { + printdebug( + "passing in NULL table entry to getAdInfoType. Invalid"); + return -1; + } + return tn->tag; + /* + if (tn == undefined) { + printdebug("passing in undefined table entry to getAdInfoType. " + "Invalid"); + return -1; + } + if (tn->theType == NULL) { + printdebug("Entry being passed in has a null" + "reference for theType to getAdInfoType. Invalid."); + return -1; + } + if (tn->theType == undefined) { + printdebug("Entry being passed in an undefined " + "reference for theType to getAdInfoType. Invalid."); + return -1; + } + if (strcmp(getName(tn), getName(integ)) == 0) { + return TYPE_PRIMITIVE; + } + if (strcmp(getName(tn), getName(addr)) == 0) { + return TYPE_PRIMITIVE; + } + if (strcmp(getName(tn), getName(chara)) == 0) { + return TYPE_PRIMITIVE; + } + if (strcmp(getName(tn), getName(stri)) == 0) { + return TYPE_ARRAY_TYPE; + } + if (strcmp(getName(tn), getName(boo)) == 0) { + return TYPE_PRIMITIVE; + } + if (strcmp(getName(tn), getName(recprime)) == 0) { + return TYPE_RECORD_TYPE; + } + if (strcmp(getName(tn), getName(funtypeprime)) == 0) { + return TYPE_FUNCTION_TYPE; + } + if (strcmp(getName(tn), getName(arrayprim)) == 0) { + return TYPE_ARRAY_TYPE; // changed from TYPE_ARRAY cuz + } + if (strcmp(getName(tn), getName(undefined)) == 0) { + return TYPE_UNDEFINED; + } else { + if (strcmp(getType(tn), getName(funtypeprime)) == 0) { + printdebug("passed in a function to getAdInfoType"); + return TYPE_FUNCTION_DECLARATION; + } + if (strcmp(getType(tn), getName(arrayprim)) == 0) { + printdebug("passed in an array to getAdInfoType"); + return TYPE_ARRAY_TYPE; + } + if (strcmp(getType(tn), getName(recprime)) == 0) { + printdebug("passed in a record to getAdInfoType"); + return TYPE_RECORD; + } + printdebug( + "passed in an entry that is not a primitive type, array, " + "or record. Invalid."); + return TYPE_FUNCTION_DECLARATION; + }*/ +} + +TableNode *CreateEntry(SymbolTable *table, int tag, TableNode *typeOf, char *id, + AdInfo *ad) { + if (table == NULL) { + printdebug("Null reference to table"); + return undefined; + } + + /* + TableNode* topDef = (table_lookup(getAncestor(table),typeOf)); + if(topDef == NULL){ + printdebug("This type is not defined at the top level"); return NULL; } - TableNode* ret = table_lookup(table, x); - if (ret != NULL) { - return ret; - } - return look_up(table->Parent_Scope, x); + */ + if (typeOf == NULL) { + printdebug("Passing an NULL Type Node to Create Entry"); + return undefined; + } + if (typeOf == undefined) { + printdebug("Passing an undefined Type Node to Create Entry"); + return undefined; + } + + TableNode *newEntry = (TableNode *)calloc(1, sizeof(TableNode)); + if (tag < 1 && tag > 11) { + printdebug( + "Note- not passing in valid 'tag' identifier to " + "create entry function. Setting tag to undefined"); + newEntry->tag = TYPE_UNDEFINED; + } else { + newEntry->tag = tag; + } + newEntry->theType = typeOf /*topDef*/; + newEntry->theName = id; + newEntry->additionalinfo = ad; + if (table->entries == NULL) { + table->entries = newEntry; + printdebug("[CreateEntry] Adding %s to the symbol table", id); + return newEntry; + } else { + TableNode *oldEntry = table->entries; + table->entries = newEntry; + newEntry->next = oldEntry; + printdebug("[CreateEntry] Adding %s to the symbol table", id); + return newEntry; + } } -void print_symbol_table(SymbolTable* table, FILE* file_ptr) { - if (table->Parent_Scope == NULL) { - fprintf(file_ptr, "%-17s: %-6s : %-6s : %-21s: %-28s\n", "NAME", "SCOPE", - "PARENT", "TYPE", "Extra annotation"); +TableNode *getTypeEntry(TableNode *tn) { + if (tn == NULL) { + printdebug("passed a NULL table entry to getType"); + return undefined; + } + if (tn == undefined) { + printdebug("passed an undefined table entry to getType"); + return undefined; + } + if (tn->theType == NULL) { + printdebug("type of entry is currently NULL type"); + return undefined; + } + if (tn->theType == undefined) { + printdebug("type of entry is currently undefined type"); + return undefined; + } + return tn->theType; +} + +char *getType(TableNode *tn) { + if (tn == NULL) { + printdebug("passed a NULL table entry to getType"); + return getName(undefined); + } + if (tn == undefined) { + printdebug("passed an undefined table entry to getType"); + return getName(undefined); + } + if (tn->theType == NULL) { + printdebug("type of entry is currently NULL type"); + return getName(undefined); + } + if (tn->theType == undefined) { + printdebug("type of entry is currently undefined type"); + return getName(undefined); + } + return tn->theType->theName; +} + +char *getName(TableNode *tn) { + if (tn == NULL) { + printdebug("passed a NULL table entry to getName"); + return undefined->theName; + } + if (tn == undefined) { + printdebug("passed an undefined table entry to getName"); + return undefined->theName; + } + if (tn->theName == NULL) { + printdebug("name of entry is currently NULL, undefined"); + return undefined->theName; + } + return tn->theName; +} + +int getLine(SymbolTable *st) { + if (st == NULL) { + printdebug( + "passed a NULL symbol table to getLine function. " + "Invalid."); + return -1; + } + return st->Line_Number; +} +int getColumn(SymbolTable *st) { + if (st == NULL) { + printdebug( + "passed a NULL symbol table to getColumn function. " + "Invalid."); + return -1; + } + return st->Column_Number; +} +TableNode *addName(TableNode *tn, char *str) { + if (tn == NULL) { + printdebug( + "passed a Null table node to the addName " + "function. Invalid."); + return undefined; + } + if (tn == undefined) { + printdebug( + "passed an undefined table node to the addName " + "function. Invalid."); + return undefined; + } + if (tn->theName != NULL) { + // printdebug( + //"Name doesn't look like it is empty before you change. " + //"Are you sure you need to update name?"); + if (str != NULL) { + tn->theName = str; + return tn; } - TableNode* entrie = table->entries; - fprintf(file_ptr, - "-----------------:--------:--------:----------------------:---------" - "--------------------\n"); - int parant_scope = 0; - int current_scope = 0; - if (table->Parent_Scope != NULL) { - parant_scope = table->Parent_Scope->Line_Number * 1000 + - table->Parent_Scope->Column_Number; - current_scope = table->Line_Number * 1000 + table->Column_Number; - } else { - current_scope = 1001; + printdebug("passed a NULL string to the addName function"); + return undefined; + } + if (str == NULL) { + printdebug( + "passed a NULL string to the addName function. Invalid."); + return undefined; + } + tn->theName = str; + return tn; +} + +SymbolTable *setLineNumber(SymbolTable *st, int line) { + if (st == NULL) { + printdebug( + "passed a Null Symbol Table to the setLineNumber " + "function. Invalid."); + return st; + } + st->Line_Number = line; + return st; +} + +SymbolTable *setColumnNumber(SymbolTable *st, int column) { + if (st == NULL) { + printdebug( + "passed a Null Symbol Table to the setColumnNumber " + "function. Invalid."); + return st; + } + st->Line_Number = column; + return st; +} + +// only check table that is given +TableNode *table_lookup(SymbolTable *table, char *x) { + if (table == NULL) { + printdebug("passed in empty scope. error."); + return undefined; + } + TableNode *entrie = table->entries; + for (; entrie != NULL; entrie = entrie->next) { + if (!strcmp(entrie->theName, x)) { + return entrie; } - if ( entrie == NULL ) { - fprintf(file_ptr, "%-17s: %06d : %06d : %-21s: %-28s\n", "", - current_scope, parant_scope, "", "Empty Scope"); + } + printdebug("Could not find %s in scope using table_lookup", x); + return undefined; +} + +// check current table and all parents +TableNode *look_up(SymbolTable *table, char *x) { + if (table == NULL) { + printdebug("Could not find %s in any scope using lookup", x); + return undefined; + } + TableNode *ret = table_lookup(table, x); + if (ret != NULL && ret != undefined) { + return ret; + } + printdebug( + "could not find %s in scope that started at line %d and column " + "%d so moving up a scope", + x, getLine(table), getColumn(table)); + return look_up(table->Parent_Scope, x); +} +int col_widths[5] = {30, 8, 8, 35, 35}; +void printline(FILE *file_ptr, bool b) { + if (b) { + fprintf(file_ptr, "oop\n"); + } + + for (int i = 0; i < 5; i++) { + for (int ii = 0; ii < col_widths[i]; ii++) { + fprintf(file_ptr, "-"); } - for (; entrie != NULL; entrie = entrie->next) { - if (parant_scope == 0) { - fprintf(file_ptr, "%-17s: %06d : : %-21s: %-28s\n", - entrie->theName, current_scope, entrie->theType, - "Extra annotation"); + fprintf(file_ptr, ":"); + } + fprintf(file_ptr, "\n"); +} + +void st_fprint(FILE *file_ptr, char *label1, int label2, int label3, char *label4, char *label5) { + if (label3 == -100) { + fprintf(file_ptr, "%-*s: %0*d : %*s :%-*s:%-*s\n", + col_widths[0], (label1 ? label1 : ""), + col_widths[1] - 2, label2, + col_widths[2] - 2, "", + col_widths[3], (label4 ? label4 : ""), + col_widths[4], (label5 ? label5 : "")); + } else { + fprintf(file_ptr, "%-*s: %0*d : %0*d :%-*s:%-*s\n", + col_widths[0], (label1 ? label1 : ""), + col_widths[1] - 2, label2, + col_widths[2] - 2, label3, + col_widths[3], (label4 ? label4 : ""), + col_widths[4], (label5 ? label5 : "")); + } +} + +void print_symbol_table(SymbolTable *table, FILE *file_ptr) { + if (table == NULL) { + printdebug("%s[FATAL] passed in NULL table to print_symbol_table", COLOR_RED); + return; + } + + if (table->Parent_Scope == NULL) { + fprintf(file_ptr, "%-*s:%-*s:%-*s:%-*s:%-*s:\n", + col_widths[0], "NAME", + col_widths[1], " SCOPE", + col_widths[2], " PARENT", + col_widths[3], " TYPE", + col_widths[4], " EXTRA ANNOTATION"); + } + + TableNode *entry = table->entries; + printline(file_ptr, false); + int parentScopeNum = 0; + int currentScopeNum = 0; + + if (table->Parent_Scope != NULL) { + parentScopeNum = getParent(table)->Line_Number * 1000 + getParent(table)->Column_Number; + currentScopeNum = table->Line_Number * 1000 + table->Column_Number; + } else { + currentScopeNum = 1001; + } + + if (entry == NULL) { + st_fprint(file_ptr, "", currentScopeNum, parentScopeNum, "", " Empty Scope"); + } + + for (; entry != NULL; entry = getNextEntry(entry)) { + if (getAdInfoType(entry) == TYPE_ARRAY_TYPE) { + char *arrayType = (char *)malloc(100); + sprintf(arrayType, " %d -> %s", getNumArrDim(entry), + getName(getArrType(entry))); + + if (parentScopeNum == 0) { + st_fprint(file_ptr, getName(entry), currentScopeNum, -100, arrayType, " Type of Array"); + } else { + st_fprint(file_ptr, getName(entry), currentScopeNum, parentScopeNum, arrayType, " Type of Array"); + } + } + if (getAdInfoType(entry) == TYPE_ARRAY) { + char *arrayType = (char *)malloc(sizeof(getType(entry) + 1)); + sprintf(arrayType, " %s", getType(entry)); + if (parentScopeNum == 0) { + st_fprint(file_ptr, getName(entry), currentScopeNum, -100, arrayType, " Array Instance"); + } else { + st_fprint(file_ptr, getName(entry), currentScopeNum, parentScopeNum, arrayType, " Array Instance"); + } + } + if (getAdInfoType(entry) == TYPE_RECORD_TYPE) { + char *recordAdInfo = (char *)malloc(100); + sprintf(recordAdInfo, " elements-%d size-%d bytes", getRecLength(entry), getRecTotal(entry)); + if (parentScopeNum == 0) { + st_fprint(file_ptr, getName(entry), currentScopeNum, -100, " Record Type", recordAdInfo); + } else { + st_fprint(file_ptr, getName(entry), currentScopeNum, parentScopeNum, " Record Type", recordAdInfo); + } + } + + if (getAdInfoType(entry) == TYPE_RECORD) { + char *recordAdInfo = (char *)malloc(100); + sprintf(recordAdInfo, " elements-%d", getRecLength(entry)); + char *recordType = (char *)malloc(sizeof(getType(entry) + 1)); + sprintf(recordType, " %s", getType(entry)); + if (parentScopeNum == 0) { + st_fprint(file_ptr, getName(entry), currentScopeNum, -100, recordType, " Record Instance"); + } else { + st_fprint(file_ptr, getName(entry), currentScopeNum, parentScopeNum, recordType, " Record Instance"); + } + } + + if (getAdInfoType(entry) == TYPE_PRIMITIVE_TYPE) { + char *primAdInfo = (char *)malloc(100); + sprintf(primAdInfo, " size-%d bytes", getPrimSize(entry)); + if (parentScopeNum == 0) { + st_fprint(file_ptr, getName(entry), currentScopeNum, -100, " Primitive Type", primAdInfo); + } else { + char *primType = (char *)malloc(sizeof(getType(entry) + 1)); + sprintf(primType, " %s", getType(entry)); + st_fprint(file_ptr, getName(entry), currentScopeNum, parentScopeNum, primType, primAdInfo); + } + } + if (getAdInfoType(entry) == TYPE_PRIMITIVE) { + char *primAdInfo = (char *)malloc(100); + sprintf(primAdInfo, " size-%d bytes", getPrimSize(getTypeEntry(entry))); + if (parentScopeNum == 0) { + st_fprint(file_ptr, getName(entry), currentScopeNum, -100, " Primitive", primAdInfo); + } else { + char *primType = (char *)malloc(sizeof(getType(entry) + 1)); + sprintf(primType, " %s", getType(entry)); + st_fprint(file_ptr, getName(entry), currentScopeNum, parentScopeNum, primType, " Primitive Instance"); + } + } + + if (getAdInfoType(entry) == TYPE_FUNCTION_TYPE) { + char *functiontype = (char *)malloc(100); + sprintf(functiontype, " %s -> %s", getName(getParameter(entry)), + getName(getReturn(entry))); + if (parentScopeNum == 0) { + st_fprint(file_ptr, getName(entry), currentScopeNum, -100, functiontype, " Type of Function"); + } else { + st_fprint(file_ptr, getName(entry), currentScopeNum, parentScopeNum, functiontype, " Type of Function"); + } + } + + if (getAdInfoType(entry) == TYPE_FUNCTION_DECLARATION) { + char *functiontype = (char *)malloc(100); + sprintf(functiontype, " %s", getName(getReturn(entry))); + if (parentScopeNum == 0) { + st_fprint(file_ptr, getName(entry), currentScopeNum, -100, functiontype, " Function Definition"); + } else { + st_fprint(file_ptr, getName(entry), currentScopeNum, parentScopeNum, functiontype, " Function Definition"); + } + } + + if (getAdInfoType(entry) == TYPE_UNDEFINED) { + if (parentScopeNum == 0) { + st_fprint(file_ptr, getName(entry), currentScopeNum, -100, " undefined", "undefined entry"); + } else { + st_fprint(file_ptr, getName(entry), currentScopeNum, parentScopeNum, " undefined", "undefined entry"); + } + } + } + + if (getChildren(table) != NULL) { + ListOfTable *node = getChildren(table); + for (; node != NULL; node = getRestOfChildren(node)) { + if ((getFirstChild(node)) == NULL) { + print_symbol_table(getFirstChild(node), file_ptr); + } else { + if (getLine(getFirstChild(node)) == -1) { + continue; } else { - fprintf(file_ptr, "%-17s: %06d : %06d : %-21s: %-28s\n", entrie->theName, - current_scope, parant_scope, entrie->theType, "Extra annotation"); + print_symbol_table(getFirstChild(node), file_ptr); } + } } - if (table->Children_Scope != NULL) { - ListOfTable* node = table->Children_Scope; - for (; node != NULL; node = node->next) { - print_symbol_table(node->table, file_ptr); - } - } - if (table->Parent_Scope == NULL) { - fprintf(file_ptr, - "-----------------:--------:--------:----------------------:-------" - "----------------------\n"); - } -} + } -SymbolTable* getAncestor(SymbolTable* table) { - if (table->Parent_Scope == NULL) { - // if table has no parent, return itself - return table; + if (getParent(table) == NULL) { + printline(file_ptr, true); + } +} +// get top most symbol table +SymbolTable *getAncestor(SymbolTable *table) { + if (table == NULL) { + printdebug("passing a NULL reference to getAncestor. Invalid."); + return NULL; + } + if (table->Parent_Scope == NULL) { + // if table has no parent, return itself + printdebug("already at top scope!"); + if (table == cur) { + printdebug("passed in the current scope"); } else { - // call function recursively to grab ancestor - return getAncestor(table->Parent_Scope); + printdebug("passed in a different scope"); } + return table; + } else { + // call function recursively to grab ancestor + return getAncestor(table->Parent_Scope); + } } -SymbolTable* getParent(SymbolTable* st) { return st->Parent_Scope; } +SymbolTable *removeEntry(SymbolTable *scope, char *search) { + if (scope == NULL) { + return NULL; + } + if (scope->entries == NULL) { + return scope; + } -ListOfTable* getChildren(SymbolTable* st) { return st->Children_Scope; } -SymbolTable* getFirstChild(ListOfTable* lt) { return lt->table; } -ListOfTable* getRestOfChildren(ListOfTable* lt) { return lt->next; } -TableNode* getFirstEntry(SymbolTable* st) { return st->entries; } -TableNode* getNextEntry(TableNode* tn) { return tn->next; } -char* getType(TableNode* tn) { return tn->theType; } -char* getName(TableNode* tn) { return tn->theName; } -int getLine(SymbolTable* st) { return st->Line_Number; } -int getColumn(SymbolTable* st) { return st->Column_Number; } -// uncomment the below main function along with the headers above for a simple -// standalone test of table and entry creation + TableNode *prev = NULL; + TableNode *now = scope->entries; -/* - int main(){ - char* String = "STRING"; - char* X = "X"; - SymbolTable* Second = CreateScope(NULL, 2,2); - printf("Line number is %d, Column number of scope is - %d\n",Second->Line_Number,Second->Column_Number); TableNode* First_Entry = - CreateEntry(Second,String,X); + while (now != NULL) { + if (strcmp(getName(now), search) == 0) { + if (prev == NULL) { + scope->entries = getNextEntry(now); + return scope; + } else { + prev->next = now->next; + return scope; + } + } + prev = now; + now = now->next; + } + return scope; +} - printf("The type of the first entry is %s\n",First_Entry->theType); - return 0; - } - */ +// almost certainly don't need to use the below function since type checking +// happens by passing types up the grammar +bool typeCheck(char *firstID, char *secondID) { + TableNode *entry1 = look_up(cur, firstID); + TableNode *entry2 = look_up(cur, secondID); + if (entry1 == NULL) { + printdebug("first type is NULL in type check. Invalid."); + return false; + } + if (entry1 == undefined) { + printdebug("first type is undefined in type check. Invalid."); + return false; + } + if (entry2 == NULL) { + printdebug("second type is NULL in type check. Invalid."); + return false; + } + if (entry2 == undefined) { + printdebug("second type is undefined in type check. Invalid."); + return false; + } + if (table_lookup(getAncestor(cur), getType(look_up(cur, firstID))) == + table_lookup(getAncestor(cur), getType(look_up(cur, secondID)))) { + if (strcmp(getType(look_up(cur, firstID)), "array") == 0) { + if (look_up(cur, firstID) + ->additionalinfo->ArrayAdInfo + ->numofdimensions == + look_up(cur, secondID) + ->additionalinfo->ArrayAdInfo + ->numofdimensions && + look_up(cur, firstID) + ->additionalinfo->ArrayAdInfo + ->typeofarray == + look_up(cur, secondID) + ->additionalinfo->ArrayAdInfo + ->typeofarray) { + return true; + } else { + return false; + } + } + return true; + } + return false; +} + +SymbolTable *getParent(SymbolTable *st) { + if (st == NULL) { + printdebug( + "passed a NULL symbol table to getParent function. " + "Invalid."); + return NULL; + } + if (st->Parent_Scope == NULL) { + printdebug( + "passed a top level scope to getParent function. " + "Invalid."); + return st; + } + return st->Parent_Scope; +} + +ListOfTable *getChildren(SymbolTable *st) { return st->Children_Scope; } +SymbolTable *getFirstChild(ListOfTable *lt) { return lt->table; } +ListOfTable *getRestOfChildren(ListOfTable *lt) { return lt->next; } +TableNode *getFirstEntry(SymbolTable *st) { return st->entries; } + +// Segfaults when passed an invalid table node! +TableNode *getNextEntry(TableNode *tn) { + if (tn == NULL) { + printdebug("passed a NULL table node to getNextEntry"); + return undefined; + } + if (tn == undefined) { + printdebug("passed an undefined table node to getNextEntry"); + return undefined; + } + return tn->next; +} + +// Prints all info about a table node +// Uses pointers to the table node to print the info +TableNode *printTableNode(TableNode *tn) { + if (DEBUG == 0) { + return tn; + } + + if (tn == NULL) { + printdebug("%s[PrintTN] Passed a NULL tablenode!", COLOR_RED); + return undefined; + } + if (tn == undefined) { + printdebug("%s[PrintTN] Passed an undefined tablenode!", + COLOR_RED); + return undefined; + } + if (tn->theName == NULL) { + printdebug("%s[PrintTN] Passed a tablenode with NULL name!", + COLOR_RED); + return undefined; + } + if (tn->theType == NULL) { + printdebug("%s[PrintTN] Passed a tablenode with NULL type!", + COLOR_RED); + return undefined; + } + if (tn->additionalinfo == NULL) { + printdebug( + "%s[PrintTN] Passed a tablenode with NULL additional info!", + COLOR_RED); + return undefined; + } + + printdebug("%s[PrintTN] Printing tablenode...", COLOR_ORANGE); + printdebug(" %sName: %s%s", COLOR_YELLOW, COLOR_LIGHTBLUE, + tn->theName); + printdebug(" %sType: %s%s", COLOR_YELLOW, COLOR_LIGHTBLUE, + tn->theType->theName); + printdebug(" %sTag: %s%d", COLOR_YELLOW, COLOR_LIGHTBLUE, tn->tag); + + if (tn->next == NULL) { + printdebug(" %sNext: %sNULL", COLOR_YELLOW, COLOR_LIGHTBLUE); + } else { + printdebug(" %sNext: %s%s (tn)", COLOR_YELLOW, COLOR_LIGHTBLUE, tn->next->theName); + } + + if (tn->tag == TYPE_RECORD_TYPE || tn->tag == TYPE_RECORD) { + printdebug(" %sAdditional Info: %sRecAdInfo", COLOR_YELLOW, + COLOR_LIGHTBLUE); + printdebug(" %snumberOfElements: %s%d", COLOR_YELLOW, + COLOR_LIGHTBLUE, + tn->additionalinfo->RecAdInfo->numofelements); + if (tn->additionalinfo->RecAdInfo->recordScope == NULL) { + printdebug(" %srecordScope (line): %s(NULL)", + COLOR_YELLOW, COLOR_LIGHTBLUE); + } else { + printdebug(" %srecordScope (line): %s%d", + COLOR_YELLOW, COLOR_LIGHTBLUE, + tn->additionalinfo->RecAdInfo->recordScope + ->Line_Number); + } + } else if (tn->tag == TYPE_ARRAY_TYPE || tn->tag == TYPE_ARRAY) { + printdebug(" %sAdditional Info: %sArrayAdInfo", COLOR_YELLOW, + COLOR_LIGHTBLUE); + printdebug(" %snumberOfDimensions: %s%d", COLOR_YELLOW, + COLOR_LIGHTBLUE, + tn->additionalinfo->ArrayAdInfo->numofdimensions); + printdebug( + " %stypeOfArray: %s%s", COLOR_YELLOW, + COLOR_LIGHTBLUE, + tn->additionalinfo->ArrayAdInfo->typeofarray->theName); + } else if (tn->tag == TYPE_FUNCTION_TYPE) { + printdebug(" %sAdditional Info: %sFunTypeAdInfo", + COLOR_YELLOW, COLOR_LIGHTBLUE); + printdebug( + " %sparameter: %s%s", COLOR_YELLOW, COLOR_LIGHTBLUE, + tn->additionalinfo->FunTypeAdInfo->parameter->theName); + printdebug( + " %sreturntype: %s%s", COLOR_YELLOW, COLOR_LIGHTBLUE, + tn->additionalinfo->FunTypeAdInfo->returntype->theName); + } else if (tn->tag == TYPE_FUNCTION_DECLARATION) { + printdebug(" %sAdditional Info: %sFunDecAdInfo", + COLOR_YELLOW, COLOR_LIGHTBLUE); + printdebug(" %sstartLineNumber: %s%d", COLOR_YELLOW, + COLOR_LIGHTBLUE, + tn->additionalinfo->FunDecAdInfo->startlinenumber); + printdebug(" %sregularOrAs: %s%s", COLOR_YELLOW, + COLOR_LIGHTBLUE, + tn->additionalinfo->FunDecAdInfo->regularoras + ? "true" + : "false"); + } else if (tn->tag == TYPE_PRIMITIVE) { + printdebug(" %sAdditional Info: %sPrimAdInfo", COLOR_YELLOW, + COLOR_LIGHTBLUE); + printdebug(" %ssize: %s%d", COLOR_YELLOW, + COLOR_LIGHTBLUE, + tn->additionalinfo->PrimAdInfo->size); + } else { + printdebug(" AdInfo not handled."); + } + + return tn; +} diff --git a/src/symbol_table.h b/src/symbol_table.h index 03028ad..391f05a 100644 --- a/src/symbol_table.h +++ b/src/symbol_table.h @@ -1,42 +1,194 @@ +/* Symbol Table */ +/* The Translators - Spring 2025 */ + +#pragma once + +#include #include +#include #include #include #include +#define SIZE_INT 4 +#define SIZE_ADDR 8 +#define SIZE_CHAR 1 +#define SIZE_BOOL 1 + +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* prev; - struct ListOfTable* next; + struct SymbolTable *table; + struct ListOfTable *next; } ListOfTable; typedef struct TableNode { - char* theType; - char* theName; - struct TableNode* next; + 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; + TableNode *entries; + struct SymbolTable *Parent_Scope; + struct ListOfTable *Children_Scope; + int Line_Number; + int Column_Number; } SymbolTable; -SymbolTable* CreateScope(SymbolTable* ParentScope, int Line, int Column); -TableNode* CreateEntry(SymbolTable* table, char* typeOf, char* id); -TableNode* table_lookup(SymbolTable* table, char* x); -TableNode* look_up(SymbolTable* table, char* x); -void print_symbol_table(SymbolTable* table, FILE* file_ptr); +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; -SymbolTable* getAncestor(SymbolTable* table); -SymbolTable* getParent(SymbolTable* st); -ListOfTable* getChildren(SymbolTable* st); -SymbolTable* getFirstChild(ListOfTable* lt); -ListOfTable* getRestOfChildren(ListOfTable* lt); -TableNode* getFirstEntry(SymbolTable* st); -TableNode* getNextEntry(TableNode* tn); -char* getType(TableNode* tn); -char* getName(TableNode* tn); -int getLine(SymbolTable* st); -int getColumn(SymbolTable* st); +void printdebug_impl(char *file, int line, const char *format, ...); +#define printdebug(format, ...) \ + printdebug_impl(__FILE__, __LINE__, format, ##__VA_ARGS__) + +char *temp_var_gen(); +Constant_Stack *Push(TableNode *type, void *value, bool isConst); +Constant_Stack *Pop(); +Constant_Stack *Print_Stack(); +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 getRecTotal(TableNode *node); +TableNode *setRecOffsetInfo(SymbolTable *scope, TableNode *node); +int *getRecOffsets(TableNode *node); +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); +AdInfo *getAdInfo(TableNode *tn); +int getAdInfoType(TableNode *tn); +TableNode *CreateEntry(SymbolTable *table, int tag, TableNode *typeOf, char *id, AdInfo *ad); +TableNode *getTypeEntry(TableNode *tn); +char *getType(TableNode *tn); +char *getName(TableNode *tn); +int getLine(SymbolTable *st); +int getColumn(SymbolTable *st); +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 printline(FILE *file_ptr, bool b); +void st_fprint(FILE *file_ptr, char *label1, int label2, int label3, char *label4, char *label5); +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); + +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; \ No newline at end of file diff --git a/src/typedefs.h b/src/typedefs.h index 5405f66..5c476bf 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -1,3 +1,6 @@ +/* Type Definitions */ +/* The Translators - Spring 2025 */ + // identifier #define ID 101 // type names diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..3f6f5a9 --- /dev/null +++ b/test.sh @@ -0,0 +1,166 @@ +#!/bin/bash + +# Test Tool # +# The Translators - Spring 2025 # + +RED='\033[0;31m' +GREEN='\033[0;32m' +ORANGE='\033[0;33m' +BLUE='\033[0;34m' +PURPLE='\033[0;35m' +CYAN='\033[0;36m' +LIGHTGRAY='\033[0;37m' +DARKGRAY='\033[1;30m' +LIGHTRED='\033[1;31m' +LIGHTGREEN='\033[1;32m' +YELLOW='\033[1;33m' +LIGHTBLUE='\033[1;34m' +LIGHTPURPLE='\033[1;35m' +LIGHTCYAN='\033[1;36m' +WHITE='\033[1;37m' + +if [ ! -f "./alpha" ]; then + echo -e "${RED}[ERROR] ${YELLOW}File ./alpha not found!${WHITE}" + exit 1 +fi + +if [ ! -d "./out" ]; then + mkdir -p out +fi + +SWITCH=${YELLOW} +count=0 + +switchfunc() { + if [ $count -eq 0 ]; then + count=1 + SWITCH=${YELLOW} + else + count=0 + SWITCH='\033[0;35m' + fi +} + +if [ $# -eq 0 ]; then + echo -e "${YELLOW}[INFO] ${WHITE}Running all tests...${WHITE}" + echo -e "${YELLOW}[INFO] ${ORANGE}Testing SPRINT-1 ---------------------------\n${WHITE}" + for file in ./tests/sprint1/test/*; do + if [ -f "$file" ]; then + filename=$(basename -- "$file") + echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" + ./alpha -st -debug "$file" + echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n" + switchfunc + fi + done + echo -e "" + + echo -e "${YELLOW}[INFO] ${ORANGE}Testing SPRINT-2 ---------------------------\n${WHITE}" + for file in ./tests/sprint2/test/*; do + if [ -f "$file" ]; then + filename=$(basename -- "$file") + echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" + ./alpha -st -debug "$file" + echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n" + switchfunc + fi + done + echo -e "" + + echo -e "${YELLOW}[INFO] ${ORANGE}Testing SPRINT-3 ---------------------------\n${WHITE}" + for file in ./tests/sprint3/test/*; do + if [ -f "$file" ]; then + filename=$(basename -- "$file") + echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" + ./alpha -st -debug "$file" + echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n" + switchfunc + fi + done + echo -e "" + + echo -e "${YELLOW}[INFO] ${ORANGE}Testing SPRINT-4 ---------------------------\n${WHITE}" + for file in ./tests/sprint4/test/*; do + if [ -f "$file" ]; then + filename=$(basename -- "$file") + echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" + ./alpha -cg "$file" + echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n${WHITE}" + switchfunc + fi + done + +else + if [ "$1" == "--help" ]; then + echo -e "${YELLOW}[INFO] ${WHITE}Usage: ./test.sh [prefix]" + echo -e "${YELLOW}[INFO] ${WHITE}--help: show this help message" + echo -e "${YELLOW}[INFO] ${WHITE}--file : run test with file" + exit 0 + fi + if [[ "$1" == "--file" ]]; then + shift + if [ $# -eq 0 ]; then + echo -e "${RED}[ERROR] ${YELLOW}No file specified!${WHITE}" + exit 1 + fi + if [ -f "$1" ]; then + filename=$(basename -- "$1") + echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" + ./alpha -st -debug "$1" + echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}" + exit 1 + else + echo -e "${RED}[ERROR] ${YELLOW}File $1 not found!${WHITE}" + exit 1 + fi + fi + + if [[ "$1" == "sp1" ]]; then + echo -e "${YELLOW}[INFO] ${WHITE}Running tests with prefix $1..." + for file in ./tests/sprint1/test/*; do + if [[ "$file" == *"$1"* ]]; then + filename=$(basename -- "$file") + echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" + ./alpha -st -debug "$file" + echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n" + switchfunc + fi + done + elif [[ "$1" == "sp2" ]]; then + echo -e "${YELLOW}[INFO] ${WHITE}Running tests with prefix $1..." + for file in ./tests/sprint2/test/*; do + if [[ "$file" == *"$1"* ]]; then + filename=$(basename -- "$file") + echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" + ./alpha -st -debug "$file" + echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n" + switchfunc + fi + done + elif [[ "$1" == "sp3" ]]; then + echo -e "${YELLOW}[INFO] ${WHITE}Running tests with prefix $1..." + for file in ./tests/sprint3/test/*; do + if [[ "$file" == *"$1"* ]]; then + filename=$(basename -- "$file") + echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" + ./alpha -st -debug "$file" + echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n" + switchfunc + fi + done + elif [[ "$1" == "sp4" ]]; then + echo -e "${YELLOW}[INFO] ${WHITE}Running tests with prefix $1..." + for file in ./tests/sprint4/test/*; do + if [[ "$file" == *"$1"* ]]; then + filename=$(basename -- "$file") + echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" + ./alpha -cg -debug "$file" + echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n" + switchfunc + fi + done + else + echo -e "${RED}[ERROR] ${YELLOW}Invalid prefix $1!${WHITE}" + exit 1 + fi +fi diff --git a/tests/carl/Errors/entry.undeclaredType.alpha b/tests/carl/Errors/entry.undeclaredType.alpha new file mode 100644 index 0000000..6b9531f --- /dev/null +++ b/tests/carl/Errors/entry.undeclaredType.alpha @@ -0,0 +1,10 @@ +type M : string -> integer + +function foo : M + +foo (s) := { + [ + int: x + ] + return 0; +} diff --git a/tests/carl/Errors/entry.undeclaredType.alpha.asc b/tests/carl/Errors/entry.undeclaredType.alpha.asc new file mode 100644 index 0000000..cd1d37c --- /dev/null +++ b/tests/carl/Errors/entry.undeclaredType.alpha.asc @@ -0,0 +1,16 @@ +alpha parser, version 0.2 (2023-03-04) - Annotated Source Code for file entry.undeclaredType.alpha +001: type M : string -> integer +002: +003: function foo : M +004: +005: foo (s) := { +006: [ +007: int: x + ^0 ^1 + LINE 7:9 ** ERROR #0: the name 'int', used here as a type, has not been declared at this point in the program. + LINE 7:14 ** ERROR #1: the name 'x' is being declared with an unknown type. + +008: ] +009: return 0; +010: } +011: diff --git a/tests/carl/Errors/entry.undeclaredVar.alpha b/tests/carl/Errors/entry.undeclaredVar.alpha new file mode 100644 index 0000000..6cd5fa7 --- /dev/null +++ b/tests/carl/Errors/entry.undeclaredVar.alpha @@ -0,0 +1,7 @@ +type M : string -> integer + +function entry : M + +entry(s) := { + return x; +} diff --git a/tests/carl/Errors/entry.undeclaredVar.alpha.asc b/tests/carl/Errors/entry.undeclaredVar.alpha.asc new file mode 100644 index 0000000..7c4e6c2 --- /dev/null +++ b/tests/carl/Errors/entry.undeclaredVar.alpha.asc @@ -0,0 +1,12 @@ +alpha parser, version 0.2 (2023-03-04) - Annotated Source Code for file entry.undeclaredVar.alpha +001: type M : string -> integer +002: +003: function entry : M +004: +005: entry(s) := { +006: return x; + ^0 + LINE 6:12 ** ERROR #0: the name 'x', used here as a variable name, has not been declared at this point in the program. + +007: } +008: diff --git a/tests/carl/Errors/error.operator.alpha b/tests/carl/Errors/error.operator.alpha new file mode 100644 index 0000000..a7b0691 --- /dev/null +++ b/tests/carl/Errors/error.operator.alpha @@ -0,0 +1,14 @@ +type string2int: string -> integer + +function entry : string2int + +entry(arg) := { + [ integer: i; integer: sum ] + sum := 0; + i := 0; + while (i < 10) { + sum = sum + i; + i := i + 1; + } + return 0; +} diff --git a/tests/carl/Errors/error.operator.alpha.asc b/tests/carl/Errors/error.operator.alpha.asc new file mode 100644 index 0000000..82f5614 --- /dev/null +++ b/tests/carl/Errors/error.operator.alpha.asc @@ -0,0 +1,19 @@ +alpha parser, version 0.2 (2023-03-04) - Annotated Source Code for file error.operator.alpha +001: type string2int: string -> integer +002: +003: function entry : string2int +004: +005: entry(arg) := { +006: [ integer: i; integer: sum ] +007: sum := 0; +008: i := 0; +009: while (i < 10) { +010: sum = sum + i; + ^0 + LINE 10:13 ** ERROR #0: assignment operator (:=) expected but equality operator (=) found. + +011: i := i + 1; +012: } +013: return 0; +014: } +015: diff --git a/tests/carl/NoErrors/entry.definition.alpha b/tests/carl/NoErrors/entry.definition.alpha new file mode 100644 index 0000000..0003cd5 --- /dev/null +++ b/tests/carl/NoErrors/entry.definition.alpha @@ -0,0 +1,8 @@ +(* type string : 1 -> character *) +type M : string -> integer + +function entry : M + +entry(s) := { + return 0; +} diff --git a/tests/carl/NoErrors/entry.definition.alpha.asc b/tests/carl/NoErrors/entry.definition.alpha.asc new file mode 100644 index 0000000..07dbd42 --- /dev/null +++ b/tests/carl/NoErrors/entry.definition.alpha.asc @@ -0,0 +1,10 @@ +alpha parser, version 0.2 (2023-03-04) - Annotated Source Code for file entry.definition.alpha +001: (* type string : 1 -> character *) +002: type M : string -> integer +003: +004: function entry : M +005: +006: entry(s) := { +007: return 0; +008: } +009: diff --git a/tests/carl/NoErrors/entry.duplicateDifferent.alpha b/tests/carl/NoErrors/entry.duplicateDifferent.alpha new file mode 100644 index 0000000..5cbd668 --- /dev/null +++ b/tests/carl/NoErrors/entry.duplicateDifferent.alpha @@ -0,0 +1,11 @@ +type M : string -> integer + +function entry : M + +entry(s) := { + [ + integer: x; + character: x + ] + return x; +} diff --git a/tests/carl/NoErrors/entry.duplicateDifferent.alpha.asc b/tests/carl/NoErrors/entry.duplicateDifferent.alpha.asc new file mode 100644 index 0000000..65ae8d8 --- /dev/null +++ b/tests/carl/NoErrors/entry.duplicateDifferent.alpha.asc @@ -0,0 +1,13 @@ +alpha parser, version 0.2 (2023-03-04) - Annotated Source Code for file entry.duplicateDifferent.alpha +001: type M : string -> integer +002: +003: function entry : M +004: +005: entry(s) := { +006: [ +007: integer: x; +008: character: x +009: ] +010: return x; +011: } +012: diff --git a/tests/carl/NoErrors/entry.duplicateSame.alpha b/tests/carl/NoErrors/entry.duplicateSame.alpha new file mode 100644 index 0000000..554b9d8 --- /dev/null +++ b/tests/carl/NoErrors/entry.duplicateSame.alpha @@ -0,0 +1,9 @@ +type M : string -> integer +function entry : M + +entry(s) := { + [ + integer: x; integer: x + ] + return x; +} diff --git a/tests/carl/NoErrors/entry.duplicateSame.alpha.asc b/tests/carl/NoErrors/entry.duplicateSame.alpha.asc new file mode 100644 index 0000000..7861cc6 --- /dev/null +++ b/tests/carl/NoErrors/entry.duplicateSame.alpha.asc @@ -0,0 +1,11 @@ +alpha parser, version 0.2 (2023-03-04) - Annotated Source Code for file entry.duplicateSame.alpha +001: type M : string -> integer +002: function entry : M +003: +004: entry(s) := { +005: [ +006: integer: x; integer: x +007: ] +008: return x; +009: } +010: diff --git a/tests/carl/NoErrors/entry.local.alpha b/tests/carl/NoErrors/entry.local.alpha new file mode 100644 index 0000000..cff2062 --- /dev/null +++ b/tests/carl/NoErrors/entry.local.alpha @@ -0,0 +1,11 @@ +type M : string -> integer + +function entry : M + +entry(s) := { + [ + integer: x + ] + x := 0; + return x; +} diff --git a/tests/carl/NoErrors/entry.local.alpha.asc b/tests/carl/NoErrors/entry.local.alpha.asc new file mode 100644 index 0000000..e9882d4 --- /dev/null +++ b/tests/carl/NoErrors/entry.local.alpha.asc @@ -0,0 +1,13 @@ +alpha parser, version 0.2 (2023-03-04) - Annotated Source Code for file entry.local.alpha +001: type M : string -> integer +002: +003: function entry : M +004: +005: entry(s) := { +006: [ +007: integer: x +008: ] +009: x := 0; +010: return x; +011: } +012: diff --git a/tests/carl/NoErrors/error.none.alpha b/tests/carl/NoErrors/error.none.alpha new file mode 100644 index 0000000..85aa4f2 --- /dev/null +++ b/tests/carl/NoErrors/error.none.alpha @@ -0,0 +1,14 @@ +type string2int: string -> integer + +function entry : string2int + +entry(arg) := { + [ integer: i ; integer: sum ] + sum := 0; + i := 0 ; + while (i < 10) { + sum := sum + i; + i := i + 1; + } + return 0; +} diff --git a/tests/carl/NoErrors/error.none.alpha.asc b/tests/carl/NoErrors/error.none.alpha.asc new file mode 100644 index 0000000..9fdcadb --- /dev/null +++ b/tests/carl/NoErrors/error.none.alpha.asc @@ -0,0 +1,16 @@ +alpha parser, version 0.2 (2023-03-04) - Annotated Source Code for file error.none.alpha +001: type string2int: string -> integer +002: +003: function entry : string2int +004: +005: entry(arg) := { +006: [ integer: i ; integer: sum ] +007: sum := 0; +008: i := 0 ; +009: while (i < 10) { +010: sum := sum + i; +011: i := i + 1; +012: } +013: return 0; +014: } +015: diff --git a/tests/carl/NoErrors/function.declaration.alpha b/tests/carl/NoErrors/function.declaration.alpha new file mode 100644 index 0000000..69f210f --- /dev/null +++ b/tests/carl/NoErrors/function.declaration.alpha @@ -0,0 +1,3 @@ +type M : integer -> integer + +function f : M diff --git a/tests/carl/NoErrors/function.declaration.alpha.asc b/tests/carl/NoErrors/function.declaration.alpha.asc new file mode 100644 index 0000000..fca046a --- /dev/null +++ b/tests/carl/NoErrors/function.declaration.alpha.asc @@ -0,0 +1,5 @@ +alpha parser, version 0.2 (2023-03-04) - Annotated Source Code for file function.declaration.alpha +001: type M : integer -> integer +002: +003: function f : M +004: diff --git a/tests/carl/NoErrors/function.definition.alpha b/tests/carl/NoErrors/function.definition.alpha new file mode 100644 index 0000000..b729610 --- /dev/null +++ b/tests/carl/NoErrors/function.definition.alpha @@ -0,0 +1,7 @@ +type M : integer -> integer + +function f : M + +f(x) := { + return x; +} diff --git a/tests/carl/NoErrors/function.definition.alpha.asc b/tests/carl/NoErrors/function.definition.alpha.asc new file mode 100644 index 0000000..e476758 --- /dev/null +++ b/tests/carl/NoErrors/function.definition.alpha.asc @@ -0,0 +1,9 @@ +alpha parser, version 0.2 (2023-03-04) - Annotated Source Code for file function.definition.alpha +001: type M : integer -> integer +002: +003: function f : M +004: +005: f(x) := { +006: return x; +007: } +008: diff --git a/tests/carl/NoErrors/functionValue.alpha b/tests/carl/NoErrors/functionValue.alpha new file mode 100644 index 0000000..f521a42 --- /dev/null +++ b/tests/carl/NoErrors/functionValue.alpha @@ -0,0 +1,73 @@ +(* Type definitions *) + +(* mapping type *) +type string2int: string -> integer + +(* array of functions *) +type funArray: 1 -> string2int + +(* record of functions *) +type funRec: [ string2int: f; string2int: g ] + +(* function returning function *) +type integer_2_string2int: integer -> string2int + +(* function returning function *) +type string2int_2_integer: string2int -> integer + + +type iXiXc: [integer: a; integer: b; character: c] + +type iic2b: iXiXc -> Boolean + +(* Function declarations using the above type definitions *) +function a: string2int +function b: integer_2_string2int +function c: string2int_2_integer + +function d: iic2b + +d(x,y,z) := { + return (x < y & z < 'm'); +} + +function entry: string2int + +a(x) := { + [string : s] + s := x; + return 0; +} + +b(x) := { + [integer: i] + i := x; + return a; +} + +c(x) := { + [string: s] + s := "Hi!"; + return x(s); +} + + +(* Function definition + entry is the first function called + *) +entry(arg) := { + [integer: result; string2int: f; integer: temp] + temp := a("Hello"); + f := b(temp); + result := c(f); + if (d(1,2,'c')) + then { + result := 0; + } + else { + [ Boolean : b] + result := entry("hello"); + } + result := c(f); + return result; +} diff --git a/tests/carl/NoErrors/functionValue.alpha.asc b/tests/carl/NoErrors/functionValue.alpha.asc new file mode 100644 index 0000000..882d558 --- /dev/null +++ b/tests/carl/NoErrors/functionValue.alpha.asc @@ -0,0 +1,75 @@ +alpha parser, version 0.2 (2023-03-04) - Annotated Source Code for file functionValue.alpha +001: (* Type definitions *) +002: +003: (* mapping type *) +004: type string2int: string -> integer +005: +006: (* array of functions *) +007: type funArray: 1 -> string2int +008: +009: (* record of functions *) +010: type funRec: [ string2int: f; string2int: g ] +011: +012: (* function returning function *) +013: type integer_2_string2int: integer -> string2int +014: +015: (* function returning function *) +016: type string2int_2_integer: string2int -> integer +017: +018: +019: type iXiXc: [integer: a; integer: b; character: c] +020: +021: type iic2b: iXiXc -> Boolean +022: +023: (* Function declarations using the above type definitions *) +024: function a: string2int +025: function b: integer_2_string2int +026: function c: string2int_2_integer +027: +028: function d: iic2b +029: +030: d(x,y,z) := { +031: return (x < y & z < 'm'); +032: } +033: +034: function entry: string2int +035: +036: a(x) := { +037: [string : s] +038: s := x; +039: return 0; +040: } +041: +042: b(x) := { +043: [integer: i] +044: i := x; +045: return a; +046: } +047: +048: c(x) := { +049: [string: s] +050: s := "Hi!"; +051: return x(s); +052: } +053: +054: +055: (* Function definition +056: entry is the first function called +057: *) +058: entry(arg) := { +059: [integer: result; string2int: f; integer: temp] +060: temp := a("Hello"); +061: f := b(temp); +062: result := c(f); +063: if (d(1,2,'c')) +064: then { +065: result := 0; +066: } +067: else { +068: [ Boolean : b] +069: result := entry("hello"); +070: } +071: result := c(f); +072: return result; +073: } +074: diff --git a/tests/carl/NoErrors/sample.good.alpha b/tests/carl/NoErrors/sample.good.alpha new file mode 100644 index 0000000..8a8b727 --- /dev/null +++ b/tests/carl/NoErrors/sample.good.alpha @@ -0,0 +1,29 @@ + +(* Type definitions *) +type int2int: integer -> integer +type string2int: string -> integer + +(* Function declarations + They use the above type definitions +*) +function square : int2int +function entry : string2int + +(* Function definition + Functions must be declared before they are defined + *) +square(x) := { + return x * x; +} + +(* Function definition + entry is the first function called + *) +entry(arg) := { + [ integer: input ; integer: expected ; integer: actual ; Boolean: result ] + input := 7; + expected := 49; + actual := square(input); + result := expected = actual; + return 0; +} diff --git a/tests/carl/NoErrors/sample.good.alpha.asc b/tests/carl/NoErrors/sample.good.alpha.asc new file mode 100644 index 0000000..a4bfa3a --- /dev/null +++ b/tests/carl/NoErrors/sample.good.alpha.asc @@ -0,0 +1,31 @@ +alpha parser, version 0.2 (2023-03-04) - Annotated Source Code for file sample.good.alpha +001: +001: (* Type definitions *) +003: type int2int: integer -> integer +004: type string2int: string -> integer +005: +006: (* Function declarations +007: They use the above type definitions +008: *) +009: function square : int2int +010: function entry : string2int +011: +012: (* Function definition +013: Functions must be declared before they are defined +014: *) +015: square(x) := { +016: return x * x; +017: } +018: +019: (* Function definition +020: entry is the first function called +021: *) +022: entry(arg) := { +023: [ integer: input ; integer: expected ; integer: actual ; Boolean: result ] +024: input := 7; +025: expected := 49; +026: actual := square(input); +027: result := expected = actual; +028: return 0; +029: } +030: diff --git a/tests/carl/NoErrors/selectionSort.alpha b/tests/carl/NoErrors/selectionSort.alpha new file mode 100644 index 0000000..edd2076 --- /dev/null +++ b/tests/carl/NoErrors/selectionSort.alpha @@ -0,0 +1,68 @@ +(* Type definitions *) + +type string2int: string -> integer +type intArray: 1 -> integer +type intArrayXinteger: [ intArray: data; integer: index ] +type intArrayXinteger2integer: intArrayXinteger -> integer +type intArray2Boolean: intArray -> Boolean + + +(* Function declarations + They use the above type definitions +*) +function indexOfSmallest: intArrayXinteger2integer +function selectionSort: intArray2Boolean +function entry : string2int + +(* indexOfSmallest *) +indexOfSmallest (* as *) (data, startingIndex) := { + [ integer: indexOfSmallestSoFar; integer: i ] + indexOfSmallestSoFar := startingIndex; + i := 0 ; + while (i < data._1 ) { + if ( data(i) < data(indexOfSmallestSoFar) ) + then { + indexOfSmallestSoFar := i; + } + else { + i := i; + } + i := i + 1; + } + return indexOfSmallestSoFar; +} + + +(* selectionSort *) +selectionSort(data) := { + [ integer: i ] + i := 0 ; + while (i < data._1 ) { + [ integer: index; integer: temp ] + index := indexOfSmallest(data,i); + temp := data(index); + data(index) := data(i); + data(i) := temp; + i := i + 1; + } + return true; +} + + +(* Function definition + entry is the first function called + *) +entry(arg) := { + [ intArray: data; Boolean: _ ] + data := reserve data(8); + data(0) := 60; + data(1) := 80; + data(2) := 10; + data(3) := 50; + data(4) := 30; + data(5) := 40; + data(6) := 20; + data(7) := 70; + _ := selectionSort(data); + return 0; +} diff --git a/tests/carl/NoErrors/selectionSort.alpha.asc b/tests/carl/NoErrors/selectionSort.alpha.asc new file mode 100644 index 0000000..2a12877 --- /dev/null +++ b/tests/carl/NoErrors/selectionSort.alpha.asc @@ -0,0 +1,70 @@ +alpha parser, version 0.2 (2023-03-04) - Annotated Source Code for file selectionSort.alpha +001: (* Type definitions *) +002: +003: type string2int: string -> integer +004: type intArray: 1 -> integer +005: type intArrayXinteger: [ intArray: data; integer: index ] +006: type intArrayXinteger2integer: intArrayXinteger -> integer +007: type intArray2Boolean: intArray -> Boolean +008: +009: +010: (* Function declarations +011: They use the above type definitions +012: *) +013: function indexOfSmallest: intArrayXinteger2integer +014: function selectionSort: intArray2Boolean +015: function entry : string2int +016: +017: (* indexOfSmallest *) +018: indexOfSmallest (* as *) (data, startingIndex) := { +019: [ integer: indexOfSmallestSoFar; integer: i ] +020: indexOfSmallestSoFar := startingIndex; +021: i := 0 ; +022: while (i < data._1 ) { +023: if ( data(i) < data(indexOfSmallestSoFar) ) +024: then { +025: indexOfSmallestSoFar := i; +026: } +027: else { +028: i := i; +029: } +030: i := i + 1; +031: } +032: return indexOfSmallestSoFar; +033: } +034: +035: +036: (* selectionSort *) +037: selectionSort(data) := { +038: [ integer: i ] +039: i := 0 ; +040: while (i < data._1 ) { +041: [ integer: index; integer: temp ] +042: index := indexOfSmallest(data,i); +043: temp := data(index); +044: data(index) := data(i); +045: data(i) := temp; +046: i := i + 1; +047: } +048: return true; +049: } +050: +051: +052: (* Function definition +053: entry is the first function called +054: *) +055: entry(arg) := { +056: [ intArray: data; Boolean: _ ] +057: data := reserve data(8); +058: data(0) := 60; +059: data(1) := 80; +060: data(2) := 10; +061: data(3) := 50; +062: data(4) := 30; +063: data(5) := 40; +064: data(6) := 20; +065: data(7) := 70; +066: _ := selectionSort(data); +067: return 0; +068: } +069: diff --git a/tests/carl/NoErrors/type.array.alpha b/tests/carl/NoErrors/type.array.alpha new file mode 100644 index 0000000..2b04ba0 --- /dev/null +++ b/tests/carl/NoErrors/type.array.alpha @@ -0,0 +1 @@ +type A : 1 -> integer diff --git a/tests/carl/NoErrors/type.array.alpha.asc b/tests/carl/NoErrors/type.array.alpha.asc new file mode 100644 index 0000000..8e6154d --- /dev/null +++ b/tests/carl/NoErrors/type.array.alpha.asc @@ -0,0 +1,3 @@ +alpha parser, version 0.2 (2023-03-04) - Annotated Source Code for file type.array.alpha +001: type A : 1 -> integer +002: diff --git a/tests/carl/NoErrors/type.mapping.alpha b/tests/carl/NoErrors/type.mapping.alpha new file mode 100644 index 0000000..8b6bc50 --- /dev/null +++ b/tests/carl/NoErrors/type.mapping.alpha @@ -0,0 +1,2 @@ +type M : integer -> character + diff --git a/tests/carl/NoErrors/type.mapping.alpha.asc b/tests/carl/NoErrors/type.mapping.alpha.asc new file mode 100644 index 0000000..2ce8f0c --- /dev/null +++ b/tests/carl/NoErrors/type.mapping.alpha.asc @@ -0,0 +1,4 @@ +alpha parser, version 0.2 (2023-03-04) - Annotated Source Code for file type.mapping.alpha +001: type M : integer -> character +002: +003: diff --git a/tests/carl/NoErrors/type.record.alpha b/tests/carl/NoErrors/type.record.alpha new file mode 100644 index 0000000..2c5e9c9 --- /dev/null +++ b/tests/carl/NoErrors/type.record.alpha @@ -0,0 +1 @@ +type R : [ integer : i ; character : c ] diff --git a/tests/carl/NoErrors/type.record.alpha.asc b/tests/carl/NoErrors/type.record.alpha.asc new file mode 100644 index 0000000..848948b --- /dev/null +++ b/tests/carl/NoErrors/type.record.alpha.asc @@ -0,0 +1,3 @@ +alpha parser, version 0.2 (2023-03-04) - Annotated Source Code for file type.record.alpha +001: type R : [ integer : i ; character : c ] +002: diff --git a/tests/carl/NoErrors/types.alpha b/tests/carl/NoErrors/types.alpha new file mode 100644 index 0000000..0402f95 --- /dev/null +++ b/tests/carl/NoErrors/types.alpha @@ -0,0 +1,75 @@ +(* + + At compiler start-up your program should + create symbol table entries for the following + built-in types: + + Boolean (1 byte) + character (1 byte) + integer (4 bytes) + address (8 bytes) + + and the following privileged type (it has literals): + + type string: 1 -> character + + Your compiler can define other types during + its start-up routine as well, if it is helpful + to do so. + +*) + + + +type BooleanXBoolean: [Boolean: x; Boolean: y] +type characterXcharacter: [character: x; character: y] +type integerXinteger: [integer: x; integer: y] + +type Boolean2Boolean: Boolean -> Boolean +type integer2integer: integer -> integer + +type character2integer: character -> integer +type Boolean2integer: Boolean -> integer +type string2integer: string -> integer + +type integerXinteger2integer: integerXinteger -> integer + +type integerXinteger2Boolean: integerXinteger -> Boolean +type characterXcharacter2Boolean: characterXcharacter -> Boolean +type BooleanXBoolean2Boolean: BooleanXBoolean -> Boolean + + +type integer2address: integer -> address +type address2integer: address -> integer + + +(* The alpha library functions + You will be provided with x86-64 assembly + code implementations of these. +*) + +external function printInteger: integer2integer +external function printCharacter: character2integer +external function printBoolean: Boolean2integer + +(* + A declaration of the entry point function for your program + + You may assume that when starting this function will behave as if + it had been called from the C language main function like this: + + int main(int argc, char * argv[]) { + if (argc == 1) { + return entry(NULL); + } + else { + return entry(makeAlphaString(argv[1])); + } + } + + for some suitable definition of makeAlphaString which creates + an alpha string representation of its argument C string in memory + and returns a pointer to that alpha string. +*) + +function entry: string2integer diff --git a/tests/carl/NoErrors/types.alpha.asc b/tests/carl/NoErrors/types.alpha.asc new file mode 100644 index 0000000..8844865 --- /dev/null +++ b/tests/carl/NoErrors/types.alpha.asc @@ -0,0 +1,77 @@ +alpha parser, version 0.2 (2023-03-04) - Annotated Source Code for file types.alpha +001: (* +001: +002: At compiler start-up your program should +003: create symbol table entries for the following +004: built-in types: +005: +006: Boolean (1 byte) +007: character (1 byte) +008: integer (4 bytes) +009: address (8 bytes) +010: +011: and the following privileged type (it has literals): +012: +013: type string: 1 -> character +014: +015: Your compiler can define other types during +016: its start-up routine as well, if it is helpful +017: to do so. +018: +019: *) +021: +022: +023: +024: type BooleanXBoolean: [Boolean: x; Boolean: y] +025: type characterXcharacter: [character: x; character: y] +026: type integerXinteger: [integer: x; integer: y] +027: +028: type Boolean2Boolean: Boolean -> Boolean +029: type integer2integer: integer -> integer +030: +031: type character2integer: character -> integer +032: type Boolean2integer: Boolean -> integer +033: type string2integer: string -> integer +034: +035: type integerXinteger2integer: integerXinteger -> integer +036: +037: type integerXinteger2Boolean: integerXinteger -> Boolean +038: type characterXcharacter2Boolean: characterXcharacter -> Boolean +039: type BooleanXBoolean2Boolean: BooleanXBoolean -> Boolean +040: +041: +042: type integer2address: integer -> address +043: type address2integer: address -> integer +044: +045: +046: (* The alpha library functions +047: You will be provided with x86-64 assembly +048: code implementations of these. +049: *) +050: +051: external function printInteger: integer2integer +052: external function printCharacter: character2integer +053: external function printBoolean: Boolean2integer +054: +055: (* +056: A declaration of the entry point function for your program +057: +058: You may assume that when starting this function will behave as if +059: it had been called from the C language main function like this: +060: +061: int main(int argc, char * argv[]) { +062: if (argc == 1) { +063: return entry(NULL); +064: } +065: else { +066: return entry(makeAlphaString(argv[1])); +067: } +068: } +069: +070: for some suitable definition of makeAlphaString which creates +071: an alpha string representation of its argument C string in memory +072: and returns a pointer to that alpha string. +073: *) +074: +075: function entry: string2integer +076: diff --git a/tests/sprint1/expected/sp1_comment_fix1.expected b/tests/sprint1/expected/sp1_comment_fix1.expected index 07d66e1..de45b77 100644 --- a/tests/sprint1/expected/sp1_comment_fix1.expected +++ b/tests/sprint1/expected/sp1_comment_fix1.expected @@ -1 +1 @@ - daskmskdfm \ No newline at end of file +1 1 700 "(***)" diff --git a/tests/sprint1/expected/sp1_comment_fix2.expected b/tests/sprint1/expected/sp1_comment_fix2.expected new file mode 100644 index 0000000..e094e9b --- /dev/null +++ b/tests/sprint1/expected/sp1_comment_fix2.expected @@ -0,0 +1,3 @@ +1 1 700 "(*(**)" +1 7 603 "*" +1 8 502 ")" diff --git a/tests/sprint1/expected/sp1_comment_issues.expected b/tests/sprint1/expected/sp1_comment_issues.expected new file mode 100644 index 0000000..0e3c0b8 --- /dev/null +++ b/tests/sprint1/expected/sp1_comment_issues.expected @@ -0,0 +1,22 @@ +1 1 700 "(*(**)" +1 7 603 "*" +1 8 502 ")" +2 1 700 "(***)" +3 1 700 "(******)" +3 9 700 "(*\kpp*********)" +4 1 501 "(" +4 2 700 "(*((*)" +4 8 502 ")" +5 1 700 "(***)" +5 6 700 "(*) +(* *)" +7 1 700 "(***)" +7 6 502 ")" +7 7 502 ")" +7 8 502 ")" +7 9 502 ")" +7 10 502 ")" +7 11 502 ")" +7 12 603 "*" +7 13 700 "(*))))))))*)" +7 25 502 ")" diff --git a/tests/sprint1/expected/sp1_comments.expected b/tests/sprint1/expected/sp1_comments.expected new file mode 100644 index 0000000..0486ed9 --- /dev/null +++ b/tests/sprint1/expected/sp1_comments.expected @@ -0,0 +1,9 @@ +1 1 700 "(* hello *)" +2 1 700 "(* hello *)" +3 1 700 "(* I'd think this is a legal "string" that contains several \n \t +escaped characters, isn't it? *)" +5 1 700 "(* \ *)" +6 1 700 "(* *)" +7 1 700 "(*{COMMENT}+ *)" +8 1 700 "(* * *)" +9 1 700 "(* (hello) *)" diff --git a/tests/sprint1/expected/sp1_general_token.expected b/tests/sprint1/expected/sp1_general_token.expected new file mode 100644 index 0000000..d50bac7 --- /dev/null +++ b/tests/sprint1/expected/sp1_general_token.expected @@ -0,0 +1,68 @@ +1 1 101 "This" +1 6 101 "is" +1 9 101 "a" +1 11 101 "test" +2 1 301 "9" +2 2 101 "combined" +2 11 301 "7" +2 12 101 "okens" +3 1 301 "12345" +4 1 301 "893247892" +5 1 101 "combined" +5 10 101 "DueToUnknownChar" +5 27 101 "_validtoken" +5 39 101 "__validtoken1" +5 53 101 "_valid_token2" +5 67 101 "validToken3_" +6 1 305 "true" +6 6 306 "false" +7 1 302 "null" +7 6 401 "while" +7 12 609 "!" +7 13 101 "wrong" +7 19 402 "if" +7 22 101 "when" +8 1 404 "else" +8 6 405 "type" +8 11 406 "function" +9 1 407 "return" +9 9 408 "external" +9 25 409 "as" +10 1 101 "string" +10 8 101 "_NOte_that_was_not_reserved" +11 1 501 "(" +11 2 503 "[" +11 3 502 ")" +11 4 504 "]" +11 5 505 "{" +11 6 506 "}" +11 7 508 ":" +11 8 507 ";" +11 9 509 "," +11 10 510 "->" +12 1 601 "+" +12 2 602 "-" +12 3 603 "*" +12 4 604 "/" +12 5 605 "%" +13 1 606 "<" +13 2 607 "=" +14 1 608 ":=" +15 2 101 "This" +15 7 101 "is" +15 10 101 "not" +15 14 101 "a" +15 16 101 "valid" +16 1 101 "String" +17 1 304 ""This is a valid String"" +18 1 609 "!" +18 2 611 "|" +19 1 612 "." +19 2 612 "." +20 1 700 "(* this is a comment *)" +21 1 501 "(" +21 2 603 "*" +21 3 101 "Not" +21 7 101 "a" +21 9 101 "comment" +22 3 610 "&" diff --git a/tests/sprint1/expected/sp1_keywords.expected b/tests/sprint1/expected/sp1_keywords.expected new file mode 100644 index 0000000..9e70321 --- /dev/null +++ b/tests/sprint1/expected/sp1_keywords.expected @@ -0,0 +1,29 @@ +1 1 401 "while" +2 1 101 "While" +3 1 101 "whiLe" +4 1 402 "if" +5 1 101 "IF" +6 1 101 "If" +7 1 101 "iF" +8 1 403 "then" +9 1 101 "Then" +10 1 101 "theN" +11 1 404 "else" +12 1 101 "eLse" +13 1 101 "elSe" +14 1 101 "Else" +15 1 405 "type" +16 1 101 "Type" +17 1 101 "tyPe" +18 1 406 "function" +19 1 101 "Function" +20 1 101 "functioN" +21 1 407 "return" +22 1 101 "Return" +23 1 101 "returN" +24 1 408 "external" +25 1 101 "External" +26 1 101 "exteRnal" +27 1 409 "as" +28 1 101 "As" +29 1 101 "aS" diff --git a/tests/sprint1/expected/sp1_operators.expected b/tests/sprint1/expected/sp1_operators.expected new file mode 100644 index 0000000..dd3eaab --- /dev/null +++ b/tests/sprint1/expected/sp1_operators.expected @@ -0,0 +1,22 @@ +1 1 601 "+" +2 1 602 "-" +3 1 603 "*" +4 1 604 "/" +6 1 605 "%" +7 1 606 "<" +9 1 607 "=" +10 1 608 ":=" +11 1 607 "=" +11 2 508 ":" +12 1 508 ":" +13 1 607 "=" +14 1 609 "!" +15 1 610 "&" +16 1 611 "|" +17 1 612 "." +18 1 101 "relEASE" +19 1 614 "release" +20 1 101 "RELEASE" +21 1 613 "reserve" +22 1 101 "RESERVE" +23 1 101 "reSERVe" diff --git a/tests/sprint1/expected/sp1_other_punc.expected b/tests/sprint1/expected/sp1_other_punc.expected new file mode 100644 index 0000000..7500378 --- /dev/null +++ b/tests/sprint1/expected/sp1_other_punc.expected @@ -0,0 +1,7 @@ +1 1 507 ";" +2 1 508 ":" +3 1 509 "," +4 1 510 "->" +5 1 510 "->" +6 1 602 "-" +6 2 510 "->" diff --git a/tests/sprint1/expected/sp1_punc_grouping.expected b/tests/sprint1/expected/sp1_punc_grouping.expected new file mode 100644 index 0000000..c58a316 --- /dev/null +++ b/tests/sprint1/expected/sp1_punc_grouping.expected @@ -0,0 +1,59 @@ +1 1 502 ")" +2 1 101 "a" +2 2 502 ")" +3 1 502 ")" +3 2 101 "a" +4 1 502 ")" +4 2 603 "*" +5 1 603 "*" +5 2 502 ")" +7 1 700 "(* jellsls + well this seems to work + + + *)" +13 1 501 "(" +14 1 101 "a" +14 2 501 "(" +15 1 501 "(" +15 2 101 "a" +16 1 501 "(" +16 2 603 "*" +17 1 603 "*" +17 2 501 "(" +20 1 505 "{" +21 1 101 "a" +21 2 505 "{" +22 1 505 "{" +22 2 101 "a" +23 1 505 "{" +23 2 603 "*" +24 1 603 "*" +24 2 505 "{" +25 1 506 "}" +26 1 101 "a" +26 2 506 "}" +27 1 506 "}" +27 2 101 "a" +28 1 506 "}" +28 2 603 "*" +29 1 603 "*" +29 2 506 "}" +33 1 503 "[" +34 1 101 "a" +34 2 503 "[" +35 1 503 "[" +35 2 101 "a" +36 1 503 "[" +36 2 603 "*" +37 1 603 "*" +37 2 503 "[" +38 1 504 "]" +39 1 101 "a" +39 2 504 "]" +40 1 504 "]" +40 2 101 "a" +41 1 504 "]" +41 2 603 "*" +42 1 603 "*" +42 2 504 "]" diff --git a/tests/sprint1/expected/sp1_real_alpha_file1.expected b/tests/sprint1/expected/sp1_real_alpha_file1.expected new file mode 100644 index 0000000..cc3f2c9 --- /dev/null +++ b/tests/sprint1/expected/sp1_real_alpha_file1.expected @@ -0,0 +1,145 @@ +1 1 405 "type" +1 6 101 "rec" +1 9 508 ":" +1 11 503 "[" +1 12 201 "integer" +1 19 508 ":" +1 21 101 "x" +1 22 507 ";" +1 24 201 "integer" +1 31 508 ":" +1 33 101 "y" +1 34 504 "]" +2 1 405 "type" +2 6 101 "T1" +2 8 508 ":" +2 10 201 "integer" +2 18 510 "->" +2 21 201 "integer" +3 1 405 "type" +3 6 101 "T2" +3 8 508 ":" +3 10 101 "rec" +3 14 510 "->" +3 17 201 "integer" +4 1 406 "function" +4 10 101 "foo" +4 14 508 ":" +4 16 101 "T1" +5 1 406 "function" +5 10 101 "bar1" +5 15 508 ":" +5 17 101 "T2" +6 1 406 "function" +6 10 101 "bar2" +6 15 508 ":" +6 17 101 "T2" +7 1 101 "foo" +7 4 501 "(" +7 5 101 "x" +7 6 502 ")" +7 8 608 ":=" +7 11 505 "{" +8 2 407 "return" +8 9 101 "x" +8 11 603 "*" +8 13 101 "x" +8 14 507 ";" +9 9 506 "}" +10 1 101 "bar1" +10 5 501 "(" +10 6 101 "a" +10 7 502 ")" +10 9 608 ":=" +10 12 505 "{" +11 9 407 "return" +11 16 101 "a" +11 17 612 "." +11 18 101 "x" +11 20 603 "*" +11 22 101 "a" +11 23 612 "." +11 24 101 "y" +11 25 507 ";" +12 9 506 "}" +13 1 101 "bar2" +13 6 409 "as" +13 9 501 "(" +13 10 101 "r" +13 11 509 "," +13 12 101 "s" +13 13 502 ")" +13 15 608 ":=" +13 18 505 "{" +14 9 407 "return" +14 16 101 "r" +14 18 603 "*" +14 20 101 "s" +14 21 507 ";" +15 9 506 "}" +16 1 101 "entry" +16 6 501 "(" +16 7 101 "arg" +16 10 502 ")" +16 12 608 ":=" +16 15 505 "{" +17 9 503 "[" +17 11 201 "integer" +17 18 508 ":" +17 20 101 "result" +17 27 507 ";" +17 29 101 "rec" +17 32 508 ":" +17 34 101 "w" +17 35 504 "]" +18 9 101 "result" +18 16 608 ":=" +18 19 101 "foo" +18 22 501 "(" +18 23 301 "5" +18 24 502 ")" +18 25 507 ";" +19 9 101 "w" +19 11 608 ":=" +19 14 613 "reserve" +19 21 501 "(" +19 22 101 "w" +19 23 502 ")" +19 24 507 ";" +19 26 700 "(* see types.alpha – reserve returns a value of type address, + which can be assigned to array and record variables + *)" +22 9 101 "w" +22 10 612 "." +22 11 101 "x" +22 13 608 ":=" +22 16 301 "5" +22 17 507 ";" +23 9 101 "w" +23 10 612 "." +23 11 101 "y" +23 13 608 ":=" +23 16 301 "7" +23 17 507 ";" +24 9 101 "result" +24 16 608 ":=" +24 19 101 "bar1" +24 23 501 "(" +24 24 101 "w" +24 25 502 ")" +24 26 507 ";" +24 28 700 "(* pass w (a rec type value) to bar1 *)" +25 9 101 "result" +25 16 608 ":=" +25 19 101 "bar2" +25 23 501 "(" +25 24 301 "5" +25 25 509 "," +25 26 301 "7" +25 27 502 ")" +25 28 507 ";" +25 30 700 "(* implicitly build a rec type value, assign 5 and 7 to fields x and y, but call them r and s *)" +27 9 407 "return" +27 16 301 "0" +27 17 507 ";" +28 1 506 "}" diff --git a/tests/sprint1/expected/sp1_real_alpha_file2.expected b/tests/sprint1/expected/sp1_real_alpha_file2.expected new file mode 100644 index 0000000..90c34a2 --- /dev/null +++ b/tests/sprint1/expected/sp1_real_alpha_file2.expected @@ -0,0 +1,100 @@ +1 1 700 "(* Type definitions *)" +2 1 405 "type" +2 6 101 "string" +2 12 508 ":" +2 14 301 "1" +2 16 510 "->" +2 19 204 "character" +3 1 405 "type" +3 6 101 "int2int" +3 13 508 ":" +3 15 201 "integer" +3 23 510 "->" +3 26 201 "integer" +4 1 405 "type" +4 6 101 "string2int" +4 16 508 ":" +4 18 101 "string" +4 25 510 "->" +4 28 201 "integer" +5 1 700 "(* Function prototypes +They use the above type definitions +*)" +8 1 406 "function" +8 10 101 "square" +8 17 508 ":" +8 19 101 "int2int" +9 1 406 "function" +9 10 101 "entry" +9 16 508 ":" +9 18 101 "string2int" +10 1 700 "(* Function definition +Functions must be declared before they are defined +*)" +13 1 101 "square" +13 7 501 "(" +13 8 101 "x" +13 9 502 ")" +13 11 608 ":=" +13 14 505 "{" +14 1 407 "return" +14 8 101 "x" +14 10 603 "*" +14 12 101 "x" +14 13 507 ";" +15 1 506 "}" +16 1 700 "(* Function definition +entry is the first function called +*)" +19 1 101 "entry" +19 6 501 "(" +19 7 101 "arg" +19 10 502 ")" +19 12 608 ":=" +19 15 505 "{" +20 1 101 "input" +20 7 607 "=" +20 9 301 "7" +20 10 507 ";" +21 1 101 "expected" +21 10 607 "=" +21 12 301 "49" +21 14 507 ";" +22 1 101 "actual" +22 8 608 ":=" +22 11 101 "square" +22 17 501 "(" +22 18 101 "input" +22 23 502 ")" +22 24 507 ";" +23 1 101 "rseult" +23 8 608 ":=" +23 11 101 "expected" +23 20 607 "=" +23 22 101 "actual" +23 28 507 ";" +24 1 407 "return" +24 8 301 "0" +24 9 507 ";" +25 1 503 "[" +25 3 201 "integer" +25 10 508 ":" +25 12 101 "input" +25 17 507 ";" +25 19 201 "integer" +25 26 508 ":" +25 28 101 "expected" +25 36 507 ";" +25 38 201 "integer" +25 45 508 ":" +25 47 101 "actual" +25 53 507 ";" +25 55 101 "boolean" +25 62 508 ":" +25 64 101 "result" +25 70 507 ";" +25 72 101 "string" +25 78 508 ":" +25 80 101 "input" +25 86 504 "]" +26 1 506 "}" diff --git a/tests/sprint1/expected/sp1_simple_int.expected b/tests/sprint1/expected/sp1_simple_int.expected new file mode 100644 index 0000000..0bcbefb --- /dev/null +++ b/tests/sprint1/expected/sp1_simple_int.expected @@ -0,0 +1,8 @@ +1 1 301 "45" +2 1 301 "123" +3 1 301 "8392" +4 1 301 "40" +4 4 301 "40" +5 2 301 "200" +5 6 301 "50" +5 9 301 "21783" diff --git a/tests/sprint1/expected/sp1_simple_literals.expected b/tests/sprint1/expected/sp1_simple_literals.expected new file mode 100644 index 0000000..788adc2 --- /dev/null +++ b/tests/sprint1/expected/sp1_simple_literals.expected @@ -0,0 +1,64 @@ +1 1 304 ""this is a string"" +1 20 301 "721398" +1 27 303 "'g'" +1 32 604 "/" +1 33 101 "n" +1 36 700 "(* should print 3 tokens before this *)" +4 1 301 "12893" +4 8 101 "this" +4 13 101 "is" +4 16 101 "not" +4 20 101 "a" +4 22 101 "string" +4 29 700 "(*one valid token before this*)" +5 1 700 "(* spacey comment here +over multiple lines +will it work? *)" +7 18 306 "false" +11 1 306 "false" +12 1 700 "(**)" +14 1 101 "nullfalse" +15 2 101 "nulltrue" +16 1 302 "null" +17 1 303 "'7'" +18 1 305 "true" +19 2 301 "189" +20 1 303 "'\t'" +21 1 303 "'"'" +22 1 303 "'/'" +23 1 303 "'\n'" +24 1 303 "'\''" +25 1 303 "'\t'" +26 1 303 "'\\'" +27 1 303 "'n'" +29 2 101 "fdsf" +30 1 700 "(*/jnewjno2893u86^ Lots of random characters /n /t '") *)" +35 1 304 ""STRINGwithnotSPaces"" +36 1 303 "' '" +38 1 304 ""J"" +39 1 304 """" +40 1 304 "" "" +42 1 304 ""{SCHAR}"" +43 1 304 ""SCHAR"" +44 1 304 ""[SCHAR]"" +45 1 304 ""FINAL: I'd think this is a legal \"string\" that contains \n \t several escaped characters, isn't it?"" +46 2 101 "I" +46 4 101 "d" +46 6 101 "think" +46 12 101 "this" +46 17 101 "is" +46 20 101 "a" +46 22 101 "legal" +46 30 101 "string" +46 39 101 "that" +46 44 101 "contains" +46 53 101 "several" +46 63 101 "n" +46 66 101 "t" +46 68 101 "escaped" +46 76 101 "characters" +46 86 509 "," +46 88 101 "isn" +46 92 101 "t" +46 94 101 "it" +47 1 101 "nullLike" diff --git a/tests/sprint1/expected/sp1_variables.expected b/tests/sprint1/expected/sp1_variables.expected new file mode 100644 index 0000000..223288a --- /dev/null +++ b/tests/sprint1/expected/sp1_variables.expected @@ -0,0 +1,13 @@ +1 1 101 "valid1" +2 1 101 "Valid2" +3 1 101 "_valid3" +4 1 101 "_valid_name_4" +5 1 101 "VALID" +6 1 301 "0" +6 2 101 "Invalid" +7 1 301 "1" +7 2 101 "invalid" +8 2 101 "invalid" +9 1 101 "invalid" +9 8 607 "=" +10 1 101 "String" diff --git a/tests/sprint2/expected/sp2_carls_mistake.expected b/tests/sprint2/expected/sp2_carls_mistake.expected new file mode 100644 index 0000000..cee5d6f --- /dev/null +++ b/tests/sprint2/expected/sp2_carls_mistake.expected @@ -0,0 +1,35 @@ +NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +bar2 : 001001 : : undefined : Function Definition +bar1 : 001001 : : undefined : Function Definition +foo : 001001 : : undefined : Function Definition +entry : 001001 : : undefined : Function Definition +main : 001001 : : string -> integer : Type of Function +arr : 001001 : : 1 -> integer : Type of Array +T2 : 001001 : : rec -> integer : Type of Function +T1 : 001001 : : integer -> integer : Type of Function +rec : 001001 : : Record Type : elements-2 size-8 bytes +integer : 001001 : : Primitive Type : size-4 bytes +address : 001001 : : Primitive Type : size-8 bytes +character : 001001 : : Primitive Type : size-1 bytes +string : 001001 : : 1 -> character : Type of Array +Boolean : 001001 : : Primitive Type : size-4 bytes +reserve type : 001001 : : integer -> address : Type of Function +reserve : 001001 : : undefined : Function Definition +release type : 001001 : : address -> integer : Type of Function +release : 001001 : : undefined : Function Definition +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +w : 025000 : 001001 : rec : Record Instance +result : 025000 : 001001 : integer : Primitive Instance +arg : 025000 : 001001 : string : Array Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +r : 021000 : 001001 : integer : Primitive Instance +s : 021000 : 001001 : integer : Primitive Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +x : 017000 : 001001 : integer : Primitive Instance +y : 017000 : 001001 : integer : Primitive Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +x : 013000 : 001001 : integer : Primitive Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +y : 001000 : 001001 : integer : Primitive Instance +x : 001000 : 001001 : integer : Primitive Instance diff --git a/tests/sprint2/expected/sp2_function_types.expected b/tests/sprint2/expected/sp2_function_types.expected new file mode 100644 index 0000000..391690b --- /dev/null +++ b/tests/sprint2/expected/sp2_function_types.expected @@ -0,0 +1,29 @@ +NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +entry : 001001 : : undefined : Function Definition +integer2integer2integerFunc : 001001 : : undefined : Function Definition +released : 001001 : : undefined : Function Definition +reserved : 001001 : : undefined : Function Definition +printBoolean : 001001 : : undefined : Function Definition +printCharacter : 001001 : : undefined : Function Definition +printInteger : 001001 : : undefined : Function Definition +integer2integer2integer : 001001 : : integer2integer -> integer : Type of Function +address2integer : 001001 : : address -> integer : Type of Function +integer2address : 001001 : : integer -> address : Type of Function +Boolean2Boolean2Boolean : 001001 : : Boolean2Boolean -> Boolean : Type of Function +character2character2Boolean : 001001 : : undefined -> undefined : Type of Function +integer2integer2Boolean : 001001 : : integer2integer -> Boolean : Type of Function +string2integer : 001001 : : string -> integer : Type of Function +Boolean2integer : 001001 : : Boolean -> integer : Type of Function +character2integer : 001001 : : character -> integer : Type of Function +integer2integer : 001001 : : integer -> integer : Type of Function +Boolean2Boolean : 001001 : : Boolean -> Boolean : Type of Function +integer : 001001 : : Primitive Type : size-4 bytes +address : 001001 : : Primitive Type : size-8 bytes +character : 001001 : : Primitive Type : size-1 bytes +string : 001001 : : 1 -> character : Type of Array +Boolean : 001001 : : Primitive Type : size-4 bytes +reserve type : 001001 : : integer -> address : Type of Function +reserve : 001001 : : undefined : Function Definition +release type : 001001 : : address -> integer : Type of Function +release : 001001 : : undefined : Function Definition diff --git a/tests/sprint2/expected/sp2_integer_binary_op.expected b/tests/sprint2/expected/sp2_integer_binary_op.expected new file mode 100644 index 0000000..d24c170 --- /dev/null +++ b/tests/sprint2/expected/sp2_integer_binary_op.expected @@ -0,0 +1,21 @@ +NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +testarr : 001001 : : 1 -> integer : Type of Array +entry : 001001 : : undefined : Function Definition +main : 001001 : : string -> integer : Type of Function +integer : 001001 : : Primitive Type : size-4 bytes +address : 001001 : : Primitive Type : size-8 bytes +character : 001001 : : Primitive Type : size-1 bytes +string : 001001 : : 1 -> character : Type of Array +Boolean : 001001 : : Primitive Type : size-4 bytes +reserve type : 001001 : : integer -> address : Type of Function +reserve : 001001 : : undefined : Function Definition +release type : 001001 : : address -> integer : Type of Function +release : 001001 : : undefined : Function Definition +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +b1 : 005000 : 001001 : Boolean : Primitive Instance +b2 : 005000 : 001001 : Boolean : Primitive Instance +arr2 : 005000 : 001001 : testarr : Array Instance +arr : 005000 : 001001 : testarr : Array Instance +x : 005000 : 001001 : integer : Primitive Instance +arg : 005000 : 001001 : string : Array Instance diff --git a/tests/sprint2/expected/sp2_invalid_multiple_params_no_as.expected b/tests/sprint2/expected/sp2_invalid_multiple_params_no_as.expected new file mode 100644 index 0000000..509c6eb --- /dev/null +++ b/tests/sprint2/expected/sp2_invalid_multiple_params_no_as.expected @@ -0,0 +1,20 @@ +NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +test : 001001 : : undefined : Function Definition +main : 001001 : : rec -> integer : Type of Function +rec : 001001 : : Record Type : elements-2 size-8 bytes +integer : 001001 : : Primitive Type : size-4 bytes +address : 001001 : : Primitive Type : size-8 bytes +character : 001001 : : Primitive Type : size-1 bytes +string : 001001 : : 1 -> character : Type of Array +Boolean : 001001 : : Primitive Type : size-4 bytes +reserve type : 001001 : : integer -> address : Type of Function +reserve : 001001 : : undefined : Function Definition +release type : 001001 : : address -> integer : Type of Function +release : 001001 : : undefined : Function Definition +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +arg : 005000 : 001001 : integer : Primitive Instance +arg2 : 005000 : 001001 : integer : Primitive Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +y : 001000 : 001001 : integer : Primitive Instance +x : 001000 : 001001 : integer : Primitive Instance diff --git a/tests/sprint2/expected/sp2_invalid_recop.expected b/tests/sprint2/expected/sp2_invalid_recop.expected new file mode 100644 index 0000000..642ad85 --- /dev/null +++ b/tests/sprint2/expected/sp2_invalid_recop.expected @@ -0,0 +1,20 @@ +NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +rec : 001001 : : Record Type : elements-2 size-8 bytes +entry : 001001 : : undefined : Function Definition +main : 001001 : : string -> integer : Type of Function +integer : 001001 : : Primitive Type : size-4 bytes +address : 001001 : : Primitive Type : size-8 bytes +character : 001001 : : Primitive Type : size-1 bytes +string : 001001 : : 1 -> character : Type of Array +Boolean : 001001 : : Primitive Type : size-4 bytes +reserve type : 001001 : : integer -> address : Type of Function +reserve : 001001 : : undefined : Function Definition +release type : 001001 : : address -> integer : Type of Function +release : 001001 : : undefined : Function Definition +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +w : 006000 : 001001 : rec : Record Instance +arg : 006000 : 001001 : string : Array Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +y : 004000 : 001001 : integer : Primitive Instance +x : 004000 : 001001 : integer : Primitive Instance diff --git a/tests/sprint2/expected/sp2_invalid_release.expected b/tests/sprint2/expected/sp2_invalid_release.expected new file mode 100644 index 0000000..1ac0274 --- /dev/null +++ b/tests/sprint2/expected/sp2_invalid_release.expected @@ -0,0 +1,17 @@ +NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +rec : 001001 : : Record Type : elements-2 size-8 bytes +integer : 001001 : : Primitive Type : size-4 bytes +address : 001001 : : Primitive Type : size-8 bytes +character : 001001 : : Primitive Type : size-1 bytes +string : 001001 : : 1 -> character : Type of Array +Boolean : 001001 : : Primitive Type : size-4 bytes +reserve type : 001001 : : integer -> address : Type of Function +reserve : 001001 : : undefined : Function Definition +release type : 001001 : : address -> integer : Type of Function +release : 001001 : : undefined : Function Definition +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +w : 003000 : 001001 : rec : Record Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +y : 001000 : 001001 : integer : Primitive Instance +x : 001000 : 001001 : integer : Primitive Instance diff --git a/tests/sprint2/expected/sp2_library.expected b/tests/sprint2/expected/sp2_library.expected new file mode 100644 index 0000000..80a9611 --- /dev/null +++ b/tests/sprint2/expected/sp2_library.expected @@ -0,0 +1,39 @@ +NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +entry : 001001 : : undefined : Function Definition +printBoolean : 001001 : : undefined : Function Definition +printCharacter : 001001 : : undefined : Function Definition +printInteger : 001001 : : undefined : Function Definition +address2integer : 001001 : : address -> integer : Type of Function +integer2address : 001001 : : integer -> address : Type of Function +BooleanXBoolean2Boolean : 001001 : : BooleanXBoolean -> Boolean : Type of Function +characterXcharacter2Boolean : 001001 : : characterXcharacter -> Boolean : Type of Function +integerXinteger2Boolean : 001001 : : integerXinteger -> Boolean : Type of Function +integerXinteger2integer : 001001 : : integerXinteger -> integer : Type of Function +string2integer : 001001 : : string -> integer : Type of Function +Boolean2integer : 001001 : : Boolean -> integer : Type of Function +character2integer : 001001 : : character -> integer : Type of Function +integer2integer : 001001 : : integer -> integer : Type of Function +Boolean2Boolean : 001001 : : Boolean -> Boolean : Type of Function +integerXinteger : 001001 : : Record Type : elements-2 size-8 bytes +characterXcharacter : 001001 : : Record Type : elements-2 size-2 bytes +BooleanXBoolean : 001001 : : Record Type : elements-2 size-8 bytes +string : 001001 : : 1 -> character : Type of Array +integer : 001001 : : Primitive Type : size-4 bytes +address : 001001 : : Primitive Type : size-8 bytes +character : 001001 : : Primitive Type : size-1 bytes +string : 001001 : : 1 -> character : Type of Array +Boolean : 001001 : : Primitive Type : size-4 bytes +reserve type : 001001 : : integer -> address : Type of Function +reserve : 001001 : : undefined : Function Definition +release type : 001001 : : address -> integer : Type of Function +release : 001001 : : undefined : Function Definition +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +y : 015000 : 001001 : integer : Primitive Instance +x : 015000 : 001001 : integer : Primitive Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +y : 014000 : 001001 : character : Primitive Instance +x : 014000 : 001001 : character : Primitive Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +y : 013000 : 001001 : Boolean : Primitive Instance +x : 013000 : 001001 : Boolean : Primitive Instance diff --git a/tests/sprint2/expected/sp2_llnode.expected b/tests/sprint2/expected/sp2_llnode.expected new file mode 100644 index 0000000..ab13e6f --- /dev/null +++ b/tests/sprint2/expected/sp2_llnode.expected @@ -0,0 +1,66 @@ +NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +make_list : 001001 : : undefined : Function Definition +bar2 : 001001 : : undefined : Function Definition +bar1 : 001001 : : undefined : Function Definition +foo : 001001 : : undefined : Function Definition +list : 001001 : : integer -> llnode : Type of Function +llnode : 001001 : : Record Type : elements-3 size-24 bytes +T2 : 001001 : : rec -> integer : Type of Function +T1 : 001001 : : integer -> integer : Type of Function +rec : 001001 : : Record Type : elements-2 size-8 bytes +entry : 001001 : : undefined : Function Definition +main : 001001 : : string -> integer : Type of Function +integer : 001001 : : Primitive Type : size-4 bytes +address : 001001 : : Primitive Type : size-8 bytes +character : 001001 : : Primitive Type : size-1 bytes +string : 001001 : : 1 -> character : Type of Array +Boolean : 001001 : : Primitive Type : size-4 bytes +reserve type : 001001 : : integer -> address : Type of Function +reserve : 001001 : : undefined : Function Definition +release type : 001001 : : address -> integer : Type of Function +release : 001001 : : undefined : Function Definition +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +li : 069000 : 001001 : llnode : Record Instance +w : 069000 : 001001 : rec : Record Instance +result : 069000 : 001001 : integer : Primitive Instance +arg : 069000 : 001001 : string : Array Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +r : 054000 : 001001 : integer : Primitive Instance +s : 054000 : 001001 : integer : Primitive Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +x : 059012 : 054000 : integer : Primitive Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: + : 062028 : 059012 : : Empty Scope +------------------------------:--------:--------:-----------------------------------:-----------------------------------: + : 055021 : 054000 : : Empty Scope +------------------------------:--------:--------:-----------------------------------:-----------------------------------: + : 056026 : 055021 : : Empty Scope +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +a : 050000 : 001001 : integer : Primitive Instance +b : 050000 : 001001 : integer : Primitive Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +x : 046000 : 001001 : integer : Primitive Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +temp : 016000 : 001001 : address : Primitive Instance +curr : 016000 : 001001 : address : Primitive Instance +ret : 016000 : 001001 : address : Primitive Instance +orig_a : 016000 : 001001 : integer : Primitive Instance +a : 016000 : 001001 : integer : Primitive Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: + : 021012 : 016000 : : Empty Scope +------------------------------:--------:--------:-----------------------------------:-----------------------------------: + : 026023 : 021012 : : Empty Scope +------------------------------:--------:--------:-----------------------------------:-----------------------------------: + : 035020 : 026023 : : Empty Scope +------------------------------:--------:--------:-----------------------------------:-----------------------------------: + : 031034 : 026023 : : Empty Scope +------------------------------:--------:--------:-----------------------------------:-----------------------------------: + : 019029 : 016000 : : Empty Scope +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +next : 008000 : 001001 : llnode : Record Instance +val : 008000 : 001001 : integer : Primitive Instance +prev : 008000 : 001001 : llnode : Record Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +y : 004000 : 001001 : integer : Primitive Instance +x : 004000 : 001001 : integer : Primitive Instance diff --git a/tests/sprint2/expected/sp2_one_line.expected b/tests/sprint2/expected/sp2_one_line.expected new file mode 100644 index 0000000..dcdd20a --- /dev/null +++ b/tests/sprint2/expected/sp2_one_line.expected @@ -0,0 +1,29 @@ +NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +bar2 : 001001 : : undefined : Function Definition +bar1 : 001001 : : undefined : Function Definition +foo : 001001 : : undefined : Function Definition +T2 : 001001 : : rec -> integer : Type of Function +T1 : 001001 : : integer -> integer : Type of Function +rec : 001001 : : Record Type : elements-2 size-8 bytes +entry : 001001 : : undefined : Function Definition +main : 001001 : : string -> integer : Type of Function +integer : 001001 : : Primitive Type : size-4 bytes +address : 001001 : : Primitive Type : size-8 bytes +character : 001001 : : Primitive Type : size-1 bytes +string : 001001 : : 1 -> character : Type of Array +Boolean : 001001 : : Primitive Type : size-4 bytes +reserve type : 001001 : : integer -> address : Type of Function +reserve : 001001 : : undefined : Function Definition +release type : 001001 : : address -> integer : Type of Function +release : 001001 : : undefined : Function Definition +------------------------------:--------:--------:-----------------------------------:-----------------------------------: + : 000000 : 001001 : : Empty Scope +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +a : 001000 : 001001 : integer : Primitive Instance +undefined : 001000 : 001001 : integer : Primitive Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +x : 001000 : 001001 : integer : Primitive Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +y : 001000 : 001001 : integer : Primitive Instance +x : 001000 : 001001 : integer : Primitive Instance diff --git a/tests/sprint2/expected/sp2_presidence.expected b/tests/sprint2/expected/sp2_presidence.expected new file mode 100644 index 0000000..80d2312 --- /dev/null +++ b/tests/sprint2/expected/sp2_presidence.expected @@ -0,0 +1,23 @@ +NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +entry : 001001 : : undefined : Function Definition +rec : 001001 : : Record Type : elements-2 size-8 bytes +main : 001001 : : string -> integer : Type of Function +integer : 001001 : : Primitive Type : size-4 bytes +address : 001001 : : Primitive Type : size-8 bytes +character : 001001 : : Primitive Type : size-1 bytes +string : 001001 : : 1 -> character : Type of Array +Boolean : 001001 : : Primitive Type : size-4 bytes +reserve type : 001001 : : integer -> address : Type of Function +reserve : 001001 : : undefined : Function Definition +release type : 001001 : : address -> integer : Type of Function +release : 001001 : : undefined : Function Definition +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +arg_bool : 006000 : 001001 : Boolean : Primitive Instance +arg_record : 006000 : 001001 : rec : Record Instance +arg_y : 006000 : 001001 : integer : Primitive Instance +arg_x : 006000 : 001001 : integer : Primitive Instance +arg : 006000 : 001001 : string : Array Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +rec_y : 002000 : 001001 : integer : Primitive Instance +rec_x : 002000 : 001001 : integer : Primitive Instance diff --git a/tests/sprint2/expected/sp2_simple.expected b/tests/sprint2/expected/sp2_simple.expected new file mode 100644 index 0000000..649bea7 --- /dev/null +++ b/tests/sprint2/expected/sp2_simple.expected @@ -0,0 +1,16 @@ +NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +entry : 001001 : : undefined : Function Definition +main : 001001 : : string -> integer : Type of Function +integer : 001001 : : Primitive Type : size-4 bytes +address : 001001 : : Primitive Type : size-8 bytes +character : 001001 : : Primitive Type : size-1 bytes +string : 001001 : : 1 -> character : Type of Array +Boolean : 001001 : : Primitive Type : size-4 bytes +reserve type : 001001 : : integer -> address : Type of Function +reserve : 001001 : : undefined : Function Definition +release type : 001001 : : address -> integer : Type of Function +release : 001001 : : undefined : Function Definition +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +x : 004000 : 001001 : integer : Primitive Instance +arg : 004000 : 001001 : string : Array Instance diff --git a/tests/sprint2/expected/sp2_sp2_arrayargs.expected b/tests/sprint2/expected/sp2_sp2_arrayargs.expected new file mode 100644 index 0000000..0db9d5a --- /dev/null +++ b/tests/sprint2/expected/sp2_sp2_arrayargs.expected @@ -0,0 +1,17 @@ +NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +a_of_s : 001001 : : 1 -> string : Type of Array +string : 001001 : : 1 -> character : Type of Array +integer : 001001 : : Primitive Type : size-4 bytes +address : 001001 : : Primitive Type : size-8 bytes +character : 001001 : : Primitive Type : size-1 bytes +string : 001001 : : 1 -> character : Type of Array +Boolean : 001001 : : Primitive Type : size-4 bytes +reserve type : 001001 : : integer -> address : Type of Function +reserve : 001001 : : undefined : Function Definition +release type : 001001 : : address -> integer : Type of Function +release : 001001 : : undefined : Function Definition +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +many_names : 006000 : 001001 : a_of_s : Array Instance +another_name : 006000 : 001001 : string : Array Instance +one_name : 006000 : 001001 : string : Array Instance diff --git a/tests/sprint2/expected/sp2_valid_assignable_and_mem.expected b/tests/sprint2/expected/sp2_valid_assignable_and_mem.expected new file mode 100644 index 0000000..aa4b733 --- /dev/null +++ b/tests/sprint2/expected/sp2_valid_assignable_and_mem.expected @@ -0,0 +1,21 @@ +NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +T2 : 001001 : : rec -> integer : Type of Function +rec : 001001 : : Record Type : elements-2 size-8 bytes +entry : 001001 : : undefined : Function Definition +main : 001001 : : string -> integer : Type of Function +integer : 001001 : : Primitive Type : size-4 bytes +address : 001001 : : Primitive Type : size-8 bytes +character : 001001 : : Primitive Type : size-1 bytes +string : 001001 : : 1 -> character : Type of Array +Boolean : 001001 : : Primitive Type : size-4 bytes +reserve type : 001001 : : integer -> address : Type of Function +reserve : 001001 : : undefined : Function Definition +release type : 001001 : : address -> integer : Type of Function +release : 001001 : : undefined : Function Definition +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +w : 007000 : 001001 : rec : Record Instance +arg : 007000 : 001001 : string : Array Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +y : 004000 : 001001 : integer : Primitive Instance +x : 004000 : 001001 : integer : Primitive Instance diff --git a/tests/sprint2/other/calc.h b/tests/sprint2/other/calc.h deleted file mode 100644 index 2580e93..0000000 --- a/tests/sprint2/other/calc.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Function type. */ -typedef double (func_t) (double); -/* Data type for links in the chain of symbols. */ -struct symrec -{ - char *name; /* name of symbol */ - int type; /* type of symbol: either VAR or FUN */ - union - { - double var; /* value of a VAR */ - func_t *fun; /* value of a FUN */ - } value; - struct symrec *next; /* link field */ -}; -typedef struct symrec symrec; - -/* The symbol table: a chain of 'struct symrec'. */ -extern symrec *sym_table; - -symrec *putsym (char const *name, int sym_type); -symrec *getsym (char const *name); -struct init -{ - char const *name; - func_t *fun; -}; -struct init const funs[] = -{ - { "atan", atan }, - { "cos", cos }, - { "exp", exp }, - { "ln", log }, - { "sin", sin }, - { "sqrt", sqrt }, - { 0, 0 }, -}; -/* The symbol table: a chain of 'struct symrec'. */ -symrec *sym_table; -/* Put functions in table. */ -static void -init_table (void) -{ - for (int i = 0; funs[i].name; i++) - { - symrec *ptr = putsym (funs[i].name, FUN); - ptr->value.fun = funs[i].fun; - } -} diff --git a/tests/sprint2/other/test.c b/tests/sprint2/other/test.c deleted file mode 100644 index 0d9b343..0000000 --- a/tests/sprint2/other/test.c +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include -#include "symbol_table.h" - -int main(void){ - char *prim = strdup("primitive"); - char *inte = strdup("integer"); - SymbolTable * parant = CreateScope(NULL, 1,1); - char *boole = strdup("Boolean"); - char *chare = strdup("character"); - char *str = strdup("string"); - char *arg = strdup("arg"); - char *one_to_char = strdup("1 -> character"); - char *int_to_int = strdup("integer -> integer"); - char *int2int = strdup("int2int"); - char *str_to_int = strdup("string -> integer"); - char *str2int = strdup("string2int"); - char *square = strdup("square"); - char *string2int = strdup("string2int"); - char *entry = strdup("entry"); - char *x = strdup("x"); - char *input = strdup("input"); - char *expected = strdup("expected"); - char *actual = strdup("actual"); - char *$_und_type = strdup("$_undefined_type"); - char *result = strdup("result"); - char *BOO = strdup("BOO"); - char *YAZOO = strdup("YAZOO"); - - CreateEntry(parant, prim, boole); - CreateEntry(parant, prim, chare); - CreateEntry(parant, prim, inte); - CreateEntry(parant, one_to_char, str); - CreateEntry(parant, int_to_int, int2int); - CreateEntry(parant, str_to_int, str2int); - CreateEntry(parant, int2int, square); - CreateEntry(parant, string2int, entry); - SymbolTable * child = CreateScope(parant, 14,14); - CreateEntry(child, inte, x); - SymbolTable * second = CreateScope(parant, 21,15); - CreateEntry(second, str, arg); - CreateEntry(second, inte, input); - CreateEntry(second, inte, expected); - CreateEntry(second, inte, actual); - CreateEntry(second, $_und_type, result); - SymbolTable * third = CreateScope(second, 33,44); - CreateEntry(third, BOO, arg); - CreateEntry(third, YAZOO, input); - - TableNode *ret = table_lookup(third, "arg"); - printf("%s == %s\n", ret->theName, "arg"); - - ret = table_lookup(third, "hello"); - printf("This should be nil %p != %s\n", ret, "BOO"); - - ret = look_up(second, "input"); - printf("%s == %s\n", ret->theName, "input"); - - ret = look_up(second, "square"); - printf("%s == %s\n", ret->theName, "square"); - - ret = look_up(second, "spuare"); - printf("This should be nil %p == %s\n", ret, "square"); - - print_symbol_table(parant, stderr); - free(inte); - free(boole); - free(prim); - free(str); - free(chare); - free(arg); - return 0; -} - diff --git a/tests/sprint2/other/testGrammar.y b/tests/sprint2/other/testGrammar.y deleted file mode 100644 index 04f8f17..0000000 --- a/tests/sprint2/other/testGrammar.y +++ /dev/null @@ -1,41 +0,0 @@ -%{ - #include /* For printf, etc. */ - #include /* For pow, used in the grammar. */ - #include "calc.h" /* Contains definition of 'symrec'. */ - int yylex (void); - void yyerror (char const *); -%} -%define api.value.type union /* Generate YYSTYPE from these types: */ -%token NUM /* Double precision number. */ -%token VAR FUN /* Symbol table pointer: variable/function. */ -%nterm exp -%precedence '=' -%left '-' '+' -%left '*' '/' -%precedence NEG /* negation--unary minus */ -%right '^' /* exponentiation */ -%% /* The grammar follows. */ -input: - %empty -| input line -; -line: - '\n' -| exp '\n' { printf ("%.10g\n", $1); } -| error '\n' { yyerrok; } -; -exp: - NUM -| VAR { $$ = $1->value.var; } -| VAR '=' exp { $$ = $3; $1->value.var = $3; } -| FUN '(' exp ')' { $$ = $1->value.fun ($3); } -| exp '+' exp { $$ = $1 + $3; } -| exp '-' exp { $$ = $1 - $3; } -| exp '*' exp { $$ = $1 * $3; } -| exp '/' exp { $$ = $1 / $3; } -| '-' exp %prec NEG { $$ = -$2; } -| exp '^' exp { $$ = pow ($1, $3); } -| '(' exp ')' { $$ = $2; } -; -/* End of grammar. */ -%% diff --git a/tests/sprint2/test/sp2_carls_mistake.alpha b/tests/sprint2/test/sp2_carls_mistake.alpha new file mode 100644 index 0000000..b7fa8ee --- /dev/null +++ b/tests/sprint2/test/sp2_carls_mistake.alpha @@ -0,0 +1,35 @@ +type rec: [integer: x; integer: y] + +type T1: integer -> integer +type T2: rec -> integer +type arr: 1 -> integer + +type main: string -> integer +function entry: main +function foo: T1 +function bar1: T2 +function bar2: T2 + +foo (x) := { + return x * x; +} + +bar1 (x, y) := { + return x * y; +} + +bar2 (r,s) := { + return r * s; +} + +entry (arg) := { + [ integer: result ; rec: w] + result := foo(5); + w := reserve w; (* see types.alpha – reserve returns a value of type address, which can be assigned to array and record variables*) + w.x := 5; + w.y := 7; + ressult := bar1(w); (* pass w (a rec type value) to bar1 *) + result := bar2(5,7); (* implicitly build a rec type value, assign 5 and 7 to fields x and y, but call them r and s *) + return 0; +} + diff --git a/tests/sprint2/test/sp2_function_types.alpha b/tests/sprint2/test/sp2_function_types.alpha new file mode 100644 index 0000000..62711c3 --- /dev/null +++ b/tests/sprint2/test/sp2_function_types.alpha @@ -0,0 +1,21 @@ +type Boolean2Boolean: Boolean -> Boolean +type integer2integer: integer -> integer +type character2integer: character -> integer +type Boolean2integer: Boolean -> integer +type string2integer: string -> integer + +type integer2integer2Boolean: integer2integer -> Boolean +type character2character2Boolean: character2character -> Boolean +type Boolean2Boolean2Boolean: Boolean2Boolean -> Boolean +type integer2address: integer -> address +type address2integer: address -> integer +type integer2integer2integer: integer2integer -> integer + +external function printInteger: integer2integer +external function printCharacter: character2integer +external function printBoolean: Boolean2integer +external function reserved: integer2address +external function released: address2integer + +function integer2integer2integerFunc: integer2integer2integer +function entry: string2integer \ No newline at end of file diff --git a/tests/sprint2/test/sp2_integer_binary_op.alpha b/tests/sprint2/test/sp2_integer_binary_op.alpha index 39e00a6..2dfeb73 100644 --- a/tests/sprint2/test/sp2_integer_binary_op.alpha +++ b/tests/sprint2/test/sp2_integer_binary_op.alpha @@ -1,12 +1,18 @@ -entry(arg) := { - [integer:x; address: arr; address: arr2; Boolean : b2; Boolean : b1] - x := 3 + 2 * 8; - x := 3 - 2 / 8; - x := 3 * 2 % 8; - x := 3 * 2 % 8; - x := 3 % 2 * 8; - x := 3 + 2 - 8; - arr2 := 1 * reserve x; +type main: string -> integer +function entry: main +type testarr : 1 -> integer + +entry (arg) := { + [integer:x; testarr: arr; testarr: arr2; Boolean : b2; Boolean : b1] + + x := 3 + 2 * 8; + x := 3 - 2 / 8; + x := 3 * 2 % 8; + x := 3 * 2 % 8; + x := 3 % 2 * 8; + x := 3 + 2 - 8; + + arr2 := 1 * reserve x; arr2 := release x; b2 := 3 < 2; b1 := 1 = 2; diff --git a/tests/sprint2/test/sp2_invalid_multiple_params_no_as.alpha b/tests/sprint2/test/sp2_invalid_multiple_params_no_as.alpha new file mode 100644 index 0000000..805fb6e --- /dev/null +++ b/tests/sprint2/test/sp2_invalid_multiple_params_no_as.alpha @@ -0,0 +1,7 @@ +type rec: [integer: x; integer: y] +type main: rec -> integer +function test: main + +test (arg, arg2) := { + return 0; +} \ No newline at end of file diff --git a/tests/sprint2/test/sp2_invalid_recop.alpha b/tests/sprint2/test/sp2_invalid_recop.alpha new file mode 100644 index 0000000..41b3a55 --- /dev/null +++ b/tests/sprint2/test/sp2_invalid_recop.alpha @@ -0,0 +1,13 @@ +type main: string -> integer +function entry: main + +type rec: [integer: x; integer: y] + +entry (arg) := { + [rec: w] + w := reserve w; + w.x := 1; + w.y := 2; + w.z := 3; + return 0; +} \ No newline at end of file diff --git a/tests/sprint2/test/sp2_invalid_release.alpha b/tests/sprint2/test/sp2_invalid_release.alpha new file mode 100644 index 0000000..2bd645a --- /dev/null +++ b/tests/sprint2/test/sp2_invalid_release.alpha @@ -0,0 +1,8 @@ +type rec: [integer: x; integer: y] + +entry (arg) := { + [rec: w] + w := reserve w; + w := release (w); + return 0; +} \ No newline at end of file diff --git a/tests/sprint2/test/sp2_library.alpha b/tests/sprint2/test/sp2_library.alpha index 9bacd6c..82120be 100644 --- a/tests/sprint2/test/sp2_library.alpha +++ b/tests/sprint2/test/sp2_library.alpha @@ -1,15 +1,18 @@ -(* At compiler start-up your program should create symbol table entries for the four primitive types: - Boolean (1 byte) - character (1 byte) - integer (4 bytes) - address (8 bytes) -You should #include this file at the start of your alpha file. -Some useful types are defined below. +(* + At compiler start-up your program should create symbol table entries for the four primitive types: + Boolean (1 byte) + character (1 byte) + integer (4 bytes) + address (8 bytes) + + should #include this file at the start of your alpha file. + Some useful types are defined below. *) + type string: 1 -> character -type BooleanXBoolean: [Boolean: x, y] -type characterXcharacter: [character: x, y] -type integerXinteger: [integer: x, y] +type BooleanXBoolean: [Boolean: x; Boolean: y] +type characterXcharacter: [character: x; character: y] +type integerXinteger: [integer: x; integer: y] type Boolean2Boolean: Boolean -> Boolean type integer2integer: integer -> integer @@ -22,9 +25,9 @@ type characterXcharacter2Boolean: characterXcharacter -> Boolean type BooleanXBoolean2Boolean: BooleanXBoolean -> Boolean type integer2address: integer -> address type address2integer: address -> integer + external function printInteger: integer2integer external function printCharacter: character2integer external function printBoolean: Boolean2integer -external function reserve: integer2address -external function release: address2integer + function entry: string2integer diff --git a/tests/sprint2/test/sp2_llnode.alpha b/tests/sprint2/test/sp2_llnode.alpha index 6b4912e..3ecfb11 100644 --- a/tests/sprint2/test/sp2_llnode.alpha +++ b/tests/sprint2/test/sp2_llnode.alpha @@ -1,3 +1,6 @@ +type main: string -> integer +function entry: main + type rec: [integer: x; integer: y] type T1: integer -> integer type T2: rec -> integer @@ -9,66 +12,69 @@ function foo : T1 function bar1 : T2 function bar2 : T2 function make_list : list -make_list(a) := { - [integer:orig_a; address: ret; address: curr; address: temp] - if (a < 0 | a = 0) then { - return null; - } else { - ret := reserve llnode; - ret.prev := null; - ret.next := null; - ret.val := a; - while (0 < a) { - temp := reserve llnode; - temp.prev := null; - temp.next := null; - temp.val := val; - if (a = orig_a) then { - ret.next := temp; - temp.prev := ret; - curr := temp; - } else { - curr.next := temp; - temp.prev := curr; - curr := temp; - } - a := a - 1; - } - return ret; + +make_list (a) := { + [integer:orig_a; llnode: ret; llnode: curr; llnode: temp] + + if (a < 0 | a = 0) then { + return null; + } else { + ret := reserve ret; + ret.prev := null; + ret.next := null; + ret.val := a; + while (0 < a) { + temp := reserve temp; + temp.prev := null; + temp.next := null; + temp.val := ret.val; + if (a = orig_a) then { + ret.next := temp; + temp.prev := ret; + curr := temp; + } else { + curr.next := temp; + temp.prev := curr; + curr := temp; + } + a := a - 1; } + return ret; + } } - -foo(x) := { - return x * x; - } -bar1(a) := { - return a.x * a.y; - } - -bar2 as (r,s) := { - if (r < s) then { - while (!(r < s)) { - r := r + 1; - } - } else { - [integer: x] - x := 0; - while (x < 10) { - r := r + s; - } - } - return r * s; - } -entry(arg) := { - [ integer: result ; rec: w; llnode: li] - li := make_list(6); - result := foo(5); - w := reserve w; - w.x := 5; - w.y := 7; - result := bar1(w); - result := bar2(5,7); - - return 0; +foo (x) := { + return x * x; } + +bar1(a,b) := { + return a * b; +} + +bar2(r,s) := { + if (r < s) then { + while (!(r < s)) { + r := r + 1; + } + } else { + [integer: x] + x := 0; + while (x < 10) { + r := r + s; + } + } + return r * s; +} + +entry (arg) := { + [ integer: result ; rec: w; llnode: li] + li := make_list(6); + result := foo(5); + w := reserve w; + w.x := 5; + w.y := 7; + result := bar1(w); + result := bar2(5,7); + + return 0; +} \ No newline at end of file diff --git a/tests/sprint2/test/sp2_one_line.alpha b/tests/sprint2/test/sp2_one_line.alpha index 9031b5f..f1062e9 100644 --- a/tests/sprint2/test/sp2_one_line.alpha +++ b/tests/sprint2/test/sp2_one_line.alpha @@ -1 +1 @@ -type rec: [integer: x; integer: y] type T1: integer -> integer type T2: rec -> integer function foo : T1 function bar1 : T2 function bar2 : T2 foo(x) := { return x * x; } bar1(a) := { return a.x * a.y; } bar2 as (r,s) := { return r * s; } entry(arg) := { [ integer: result ; rec: w] result := foo(5); w := reserve w; w.x := 5; w.y := 7; result := bar1(w); result := bar2(5,7); return 0; } +type main: string -> integer function entry: main type rec: [integer: x; integer: y] type T1: integer -> integer type T2: rec -> integer function foo : T1 function bar1 : T2 function bar2 : T2 foo(x) := { return x * x; } bar1(a) := { return a.x * a.y; } bar2 as (r,s) := { return r * s; } entry(arg) := { [ integer: result ; rec: w] result := foo(5); w := reserve w; w.x := 5; w.y := 7; result := bar1(w); result := bar2(5,7); return 0; } diff --git a/tests/sprint2/test/sp2_presidence.alpha b/tests/sprint2/test/sp2_presidence.alpha index 9b2ef86..d60611d 100644 --- a/tests/sprint2/test/sp2_presidence.alpha +++ b/tests/sprint2/test/sp2_presidence.alpha @@ -1,4 +1,10 @@ -entry(arg) := { - [integer:x] - x := 3 + 2 * 8; +type main: string -> integer +type rec: [integer: rec_x; integer: rec_y] + +function entry: main + +entry (arg) := { + [integer: arg_x; integer: arg_y; rec: arg_record; Boolean: arg_bool] + arg_x := 3 + 2 * 8; + return 0; } diff --git a/tests/sprint2/test/sp2_simple.alpha b/tests/sprint2/test/sp2_simple.alpha index 0b214c3..4042a5a 100644 --- a/tests/sprint2/test/sp2_simple.alpha +++ b/tests/sprint2/test/sp2_simple.alpha @@ -1,5 +1,7 @@ +type main: string -> integer +function entry: main entry(arg) := { - [int : x] - return 0; -} + [integer : x] + return 2; +} \ No newline at end of file diff --git a/tests/sprint2/test/sp2_sp2_arrayargs.alpha b/tests/sprint2/test/sp2_sp2_arrayargs.alpha new file mode 100644 index 0000000..dfb0332 --- /dev/null +++ b/tests/sprint2/test/sp2_sp2_arrayargs.alpha @@ -0,0 +1,16 @@ +type string: 1 -> character +type a_of_s: 1 -> string + +(* maybe some other type definitions *) + +entry(arg) := { + [ string: one_name; string: another_name; a_of_s: many_names ] + another_name := reserve another_name(4); (* reserve space for an an array of character, with 4 members *) + many_names := reserve a_of_s(many_names); + many_names(0) := one_name; + many_names(1) := another_name; + many_names(2) := reserve a_of_s(2)(6); (* reserve space for an item of the same type as a_of_s(2), an array of character, with 6 members *) + many_names(2)(0) := "P"; + + return 0; +} \ No newline at end of file diff --git a/tests/sprint2/test/sp2_sp2_arrayargs.alpha~ b/tests/sprint2/test/sp2_sp2_arrayargs.alpha~ new file mode 100644 index 0000000..ce1673d --- /dev/null +++ b/tests/sprint2/test/sp2_sp2_arrayargs.alpha~ @@ -0,0 +1,16 @@ +type string: 1 -> character +type a_of_s: 1 -> string + +(* maybe some other type definitions *) + +entry(arg) := { + [ string: one_name; string: another_name; a_of_s: many_names ] + another_name := reserve another_name(4); (* reserve space for an an array of character, with 4 members *) + many_names := reserve a_of_s(3); + many_names(0) := one_name; + many_names(1) := another_name; + many_names(2) := reserve a_of_s(2)(6); (* reserve space for an item of the same type as a_of_s(2), an array of character, with 6 members *) + many_names(2)(0) := "P"; + + return 0; +} \ No newline at end of file diff --git a/tests/sprint2/test/sp2_valid_assignable_and_mem.alpha b/tests/sprint2/test/sp2_valid_assignable_and_mem.alpha new file mode 100644 index 0000000..a49c5dd --- /dev/null +++ b/tests/sprint2/test/sp2_valid_assignable_and_mem.alpha @@ -0,0 +1,16 @@ +type main: string -> integer +function entry: main + +type rec: [integer: x; integer: y] +type T2: rec -> integer + +entry(arg) := { + [rec: w] + + w := reserve w; + w.x := 1; + w.y := 2; + w := release w; + + return 0; +} \ No newline at end of file diff --git a/tests/sprint3/expected/sp3_and_or_type_check.expected b/tests/sprint3/expected/sp3_and_or_type_check.expected new file mode 100644 index 0000000..493f53b --- /dev/null +++ b/tests/sprint3/expected/sp3_and_or_type_check.expected @@ -0,0 +1,50 @@ +001: type rec: [integer: x; integer: y] +002: type main: rec -> integer +003: function test: main +004: +005: test (arg) := { +006: [integer:x; Boolean: b] +007: while (true) { +008: x := 0; +009: } +010: +011: while (7) { +012: x := 1; +013: } +014: +015: if (true) then { +016: x := 1; +017: } else { +018: x := 0; +019: } +020: +021: if (x) then { +022: x := 0; +023: } else { +024: x := 1; +025: } +026: +027: b := b | b; +028: b := b & b; +029: b := 1 | b; + LINE (29:12) ** TYPE ERROR: b != undefined + +030: b := b | 1; + LINE (30:12) ** TYPE ERROR: b != undefined + +031: b := b & 1; + LINE (31:12) ** TYPE ERROR: b != undefined + +032: b := 1 & b; + LINE (32:12) ** TYPE ERROR: b != undefined + +033: b := 1 = 1; +034: +035: +036: +037: b := 1 = b; + LINE (37:12) ** TYPE ERROR: b != undefined + +038: +039: return 0; +040: } diff --git a/tests/sprint3/expected/sp3_boolean_binary_op_typecheck.expected b/tests/sprint3/expected/sp3_boolean_binary_op_typecheck.expected new file mode 100644 index 0000000..f95e765 --- /dev/null +++ b/tests/sprint3/expected/sp3_boolean_binary_op_typecheck.expected @@ -0,0 +1,16 @@ +001: type main: string -> integer +002: function entry: main +003: +004: entry (arg) := { +005: [integer:x; address: arr; address: arr2; Boolean : b2; Boolean : b1] +006: +007: b2 := 3 < x; +008: b1 := arr = 2; + LINE (8:18) ** TYPE ERROR: b1 != undefined + +009: b1 := 6<7 & arr2=7; + LINE (9:23) ** TYPE ERROR: b1 != undefined + +010: +011: return 0; +012: } diff --git a/tests/sprint3/expected/sp3_boolean_unary_op_typecheck.expected b/tests/sprint3/expected/sp3_boolean_unary_op_typecheck.expected new file mode 100644 index 0000000..39237bc --- /dev/null +++ b/tests/sprint3/expected/sp3_boolean_unary_op_typecheck.expected @@ -0,0 +1,13 @@ +001: type main: string -> integer +002: function entry: main +003: +004: entry (arg) := { +005: [integer:x; address: arr; address: arr2; Boolean : b2; Boolean : b1] +006: +007: b2 := !(3 < 2); +008: b1 := !5; + LINE (8:13) ** TYPE ERROR: b1 != undefined + +009: +010: return 0; +011: } diff --git a/tests/sprint3/expected/sp3_carls_second_mistake.expected b/tests/sprint3/expected/sp3_carls_second_mistake.expected new file mode 100644 index 0000000..6f509e0 --- /dev/null +++ b/tests/sprint3/expected/sp3_carls_second_mistake.expected @@ -0,0 +1,20 @@ +NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +a_of_s : 001001 : : 1 -> string : Type of Array +string : 001001 : : 1 -> character : Type of Array +entry : 001001 : : undefined : Function Definition +main : 001001 : : string -> integer : Type of Function +integer : 001001 : : Primitive Type : size-4 bytes +address : 001001 : : Primitive Type : size-8 bytes +character : 001001 : : Primitive Type : size-1 bytes +string : 001001 : : 1 -> character : Type of Array +Boolean : 001001 : : Primitive Type : size-4 bytes +reserve type : 001001 : : integer -> address : Type of Function +reserve : 001001 : : undefined : Function Definition +release type : 001001 : : address -> integer : Type of Function +release : 001001 : : undefined : Function Definition +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +many_names : 009000 : 001001 : a_of_s : Array Instance +another_name : 009000 : 001001 : string : Array Instance +one_name : 009000 : 001001 : string : Array Instance +arg : 009000 : 001001 : string : Array Instance diff --git a/tests/sprint3/expected/sp3_integer_binary_op_typecheck.expected b/tests/sprint3/expected/sp3_integer_binary_op_typecheck.expected new file mode 100644 index 0000000..0b4c83f --- /dev/null +++ b/tests/sprint3/expected/sp3_integer_binary_op_typecheck.expected @@ -0,0 +1,25 @@ +001: type main: string -> integer +002: +003: type rec: [integer: x; integer: y] +004: function entry: main +005: +006: entry (arg) := { +007: [integer:x; address: arr; address: arr2; Boolean : b2; Boolean : b1; character : a; rec : r] +008: +009: x := 3 + 2 * 8; +010: x := 3 - 2 / 8; +011: x := a * 2 % 8; + LINE (11:20) ** TYPE ERROR: x != undefined + +012: b2 := 3 * 2 % 8; +013: x := 3 % 2 * 8; +014: x := 3 + arr - 8; + LINE (14:22) ** TYPE ERROR: x != undefined + +015: x := r.x; + LINE (15:10) ** TYPE ERROR: x != r + +016: x := a.x; +017: +018: return 0; +019: } diff --git a/tests/sprint3/expected/sp3_integer_unary_op_typecheck.expected b/tests/sprint3/expected/sp3_integer_unary_op_typecheck.expected new file mode 100644 index 0000000..18bd5a7 --- /dev/null +++ b/tests/sprint3/expected/sp3_integer_unary_op_typecheck.expected @@ -0,0 +1,14 @@ +001: type main: string -> integer +002: function entry: main +003: +004: entry (arg) := { +005: [integer:x; address: arr; address: arr2; Boolean : b2; Boolean : b1] +006: +007: x := -8; +008: x := -b1; + LINE (8:10) ** TYPE ERROR: x != undefined + +009: b2 := -x; +010: +011: return 0; +012: } diff --git a/tests/sprint3/expected/sp3_multiple_args.expected b/tests/sprint3/expected/sp3_multiple_args.expected new file mode 100644 index 0000000..c0128e1 --- /dev/null +++ b/tests/sprint3/expected/sp3_multiple_args.expected @@ -0,0 +1,25 @@ +NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +bar : 001001 : : undefined : Function Definition +entry : 001001 : : undefined : Function Definition +main : 001001 : : string -> integer : Type of Function +T2 : 001001 : : rec -> integer : Type of Function +rec : 001001 : : Record Type : elements-2 size-6 bytes +integer : 001001 : : Primitive Type : size-4 bytes +address : 001001 : : Primitive Type : size-8 bytes +character : 001001 : : Primitive Type : size-1 bytes +string : 001001 : : 1 -> character : Type of Array +Boolean : 001001 : : Primitive Type : size-4 bytes +reserve type : 001001 : : integer -> address : Type of Function +reserve : 001001 : : undefined : Function Definition +release type : 001001 : : address -> integer : Type of Function +release : 001001 : : undefined : Function Definition +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +w : 013000 : 001001 : rec : Record Instance +result : 013000 : 001001 : integer : Primitive Instance +arg : 013000 : 001001 : string : Array Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: + : 009000 : 001001 : : Empty Scope +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +y : 001000 : 001001 : integer : Primitive Instance +x : 001000 : 001001 : character : Primitive Instance diff --git a/tests/sprint3/expected/sp3_primitive_type_check.expected b/tests/sprint3/expected/sp3_primitive_type_check.expected new file mode 100644 index 0000000..0a57752 --- /dev/null +++ b/tests/sprint3/expected/sp3_primitive_type_check.expected @@ -0,0 +1,19 @@ +NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +entry : 001001 : : undefined : Function Definition +main : 001001 : : string -> integer : Type of Function +integer : 001001 : : Primitive Type : size-4 bytes +address : 001001 : : Primitive Type : size-8 bytes +character : 001001 : : Primitive Type : size-1 bytes +string : 001001 : : 1 -> character : Type of Array +Boolean : 001001 : : Primitive Type : size-4 bytes +reserve type : 001001 : : integer -> address : Type of Function +reserve : 001001 : : undefined : Function Definition +release type : 001001 : : address -> integer : Type of Function +release : 001001 : : undefined : Function Definition +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +bool : 015000 : 001001 : Boolean : Primitive Instance +char : 015000 : 001001 : character : Primitive Instance +add : 015000 : 001001 : address : Primitive Instance +i : 015000 : 001001 : integer : Primitive Instance +arg : 015000 : 001001 : string : Array Instance diff --git a/tests/sprint3/expected/sp3_record_size_check.expected b/tests/sprint3/expected/sp3_record_size_check.expected new file mode 100644 index 0000000..a061979 --- /dev/null +++ b/tests/sprint3/expected/sp3_record_size_check.expected @@ -0,0 +1,29 @@ +NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +tricky : 001001 : : Record Type : elements-4 size-16 bytes +rec : 001001 : : Record Type : elements-6 size-24 bytes +tom : 001001 : : Record Type : elements-2 size-8 bytes +integer : 001001 : : Primitive Type : size-4 bytes +address : 001001 : : Primitive Type : size-8 bytes +character : 001001 : : Primitive Type : size-1 bytes +string : 001001 : : 1 -> character : Type of Array +Boolean : 001001 : : Primitive Type : size-4 bytes +reserve type : 001001 : : integer -> address : Type of Function +reserve : 001001 : : undefined : Function Definition +release type : 001001 : : address -> integer : Type of Function +release : 001001 : : undefined : Function Definition +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +k2 : 003000 : 001001 : integer : Primitive Instance +b2 : 003000 : 001001 : Boolean : Primitive Instance +k1 : 003000 : 001001 : integer : Primitive Instance +b1 : 003000 : 001001 : Boolean : Primitive Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +y : 002000 : 001001 : integer : Primitive Instance +b : 002000 : 001001 : Boolean : Primitive Instance +d : 002000 : 001001 : character : Primitive Instance +c : 002000 : 001001 : character : Primitive Instance +prev : 002000 : 001001 : tom : Record Instance +x : 002000 : 001001 : integer : Primitive Instance +------------------------------:--------:--------:-----------------------------------:-----------------------------------: +y : 001000 : 001001 : integer : Primitive Instance +x : 001000 : 001001 : integer : Primitive Instance diff --git a/tests/sprint3/test/sp3_and_or_type_check.alpha b/tests/sprint3/test/sp3_and_or_type_check.alpha new file mode 100644 index 0000000..c01fc10 --- /dev/null +++ b/tests/sprint3/test/sp3_and_or_type_check.alpha @@ -0,0 +1,40 @@ +type rec: [integer: x; integer: y] +type main: rec -> integer +function test: main + +test (arg) := { + [integer:x; Boolean: b] + while (true) { + x := 0; + } + + while (7) { + x := 1; + } + + if (true) then { + x := 1; + } else { + x := 0; + } + + if (x) then { + x := 0; + } else { + x := 1; + } + + b := b | b; + b := b & b; + b := 1 | b; + b := b | 1; + b := b & 1; + b := 1 & b; + b := 1 = 1; + + + + b := 1 = b; + + return 0; +} diff --git a/tests/sprint3/test/sp3_boolean_binary_op_typecheck.alpha b/tests/sprint3/test/sp3_boolean_binary_op_typecheck.alpha new file mode 100644 index 0000000..538d982 --- /dev/null +++ b/tests/sprint3/test/sp3_boolean_binary_op_typecheck.alpha @@ -0,0 +1,12 @@ +type main: string -> integer +function entry: main + +entry (arg) := { + [integer:x; address: arr; address: arr2; Boolean : b2; Boolean : b1] + + b2 := 3 < x; + b1 := arr = 2; + b1 := 6<7 & arr2=7; + + return 0; +} diff --git a/tests/sprint3/test/sp3_boolean_unary_op_typecheck.alpha b/tests/sprint3/test/sp3_boolean_unary_op_typecheck.alpha new file mode 100644 index 0000000..6a23ff6 --- /dev/null +++ b/tests/sprint3/test/sp3_boolean_unary_op_typecheck.alpha @@ -0,0 +1,11 @@ +type main: string -> integer +function entry: main + +entry (arg) := { + [integer:x; address: arr; address: arr2; Boolean : b2; Boolean : b1] + + b2 := !(3 < 2); + b1 := !5; + + return 0; +} diff --git a/tests/sprint3/test/sp3_carls_second_mistake.alpha b/tests/sprint3/test/sp3_carls_second_mistake.alpha new file mode 100644 index 0000000..ddb58a4 --- /dev/null +++ b/tests/sprint3/test/sp3_carls_second_mistake.alpha @@ -0,0 +1,30 @@ +type main: string -> integer +function entry: main + +type string: 1 -> character +type a_of_s: 1 -> string + +(* maybe some other type definitions *) + +entry (arg) := { + [ string: one_name; string: another_name; a_of_s: many_names ] + + one_name := "a string literal"; + another_name := reserve another_name(4); (* reserve space for an an array of character, with 4 members *) + another_name(0) := 'C'; + another_name(1) := 'a'; + another_name(2) := 'r'; + another_name(3) := 'l'; + many_names := reserve many_names(3); + many_names(0) := one_name; + many_names(1) := another_name; + many_names(2) := reserve many_names(2)(6); (* reserve space for an item of the same type as a_of_s(2), an array of character, with 6 members *) + many_names(2)(0) := 'P'; + many_names(2)(1) := 'a'; + many_names(2)(2) := 'r'; + many_names(2)(3) := 't'; + many_names(2)(4) := 'h'; + many_names(2)(5) := 'o'; + + return 0; +} \ No newline at end of file diff --git a/tests/sprint3/test/sp3_integer_binary_op_typecheck.alpha b/tests/sprint3/test/sp3_integer_binary_op_typecheck.alpha new file mode 100644 index 0000000..2adb394 --- /dev/null +++ b/tests/sprint3/test/sp3_integer_binary_op_typecheck.alpha @@ -0,0 +1,19 @@ +type main: string -> integer + +type rec: [integer: x; integer: y] +function entry: main + +entry (arg) := { + [integer:x; address: arr; address: arr2; Boolean : b2; Boolean : b1; character : a; rec : r] + + x := 3 + 2 * 8; + x := 3 - 2 / 8; + x := a * 2 % 8; + b2 := 3 * 2 % 8; + x := 3 % 2 * 8; + x := 3 + arr - 8; + x := r.x; + x := a.x; + + return 0; +} diff --git a/tests/sprint3/test/sp3_integer_unary_op_typecheck.alpha b/tests/sprint3/test/sp3_integer_unary_op_typecheck.alpha new file mode 100644 index 0000000..7ab6817 --- /dev/null +++ b/tests/sprint3/test/sp3_integer_unary_op_typecheck.alpha @@ -0,0 +1,12 @@ +type main: string -> integer +function entry: main + +entry (arg) := { + [integer:x; address: arr; address: arr2; Boolean : b2; Boolean : b1] + + x := -8; + x := -b1; + b2 := -x; + + return 0; +} diff --git a/tests/sprint3/test/sp3_multiple_args.alpha b/tests/sprint3/test/sp3_multiple_args.alpha new file mode 100644 index 0000000..8475d92 --- /dev/null +++ b/tests/sprint3/test/sp3_multiple_args.alpha @@ -0,0 +1,18 @@ +type rec: [character: x; integer: y] + +type T2: rec -> integer + +type main: string -> integer +function entry: main +function bar: T2 + +bar (r,s) := { + return 0; +} + +entry (arg) := { + [ integer: result ; rec: w] + result := bar(1,2); + result := bar('c', 7); + return 0; +} \ No newline at end of file diff --git a/tests/sprint3/test/sp3_primitive_type_check.alpha b/tests/sprint3/test/sp3_primitive_type_check.alpha new file mode 100644 index 0000000..6980aba --- /dev/null +++ b/tests/sprint3/test/sp3_primitive_type_check.alpha @@ -0,0 +1,23 @@ +(* + Testing the following type checks: + - integer : primitive + - character : primitive + - boolean : primitive + + - address (not included, special case) +*) + + + +type main: string -> integer +function entry: main + +entry (arg) := { + [integer: i; address: add; character: char; Boolean: bool] + + i := 3 + 2 * 8; + char := 'a'; + bool := true; + + return 0; +} diff --git a/tests/sprint3/test/sp3_record_size_check.alpha b/tests/sprint3/test/sp3_record_size_check.alpha new file mode 100644 index 0000000..8e123d0 --- /dev/null +++ b/tests/sprint3/test/sp3_record_size_check.alpha @@ -0,0 +1,3 @@ +type tom : [integer : x; integer: y] +type rec : [integer : x; tom : prev; character : c; character : d; Boolean: b; integer : y] +type tricky : [Boolean : b1; integer : k1; Boolean : b2; integer : k2] \ No newline at end of file diff --git a/tests/sprint4/expected/sp4_cg_add.expected b/tests/sprint4/expected/sp4_cg_add.expected new file mode 100644 index 0000000..4764400 --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_add.expected @@ -0,0 +1,12 @@ + movl $1, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movl $3, -12(%rbp) #constant assign + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + movl -16(%rbp), %eax #addition start + movl -16(%rbp), %eax + addl %edx, %eax + movl %eax, -20(%rbp) #addition end + movl -20(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end diff --git a/tests/sprint4/expected/sp4_cg_and.expected b/tests/sprint4/expected/sp4_cg_and.expected new file mode 100644 index 0000000..be6a53e --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_and.expected @@ -0,0 +1,20 @@ + movl $-1, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movl $-1, -12(%rbp) #constant assign + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + cmpl $0, -8(%rbp) #start and + je .L1or2 + cmpl $0, -16(%rbp) + je .L1or2 + movl $1, %eax + jmp .L1or3 +.L1or2: + movl $0, %eax +.L1or3: + movb %al, -20(%rbp) + andb $1, -20(%rbp) #and end + movl -20(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + movl $1, -24(%rbp) #constant assign diff --git a/tests/sprint4/expected/sp4_cg_div.expected b/tests/sprint4/expected/sp4_cg_div.expected new file mode 100644 index 0000000..1a71c6e --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_div.expected @@ -0,0 +1,12 @@ + movl $1, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movl $3, -12(%rbp) #constant assign + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + movl -16(%rbp), %eax #division start + cltd + idivl -8(%rbp) + movl %eax, -20(%rbp) #division end + movl -20(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end diff --git a/tests/sprint4/expected/sp4_cg_equal_to.expected b/tests/sprint4/expected/sp4_cg_equal_to.expected new file mode 100644 index 0000000..e29c6c1 --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_equal_to.expected @@ -0,0 +1,13 @@ + movl $1, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movl $2, -12(%rbp) #constant assign + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + movl -8(%rbp), %eax #equal to start + cmpl -16(%rbp), %eax + sete %al + movb %al, -20(%rbp) #equal to end + movl -20(%rbp), %eax #assign start + movl %eax, -24(%rbp) #assign end + movl $1, -28(%rbp) #constant assign diff --git a/tests/sprint4/expected/sp4_cg_less_than.expected b/tests/sprint4/expected/sp4_cg_less_than.expected new file mode 100644 index 0000000..b8d8904 --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_less_than.expected @@ -0,0 +1,13 @@ + movl $1, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movl $2, -12(%rbp) #constant assign + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + movl -8(%rbp), %eax #less than start + cmpl -16(%rbp), %eax + setl %al + movb %al, -20(%rbp) #less than end + movl -20(%rbp), %eax #assign start + movl %eax, -24(%rbp) #assign end + movl $1, -28(%rbp) #constant assign diff --git a/tests/sprint4/expected/sp4_cg_mod.expected b/tests/sprint4/expected/sp4_cg_mod.expected new file mode 100644 index 0000000..97d4259 --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_mod.expected @@ -0,0 +1,12 @@ + movl $1, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movl $3, -12(%rbp) #constant assign + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + movl -16(%rbp), %eax #mod start + cltd + idivl -8(%rbp) + movl %edx, -20(%rbp) #mod end + movl -20(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end diff --git a/tests/sprint4/expected/sp4_cg_mult.expected b/tests/sprint4/expected/sp4_cg_mult.expected new file mode 100644 index 0000000..20b0a57 --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_mult.expected @@ -0,0 +1,11 @@ + movl $1, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movl $3, -12(%rbp) #constant assign + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + movl -16(%rbp), %eax #multiplication start + imull -16(%rbp), %eax + movl %eax, -20(%rbp) #multiplication end + movl -20(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end diff --git a/tests/sprint4/expected/sp4_cg_neg.expected b/tests/sprint4/expected/sp4_cg_neg.expected new file mode 100644 index 0000000..5f61770 --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_neg.expected @@ -0,0 +1,8 @@ + movl $3, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movl -8(%rbp), %eax #negation start + negl %eax + movl %eax, -12(%rbp) #negation end + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end diff --git a/tests/sprint4/expected/sp4_cg_not.expected b/tests/sprint4/expected/sp4_cg_not.expected new file mode 100644 index 0000000..b2e4bda --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_not.expected @@ -0,0 +1,13 @@ + movl $-1, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movzbl -8(%rbp), %eax #not start + testl %eax, %eax + setne %al + xorl $1, %eax + movzbl %al, %eax + movb %al, -12(%rbp) + andb $1, -12(%rbp) #not end + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + movl $1, -20(%rbp) #constant assign diff --git a/tests/sprint4/expected/sp4_cg_or.expected b/tests/sprint4/expected/sp4_cg_or.expected new file mode 100644 index 0000000..120058f --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_or.expected @@ -0,0 +1,21 @@ + movl $-1, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movl $-1, -12(%rbp) #constant assign + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + cmpl $0, -8(%rbp) #start or + jne .L1or2 + cmpl $0, -16(%rbp) + je .L1or3 +.L1or2: + movl $1, %eax + jmp .L1or4 +.L1or3: + movl $0, %eax +.L1or4: + movb %al, -20(%rbp) + andb $1, -20(%rbp) #or end + movl -20(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + movl $1, -24(%rbp) #constant assign diff --git a/tests/sprint4/expected/sp4_cg_sub.expected b/tests/sprint4/expected/sp4_cg_sub.expected new file mode 100644 index 0000000..743ef59 --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_sub.expected @@ -0,0 +1,11 @@ + movl $1, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movl $3, -12(%rbp) #constant assign + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + movl -16(%rbp), %eax #subtraction start + subl -8(%rbp), %eax + movl %eax, -20(%rbp) #subtraction end + movl -20(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end diff --git a/tests/sprint4/test/sp4_cg_add.alpha b/tests/sprint4/test/sp4_cg_add.alpha new file mode 100644 index 0000000..f4f8138 --- /dev/null +++ b/tests/sprint4/test/sp4_cg_add.alpha @@ -0,0 +1,10 @@ +type main: integer -> integer +function test: main + +test (a) := { + [integer:x; integer:y] + y := 1; + x := 3; + y := x + y; + return y; +} \ No newline at end of file diff --git a/tests/sprint4/test/sp4_cg_and.alpha b/tests/sprint4/test/sp4_cg_and.alpha new file mode 100644 index 0000000..5017e35 --- /dev/null +++ b/tests/sprint4/test/sp4_cg_and.alpha @@ -0,0 +1,10 @@ +type main: integer -> integer +function test: main + +test (a) := { + [Boolean:b; Boolean: c; Boolean: d] + c := true; + d := false; + d := c & d; + return 1; +} \ No newline at end of file diff --git a/tests/sprint4/test/sp4_cg_div.alpha b/tests/sprint4/test/sp4_cg_div.alpha new file mode 100644 index 0000000..32d3537 --- /dev/null +++ b/tests/sprint4/test/sp4_cg_div.alpha @@ -0,0 +1,10 @@ +type main: integer -> integer +function test: main + +test (a) := { + [integer:x; integer:y] + y := 1; + x := 3; + y := x / y; + return y; +} \ No newline at end of file diff --git a/tests/sprint4/test/sp4_cg_equal_to.alpha b/tests/sprint4/test/sp4_cg_equal_to.alpha new file mode 100644 index 0000000..a3da50c --- /dev/null +++ b/tests/sprint4/test/sp4_cg_equal_to.alpha @@ -0,0 +1,10 @@ +type main: integer -> integer +function test: main + +test (a) := { + [Boolean: b; integer: x; integer: y] + x := 1; + y := 2; + b := x = y; + return 1; +} \ No newline at end of file diff --git a/tests/sprint4/test/sp4_cg_less_than.alpha b/tests/sprint4/test/sp4_cg_less_than.alpha new file mode 100644 index 0000000..8f41ced --- /dev/null +++ b/tests/sprint4/test/sp4_cg_less_than.alpha @@ -0,0 +1,10 @@ +type main: integer -> integer +function test: main + +test (a) := { + [Boolean: b; integer: x; integer: y] + x := 1; + y := 2; + b := x < y; + return 1; +} \ No newline at end of file diff --git a/tests/sprint4/test/sp4_cg_mod.alpha b/tests/sprint4/test/sp4_cg_mod.alpha new file mode 100644 index 0000000..1b579d5 --- /dev/null +++ b/tests/sprint4/test/sp4_cg_mod.alpha @@ -0,0 +1,10 @@ +type main: integer -> integer +function test: main + +test (a) := { + [integer:x; integer:y] + y := 1; + x := 3; + y := x % y; + return y; +} \ No newline at end of file diff --git a/tests/sprint4/test/sp4_cg_mult.alpha b/tests/sprint4/test/sp4_cg_mult.alpha new file mode 100644 index 0000000..c151a6b --- /dev/null +++ b/tests/sprint4/test/sp4_cg_mult.alpha @@ -0,0 +1,10 @@ +type main: integer -> integer +function test: main + +test (a) := { + [integer:x; integer:y] + y := 1; + x := 3; + y := x * x; + return y; +} \ No newline at end of file diff --git a/tests/sprint4/test/sp4_cg_neg.alpha b/tests/sprint4/test/sp4_cg_neg.alpha new file mode 100644 index 0000000..345980b --- /dev/null +++ b/tests/sprint4/test/sp4_cg_neg.alpha @@ -0,0 +1,9 @@ +type main: integer -> integer +function test: main + +test (a) := { + [integer:x; integer:y] + x := 3; + y := -x; + return y; +} \ No newline at end of file diff --git a/tests/sprint4/test/sp4_cg_not.alpha b/tests/sprint4/test/sp4_cg_not.alpha new file mode 100644 index 0000000..40252f9 --- /dev/null +++ b/tests/sprint4/test/sp4_cg_not.alpha @@ -0,0 +1,9 @@ +type main: integer -> integer +function test: main + +test (a) := { + [Boolean: c; Boolean: d] + c := true; + d := !c; + return 1; +} \ No newline at end of file diff --git a/tests/sprint4/test/sp4_cg_or.alpha b/tests/sprint4/test/sp4_cg_or.alpha new file mode 100644 index 0000000..b6d6766 --- /dev/null +++ b/tests/sprint4/test/sp4_cg_or.alpha @@ -0,0 +1,10 @@ +type main: integer -> integer +function test: main + +test (a) := { + [Boolean:b; Boolean: c; Boolean: d] + c := true; + d := false; + d := c | d; + return 1; +} \ No newline at end of file diff --git a/tests/sprint4/test/sp4_cg_sub.alpha b/tests/sprint4/test/sp4_cg_sub.alpha new file mode 100644 index 0000000..f280c9d --- /dev/null +++ b/tests/sprint4/test/sp4_cg_sub.alpha @@ -0,0 +1,10 @@ +type main: integer -> integer +function test: main + +test (a) := { + [integer:x; integer:y] + y := 1; + x := 3; + y := x - y; + return y; +} \ No newline at end of file