Merge pull request #50 from UB-CSE443/Sprint4-ASC_TC-FE-t#NoTask
Sprint4 asc tc fe t#no task
This commit is contained in:
81
Makefile
81
Makefile
@ -1,39 +1,74 @@
|
||||
# ----- 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) -g -ggdb 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
|
||||
|
||||
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
|
||||
@ -66,16 +101,4 @@ test-s4:
|
||||
chmod +x ./test.sh
|
||||
./test.sh sp4
|
||||
./check.sh sp4
|
||||
|
||||
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
|
||||
# -----------
|
618
src/codegen.c
Normal file
618
src/codegen.c
Normal file
@ -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;
|
||||
}
|
60
src/codegen.h
Normal file
60
src/codegen.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* Code Generator */
|
||||
/* The Translators - Spring 2025 */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
32
src/grammar.h
Normal file
32
src/grammar.h
Normal file
@ -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;
|
254
src/grammar.y
254
src/grammar.y
@ -1,4 +1,3 @@
|
||||
|
||||
/* Syntax Analyzer with Bison (3.8.2) */
|
||||
/* The Translators - Spring 2025 */
|
||||
|
||||
@ -17,13 +16,7 @@
|
||||
// Please ask Scarlett if you are unsure of how to format something. Thanks! 😀
|
||||
|
||||
%{
|
||||
#include "../src/symbol_table.c"
|
||||
void yyerror(const char *err);
|
||||
extern FILE *asc_flag;
|
||||
extern bool tc_flag;
|
||||
int token_tracker;
|
||||
TableNode * tn;
|
||||
void error_type(TableNode * left, TableNode * right, const char *format, ...);
|
||||
#include "../src/grammar.h"
|
||||
%}
|
||||
|
||||
%union {
|
||||
@ -113,6 +106,7 @@
|
||||
|
||||
program:
|
||||
prototype_or_definition_list
|
||||
| error { yyerrok; }
|
||||
;
|
||||
|
||||
|
||||
@ -122,12 +116,17 @@ 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; }
|
||||
|
||||
;
|
||||
|
||||
|
||||
|
||||
@ -172,9 +171,9 @@ definition:
|
||||
printdebug("see function def rule 1\n");
|
||||
TableNode *node = table_lookup(getAncestor(cur), $1);
|
||||
if (node == undefined) {
|
||||
error_type(undefined, undefined, "Undefined node declared.");
|
||||
printdebug("Undefined node declared.");
|
||||
}else if(getAdInfoType(node) != TYPE_FUNCTION_DECLARATION){
|
||||
error_type(undefined, undefined, "Not a valid function declaration.");
|
||||
throw_error(ERROR_SYNTAX, "Not a valid function declaration.");
|
||||
}
|
||||
else {
|
||||
printdebug("setting as keyword to true");
|
||||
@ -188,7 +187,7 @@ definition:
|
||||
//TableNode *parameter = getParameter(table_lookup(getAncestor(cur), getType(table_lookup(getAncestor(cur), $1))));
|
||||
printdebug("type of parameter: %s", getName(parameter));
|
||||
if (parameter == undefined) {
|
||||
error_type(undefined, undefined, "Undefined parameter in function definition.");
|
||||
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
|
||||
@ -199,7 +198,7 @@ definition:
|
||||
|| 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
|
||||
error_type(parameter, undefined, "Invalid type (%s) of parameter in function definition.", getAdInfo(parameter));
|
||||
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){
|
||||
@ -227,7 +226,7 @@ definition:
|
||||
|| 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
|
||||
error_type(entry, undefined, "Invalid type (%s) of parameter in function definition.", getAdInfo(entry));
|
||||
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));
|
||||
@ -258,9 +257,9 @@ definition:
|
||||
} idlist R_PAREN ASSIGN sblock {
|
||||
TableNode *expected = getReturn(getTypeEntry(look_up(cur, $1)));
|
||||
if ($8 == undefined) {
|
||||
error_type(undefined, undefined, "Expected %s as return type but got undefined (possibly NULL). Differing return types in function.", getName(expected));
|
||||
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) {
|
||||
error_type(undefined, undefined, "Expected %s as return type but got %s. Differing return types in function.", getName(expected), getName($8));
|
||||
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!!!");
|
||||
}
|
||||
@ -275,7 +274,7 @@ function_declaration:
|
||||
CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $4), $2, CreateFunctionDeclarationInfo(-1, false));
|
||||
}
|
||||
else{
|
||||
error_type(undefined, undefined, "Function declatation (%s) is not a valid function type", $2);
|
||||
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));
|
||||
|
||||
}
|
||||
@ -287,11 +286,12 @@ function_declaration:
|
||||
CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $5), $3, CreateFunctionDeclarationInfo(-1, false));
|
||||
}
|
||||
else{
|
||||
error_type(undefined, undefined, "Function declatation (%s) is not a valid function type", $3);
|
||||
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));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
|
||||
@ -351,6 +351,9 @@ idlist:
|
||||
printdebug("Type of entry is %s", getType(entry));
|
||||
printdebug("tag is %d", getAdInfoType(entry));
|
||||
}
|
||||
|
||||
| error { yyerrok; }
|
||||
|
||||
;
|
||||
|
||||
|
||||
@ -398,6 +401,9 @@ sblock:
|
||||
}
|
||||
R_BRACE
|
||||
{$$ = $5;}
|
||||
|
||||
| error { yyerrok; }
|
||||
|
||||
;
|
||||
|
||||
|
||||
@ -415,13 +421,20 @@ dblock:
|
||||
printdebug("Created a new scope when seeing a dblock");
|
||||
}
|
||||
}
|
||||
declaration_list R_BRACKET;
|
||||
declaration_list R_BRACKET
|
||||
|
||||
| error { yyerrok; }
|
||||
|
||||
;
|
||||
|
||||
|
||||
|
||||
declaration_list:
|
||||
declaration SEMI_COLON declaration_list
|
||||
| declaration
|
||||
|
||||
| error { yyerrok; }
|
||||
|
||||
;
|
||||
|
||||
|
||||
@ -432,7 +445,8 @@ declaration:
|
||||
printdebug("ID/TYPE: %s, ID: %s", getName((TableNode*)$1), $3) ;
|
||||
int d = getAdInfoType((TableNode*)$1);
|
||||
if(d == TYPE_UNDEFINED) {
|
||||
error_type(undefined, undefined, "Undefined type passed in declaration list");
|
||||
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) {
|
||||
@ -455,10 +469,13 @@ declaration:
|
||||
d = TYPE_PRIMITIVE;
|
||||
CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1));
|
||||
}else {
|
||||
error_type(undefined, undefined, "Invalid type passed in declaration list.");
|
||||
throw_error(ERROR_TYPE, "%s is being defined with an undefined type", $3);
|
||||
CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1));
|
||||
}
|
||||
}
|
||||
|
||||
| error { yyerrok; }
|
||||
|
||||
;
|
||||
|
||||
|
||||
@ -475,6 +492,9 @@ id_or_types:
|
||||
printdebug("string of type is %s in types pattern of id_or_type rule.",getName((TableNode*)$1));
|
||||
$$ = (TableNode*)$1;
|
||||
}
|
||||
|
||||
| error { yyerrok; }
|
||||
|
||||
;
|
||||
|
||||
|
||||
@ -510,6 +530,7 @@ compound_statement statement_list {
|
||||
| simple_statement SEMI_COLON {
|
||||
$$ = $1;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
|
||||
@ -530,9 +551,11 @@ WHILE L_PAREN expression R_PAREN sblock {
|
||||
$$ = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
| sblock {
|
||||
$$ = $1;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
|
||||
@ -548,16 +571,16 @@ simple_statement:
|
||||
|
||||
node = ((TableNode*)$1);
|
||||
} else{
|
||||
error_type(undefined, undefined, "Invalid type passed to assignable.");
|
||||
printdebug("Invalid type passed to assignable.");
|
||||
node = undefined;
|
||||
}
|
||||
|
||||
|
||||
if(getAdInfoType(node) == getAdInfoType((TableNode*)$3)){
|
||||
//EMIT ASSIGN INSTRUCTION HERE
|
||||
emit_assignment($1, tn_or_const(NODE, $3));
|
||||
printdebug("%s[☺] Passed type check; %s = %s", COLOR_GREEN, getName(node), getName((TableNode*)$3));
|
||||
} else {
|
||||
error_type(node, (TableNode*)$3, "");
|
||||
throw_error(ERROR_TYPE, "%s != %s", getName(node), getName((TableNode*)$3));
|
||||
}
|
||||
|
||||
$$ = undefined;
|
||||
@ -565,6 +588,9 @@ simple_statement:
|
||||
|
||||
|
||||
| RETURN expression {$$ = getTypeEntry((TableNode*)$2);}
|
||||
|
||||
| error { yyerrok; }
|
||||
|
||||
;
|
||||
|
||||
|
||||
@ -572,6 +598,9 @@ simple_statement:
|
||||
rec_op:
|
||||
DOT
|
||||
|
||||
| error { yyerrok; }
|
||||
|
||||
;
|
||||
|
||||
|
||||
ablock:
|
||||
@ -580,6 +609,9 @@ ablock:
|
||||
$$ = $2;
|
||||
printdebug("ablock is %d", $$);
|
||||
}
|
||||
|
||||
| error { yyerrok; }
|
||||
|
||||
;
|
||||
|
||||
|
||||
@ -598,6 +630,9 @@ argument_list:
|
||||
CreateEntry(cur,getAdInfoType((TableNode*)$1),(TableNode*)$1, getName((TableNode*)$1), NULL);
|
||||
$$ = 1; printdebug("[ARGUMENT_LIST] argument list is %d", $$);
|
||||
}
|
||||
|
||||
| error { yyerrok; }
|
||||
|
||||
;
|
||||
|
||||
|
||||
@ -615,12 +650,13 @@ 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;
|
||||
error_type(getTypeEntry((TableNode*)$2), integ, "");
|
||||
throw_error(ERROR_TYPE, "%s != %s", getName(getTypeEntry((TableNode*)$2)), getName(integ));
|
||||
}
|
||||
}
|
||||
|
||||
@ -630,12 +666,13 @@ 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;
|
||||
error_type(getTypeEntry((TableNode*)$2), boo, "");
|
||||
throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$2), getName(boo));
|
||||
}
|
||||
}
|
||||
|
||||
@ -645,12 +682,11 @@ 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);
|
||||
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
|
||||
//result of binary operation
|
||||
emit_binary_op(E_ADD,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
|
||||
$$ = node;
|
||||
} else {
|
||||
$$=undefined;
|
||||
error_type(getTypeEntry((TableNode*)$1), getTypeEntry((TableNode*)$3), "");
|
||||
throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3));
|
||||
}
|
||||
}
|
||||
|
||||
@ -660,12 +696,12 @@ 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);
|
||||
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
|
||||
//result of binary operation
|
||||
emit_binary_op(E_SUB,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
|
||||
|
||||
$$ = node;
|
||||
} else {
|
||||
$$=undefined;
|
||||
error_type(getTypeEntry((TableNode*)$1), getTypeEntry((TableNode*)$3), "");
|
||||
throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3));
|
||||
}
|
||||
}
|
||||
|
||||
@ -675,12 +711,11 @@ 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);
|
||||
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
|
||||
//result of binary operation
|
||||
emit_binary_op(E_MUL,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
|
||||
$$ = node;
|
||||
} else {
|
||||
$$=undefined;
|
||||
error_type(getTypeEntry((TableNode*)$1), getTypeEntry((TableNode*)$3), "");
|
||||
throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3));
|
||||
}
|
||||
}
|
||||
|
||||
@ -690,12 +725,11 @@ 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);
|
||||
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
|
||||
//result of binary operation
|
||||
emit_binary_op(E_DIV,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
|
||||
$$ = node;
|
||||
} else {
|
||||
$$=undefined;
|
||||
error_type(getTypeEntry((TableNode*)$1), getTypeEntry((TableNode*)$3), "");
|
||||
throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3));
|
||||
}
|
||||
}
|
||||
|
||||
@ -705,12 +739,11 @@ 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);
|
||||
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
|
||||
//result of binary operation
|
||||
emit_binary_op(E_MOD,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
|
||||
$$ = node;
|
||||
} else {
|
||||
$$=undefined;
|
||||
error_type(getTypeEntry((TableNode*)$1), getTypeEntry((TableNode*)$3), "");
|
||||
throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3));
|
||||
}
|
||||
}
|
||||
|
||||
@ -720,12 +753,11 @@ expression:
|
||||
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);
|
||||
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
|
||||
//result of comparison
|
||||
emit_binary_op(E_AND,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
|
||||
$$ = node;
|
||||
} else {
|
||||
$$=undefined;
|
||||
error_type(getTypeEntry((TableNode*)$1), getTypeEntry((TableNode*)$3), "");
|
||||
throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3));
|
||||
}
|
||||
}
|
||||
|
||||
@ -735,12 +767,11 @@ expression:
|
||||
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);
|
||||
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
|
||||
//result of comparison
|
||||
emit_binary_op(E_OR,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
|
||||
$$ = node;
|
||||
} else {
|
||||
$$=undefined;
|
||||
error_type(getTypeEntry((TableNode*)$1), getTypeEntry((TableNode*)$3), "");
|
||||
throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3));
|
||||
}
|
||||
}
|
||||
|
||||
@ -750,12 +781,11 @@ 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);
|
||||
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
|
||||
//result of comparison
|
||||
emit_binary_op(E_LESS_THAN,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
|
||||
$$ = node;
|
||||
} else {
|
||||
$$=undefined;
|
||||
error_type(getTypeEntry((TableNode*)$1), getTypeEntry((TableNode*)$3), "");
|
||||
throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3));
|
||||
}
|
||||
}
|
||||
|
||||
@ -765,13 +795,12 @@ 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);
|
||||
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
|
||||
//result of compariosn
|
||||
emit_binary_op(E_EQUAL_TO,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
|
||||
$$ = node;
|
||||
|
||||
} else {
|
||||
$$ = undefined;
|
||||
error_type(getTypeEntry((TableNode*)$1), getTypeEntry((TableNode*)$3), "");
|
||||
throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3));
|
||||
}
|
||||
}
|
||||
|
||||
@ -795,11 +824,13 @@ expression:
|
||||
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
|
||||
$$ = node;
|
||||
} else {
|
||||
error_type(undefined, undefined, "Invalid memOp expression (%s).", getName((TableNode*)$2));
|
||||
throw_error(ERROR_TYPE, "Invalid memOp expression (%s).", getName((TableNode*)$2));
|
||||
$$=undefined;
|
||||
}
|
||||
}
|
||||
|
||||
| error { yyerrok; }
|
||||
|
||||
;
|
||||
|
||||
//UPDATED $$ for tablenodes to this point
|
||||
@ -811,6 +842,9 @@ 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));
|
||||
}
|
||||
@ -982,6 +1016,8 @@ assignable:
|
||||
printdebug("[ASSIGNABLE - RULE 3] record = name: %s | field = %s", getName((TableNode*)($1)), getName((TableNode*)$3));
|
||||
}
|
||||
|
||||
| error { yyerrok; }
|
||||
|
||||
;
|
||||
|
||||
|
||||
@ -997,6 +1033,8 @@ memOp:
|
||||
printdebug("release expression");
|
||||
}
|
||||
|
||||
| error { yyerrok; }
|
||||
|
||||
;
|
||||
|
||||
|
||||
@ -1005,7 +1043,7 @@ constant:
|
||||
{
|
||||
char* temp = temp_var_gen();
|
||||
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, stri, temp, NULL);
|
||||
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
|
||||
emit_assignment(node, tn_or_const(STRING,$1));
|
||||
printdebug("string of C_STRING in constant is %s", $1);
|
||||
$$ = node;
|
||||
}
|
||||
@ -1014,7 +1052,7 @@ constant:
|
||||
{
|
||||
char* temp = temp_var_gen();
|
||||
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
|
||||
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
|
||||
emit_assignment(node, tn_or_const(INTEGER,&$1));
|
||||
printdebug("number of C_INTEGER in constant is %d", $1);
|
||||
$$ = node;
|
||||
}
|
||||
@ -1023,7 +1061,7 @@ constant:
|
||||
{
|
||||
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)
|
||||
emit_assignment(node, tn_or_const(ADDRESS,$1));
|
||||
printdebug("string of C_NULL in constant is NULL");
|
||||
$$ = node;
|
||||
}
|
||||
@ -1032,7 +1070,7 @@ constant:
|
||||
{
|
||||
char* temp = temp_var_gen();
|
||||
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, chara, temp, NULL);
|
||||
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
|
||||
emit_assignment(node, tn_or_const(CHARACTER,&$1));
|
||||
printdebug("string of C_CHARACTER in constant is %s",$1);
|
||||
$$ = node;
|
||||
}
|
||||
@ -1041,7 +1079,8 @@ constant:
|
||||
{
|
||||
char* temp = temp_var_gen();
|
||||
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL);
|
||||
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
|
||||
uint_least8_t b = 1;
|
||||
emit_assignment(node, tn_or_const(BOOLEAN,&b));
|
||||
printdebug("string of C_TRUE in constant is true");
|
||||
$$ = node;
|
||||
}
|
||||
@ -1050,7 +1089,8 @@ constant:
|
||||
{
|
||||
char* temp = temp_var_gen();
|
||||
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL);
|
||||
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
|
||||
uint_least8_t b = 0;
|
||||
emit_assignment(node, tn_or_const(BOOLEAN,&b));
|
||||
printdebug("string of C_FALSE in constant is false");
|
||||
$$ = node;
|
||||
}
|
||||
@ -1083,43 +1123,81 @@ types:
|
||||
$$ = $1;
|
||||
printdebug("string of T_BOOLEAN in types is %s",getName((TableNode*)$1));
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
|
||||
|
||||
void error_type(TableNode * left, TableNode * right, const char *format, ...) {
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
yyerror("");
|
||||
if (strcmp(format, "") == 0) {
|
||||
if (asc_flag != NULL) {
|
||||
fprintf(asc_flag, "(%d:%d) ** TYPE ERROR: %s != %s\n", line, column, getName(left), getName(right));
|
||||
insert_code_line(total_error_message, line);
|
||||
} else {
|
||||
fprintf(stderr, "%s(%d:%d) ** TYPE ERROR%s: %s%s %s!= %s%s\n",
|
||||
COLOR_RED, line, column, COLOR_WHITE, COLOR_YELLOW, getName(left), COLOR_WHITE, COLOR_YELLOW, getName(right), COLOR_WHITE);
|
||||
}
|
||||
} else {
|
||||
if (asc_flag != NULL) {
|
||||
fprintf(asc_flag, "(%d:%d) ** TYPE ERROR: ", line, column);
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vfprintf(asc_flag, format, args);
|
||||
va_end(args);
|
||||
fprintf(asc_flag, "\n");
|
||||
} else {
|
||||
fprintf(stderr, "%s(%d:%d) ** TYPE ERROR%s: %s", COLOR_RED, line, column, COLOR_WHITE, COLOR_YELLOW);
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vfprintf(stderr, format, args);
|
||||
va_end(args);
|
||||
fprintf(stderr, "%s\n", COLOR_WHITE);
|
||||
if (error_type != ERROR_TYPE) {
|
||||
insert_code_line(total_error_message, line);
|
||||
}
|
||||
}
|
||||
|
||||
free(error_message);
|
||||
free(error_message2);
|
||||
free(total_error_message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1130,11 +1208,13 @@ void yyerror(const char *err) {
|
||||
// Grammar Fallback Case
|
||||
if (strcmp(err, "syntax error") == 0) {
|
||||
if (asc_flag != NULL) {
|
||||
fprintf(asc_flag, "(%d:%d) ** SYNTAX ERROR: Incorrect syntax at token '%s'\n", line, column, yytext);
|
||||
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, "%s(%d:%d) ** SYNTAX ERROR%s: Incorrect syntax at token '%s%s%s'\n",
|
||||
COLOR_RED, line, column, COLOR_WHITE, COLOR_YELLOW, yytext, COLOR_WHITE);
|
||||
fprintf(stderr, " LINE (%d:%d) ** SYNTAX ERROR: Incorrect syntax at token %s\n", line, column, yytext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,48 @@
|
||||
#include <stdio.h>
|
||||
/* Intermediate Code */
|
||||
/* The Translators - Spring 2025 */
|
||||
|
||||
#include "intermediate_code.h"
|
||||
|
||||
Instruction * begin;
|
||||
Instruction * current;
|
||||
char * temp = NULL;
|
||||
|
||||
|
||||
// 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 * tn_or_const(Op op, void * tnc) {
|
||||
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 = op;
|
||||
switch (op) {
|
||||
count->d = d;
|
||||
count->tnc_union = calloc(1, sizeof(*count->tnc_union));
|
||||
switch (d) {
|
||||
case NODE:
|
||||
count->tnc_union->node = tnc;
|
||||
break;
|
||||
@ -30,7 +59,7 @@ TNodeOrConst * tn_or_const(Op op, void * tnc) {
|
||||
count->tnc_union->character = *(char*)tnc;
|
||||
break;
|
||||
case BOOLEAN:
|
||||
count->tnc_union->Boolean = *(bool*)tnc;
|
||||
count->tnc_union->Boolean = *(uint_least8_t*)tnc;
|
||||
break;
|
||||
}
|
||||
return count;
|
||||
@ -44,7 +73,7 @@ static void emit_helper(void){
|
||||
} else {
|
||||
current->next = inst;
|
||||
inst->prev = current;
|
||||
inst->index = current->index++;
|
||||
inst->index = current->index + 1;
|
||||
current = inst;
|
||||
}
|
||||
}
|
||||
@ -52,10 +81,10 @@ static void emit_helper(void){
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
||||
void emit_unary_op(Op op, TableNode* result, TNodeOrConst* arg) {
|
||||
@ -63,38 +92,163 @@ void emit_unary_op(Op op, TableNode * result, TNodeOrConst * arg){
|
||||
current->opcode = op;
|
||||
current->result = result;
|
||||
current->operand1 = arg;
|
||||
return;
|
||||
}
|
||||
|
||||
void emit_assignment(TableNode* target, TNodeOrConst* source) {
|
||||
emit_helper();
|
||||
current->opcode = E_ASSIGN; // TODO: replace with move
|
||||
current->opcode = E_ASSIGN;
|
||||
current->result = target;
|
||||
current->operand1 = source;
|
||||
return;
|
||||
}
|
||||
|
||||
void emit_as_file(FILE * out_file, Instruction * instr_arr){
|
||||
if(instr_arr == NULL){
|
||||
return;
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
//fprintf(out_file,
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
||||
void emit_jump(int label) {
|
||||
emit_helper();
|
||||
current->opcode = E_GOTO;
|
||||
current->label = label;
|
||||
return;
|
||||
}
|
||||
|
||||
void emit_conditional_jump(Op condition, int label, ...) {
|
||||
@ -108,11 +262,13 @@ void emit_conditional_jump(Op condition, int label, ...){
|
||||
TNodeOrConst* n1;
|
||||
TNodeOrConst* n2;
|
||||
switch (condition) {
|
||||
case E_IF_X_TRUE: case E_IF_X_FALSE:
|
||||
case E_IF_X_TRUE:
|
||||
case E_IF_X_FALSE:
|
||||
n1 = va_arg(argptr, TNodeOrConst*);
|
||||
current->operand1 = n1;
|
||||
break;
|
||||
case E_LESSTHEN: case E_EQUALTO:
|
||||
case E_LESS_THAN:
|
||||
case E_EQUAL_TO:
|
||||
n1 = va_arg(argptr, TNodeOrConst*);
|
||||
n2 = va_arg(argptr, TNodeOrConst*);
|
||||
current->operand1 = n1;
|
||||
@ -120,22 +276,19 @@ void emit_conditional_jump(Op condition, int label, ...){
|
||||
break;
|
||||
}
|
||||
va_end(argptr);
|
||||
return;
|
||||
}
|
||||
|
||||
void emit_function_start(int name){
|
||||
void emit_function_start(TNodeOrConst * name) {
|
||||
emit_helper();
|
||||
current->opcode = E_LABEL; // I think this is right TODO: ask
|
||||
current->label = name;
|
||||
// this is probabaly a func decleration
|
||||
return;
|
||||
current->operand1 = name;
|
||||
// this is probabaly a func declaration
|
||||
}
|
||||
|
||||
void emit_parameter(TNodeOrConst* param) {
|
||||
emit_helper();
|
||||
current->opcode = E_PARAM;
|
||||
current->operand1 = param;
|
||||
return;
|
||||
}
|
||||
|
||||
void emit_function_call(TableNode* result, int param_count, TNodeOrConst* name) {
|
||||
@ -144,49 +297,104 @@ void emit_function_call(TableNode * result, int param_count, TNodeOrConst * name
|
||||
current->operand1 = tn_or_const(INTEGER, ¶m_count);
|
||||
current->operand2 = name;
|
||||
current->result = result;
|
||||
return;
|
||||
}
|
||||
|
||||
void emit_return(TNodeOrConst* value) {
|
||||
emit_helper();
|
||||
current->opcode = E_RETURN;
|
||||
current->operand1 = value;
|
||||
return;
|
||||
}
|
||||
void emit_reserve(char* result, char* type_name, int size){
|
||||
emit_helper();
|
||||
return;
|
||||
|
||||
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(char* pointer){
|
||||
emit_helper();
|
||||
|
||||
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();
|
||||
return;
|
||||
}
|
||||
void emit_array_access(char* result, char* array, char* index, char* dimension){
|
||||
emit_helper();
|
||||
return;
|
||||
}
|
||||
void emit_bounds_check(char* index, char* size, char* error_label){
|
||||
emit_helper();
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// * Implement temp variable generator function that produces unique names (t1, t2, etc.)
|
||||
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;
|
||||
}
|
||||
|
||||
char * label_gen(){
|
||||
char * ret = calloc( 9, sizeof(*ret));
|
||||
sprintf(ret, "L_%d", label_count);
|
||||
*/
|
||||
int label_gen(){
|
||||
label_count++;
|
||||
return ret;
|
||||
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;
|
||||
}
|
@ -1,9 +1,16 @@
|
||||
// Track 1: Core Infrastructure & Basic Expressions
|
||||
// * Add Bison actions for arithmetic expressions:
|
||||
// - Addition: $$ = new_temp(); emit_binary_op($$, "ADD", $1, $3);
|
||||
// - Subtraction, multiplication, division, modulo
|
||||
#include "runner.h"
|
||||
/* Intermediate Code */
|
||||
/* The Translators - Spring 2025 */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "symbol_table.h"
|
||||
|
||||
// these are from page 364
|
||||
typedef enum {
|
||||
@ -22,16 +29,16 @@ typedef enum {
|
||||
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_LESSTHEN, // 6 rule 1 + 5
|
||||
E_EQUALTO, // 6 rule 1 + 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
|
||||
E_INDEX_COPY_LEFT, // 8
|
||||
E_ADDRESS_OF // 9
|
||||
/* for x = *y and *y = x we can just use index copy right and left with
|
||||
index 0*/
|
||||
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 {
|
||||
@ -70,41 +77,48 @@ typedef struct Instruction {
|
||||
Instruction* next;
|
||||
} Instruction;
|
||||
|
||||
extern Instruction * begin;
|
||||
extern Instruction * current;
|
||||
int temp_count = 0;
|
||||
int label_count = 0;
|
||||
bool code_gen = true;
|
||||
|
||||
|
||||
|
||||
TNodeOrConst * tn_or_const(Op op, void * tnc);
|
||||
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);
|
||||
// TODO: Find out what these are suposed to do. Guess is create an entry in
|
||||
// the list of instructions. Guess is that its suposed to ret a struct ptr
|
||||
|
||||
// * Implement integer/boolean/character specific operation handling
|
||||
// TODO: Find out what this means.
|
||||
|
||||
// * Create output function to write instructions to file with line formatting
|
||||
void emit_as_file(FILE * out_file, Instruction * instr_arr);
|
||||
|
||||
// * Implement instruction array storage for backpatching
|
||||
|
||||
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(int name);
|
||||
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(char* result, char* type_name, int size);
|
||||
void emit_release(char* pointer);
|
||||
|
||||
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(char* result, char* array, char* index, char* dimension);
|
||||
void emit_bounds_check(char* index, char* size, char* error_label);
|
||||
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;
|
34
src/lexicalStructure.h
Normal file
34
src/lexicalStructure.h
Normal file
@ -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; \
|
||||
}
|
@ -6,34 +6,7 @@
|
||||
%option yylineno
|
||||
|
||||
%{
|
||||
#include "../tmp/grammar.tab.h"
|
||||
#include "../src/symbol_table.h"
|
||||
#ifndef DEBUG
|
||||
#define DEBUG 0
|
||||
#endif
|
||||
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, 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 [^\*]|\*+[^\)\*]+
|
||||
@ -46,59 +19,59 @@ 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.tn = integ;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.tn = addr;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.tn = boo;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.tn = chara;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)/*words = strdup("integer")*/;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);char* token = strdup(yytext)/*yylval.tn = chara*/;yylval.letter = token[1];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);int k = strlen(yytext);yytext[k-1] = '\0';yylval.words = strdup(&yytext[1]);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.tn = boo;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.tn = boo;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.tn = addr;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); }
|
||||
|
114
src/runner.c
114
src/runner.c
@ -22,8 +22,7 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
else {
|
||||
if (is_alpha_file(argv[argc - 1], strlen(argv[argc - 1])) !=
|
||||
0) {
|
||||
if (is_alpha_file(argv[argc - 1], strlen(argv[argc - 1])) != 0) {
|
||||
fprintf(stderr, INVALID);
|
||||
return -1;
|
||||
} else {
|
||||
@ -109,6 +108,23 @@ int run(FILE *alpha) {
|
||||
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();
|
||||
|
||||
@ -120,12 +136,14 @@ int run(FILE *alpha) {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -134,12 +152,14 @@ int run(FILE *alpha) {
|
||||
}
|
||||
|
||||
if (ir_flag != NULL) {
|
||||
printf("Flag -ir is not implemented yet\n");
|
||||
printdebug("[-ir] Intermediate code is enabled.");
|
||||
emit_as_file(ir_flag, begin);
|
||||
fclose(ir_flag);
|
||||
}
|
||||
|
||||
if (cg_flag != NULL) {
|
||||
printf("Flag -cg is not implemented yet\n");
|
||||
printdebug("[-cg] Code generation is enabled.");
|
||||
generate();
|
||||
fclose(cg_flag);
|
||||
}
|
||||
|
||||
@ -226,3 +246,89 @@ int is_alpha_file(char *alpha, int file_len) {
|
||||
}
|
||||
return 0; // is alpha file
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
24
src/runner.h
24
src/runner.h
@ -1,6 +1,8 @@
|
||||
/* Runner File - Compiles alpha Compiler */
|
||||
/* The Translators - Spring 2025 */
|
||||
|
||||
#pragma once
|
||||
|
||||
#define ALPHA_OFFSET 6
|
||||
#define TOK_LEN 3
|
||||
#define ST_LEN 2
|
||||
@ -33,9 +35,12 @@
|
||||
|
||||
#include "../tmp/flex.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;
|
||||
extern bool DEBUG;
|
||||
@ -46,9 +51,9 @@ SymbolTable *cur;
|
||||
FILE *alpha_file;
|
||||
FILE *tok_flag = NULL;
|
||||
FILE *st_flag = NULL;
|
||||
FILE *asc_flag = NULL;
|
||||
FILE *ir_flag = NULL;
|
||||
FILE *cg_flag = NULL;
|
||||
FILE *asc_flag = NULL;
|
||||
bool tc_flag = false;
|
||||
bool DEBUG = false;
|
||||
int no_flag = 0;
|
||||
@ -64,6 +69,7 @@ TableNode *boo;
|
||||
TableNode *recprime;
|
||||
TableNode *funtypeprime;
|
||||
TableNode *undefined;
|
||||
extern Instruction *begin;
|
||||
|
||||
int main(int argc, char *argv[]);
|
||||
int check_flag(char *arg, char *alpha);
|
||||
@ -89,3 +95,17 @@ 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();
|
@ -78,8 +78,8 @@ Constant_Stack* Print_Stack(){
|
||||
}
|
||||
if (cs->theType == boo) {
|
||||
if (*(bool *)cs->theValue == true) {
|
||||
printf("Type: %s, Value: true\n", getName(cs->theType));}
|
||||
else{
|
||||
printf("Type: %s, Value: true\n", getName(cs->theType));
|
||||
} else {
|
||||
printf("Type: %s, Value: false\n", getName(cs->theType));
|
||||
}
|
||||
}
|
||||
@ -1143,9 +1143,7 @@ TableNode *look_up(SymbolTable *table, char *x) {
|
||||
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);
|
||||
void printline(FILE *file_ptr, bool b) {
|
||||
if (b) {
|
||||
fprintf(file_ptr, "oop\n");
|
||||
@ -1160,7 +1158,6 @@ void printline(FILE *file_ptr, bool b) {
|
||||
fprintf(file_ptr, "\n");
|
||||
}
|
||||
|
||||
void st_fprint(FILE *file_ptr, char *label1, int label2, int label3, char *label4, char *label5);
|
||||
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",
|
||||
|
@ -1,5 +1,11 @@
|
||||
/* Symbol Table */
|
||||
/* The Translators - Spring 2025 */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -7,9 +13,11 @@
|
||||
#define SIZE_INT 4
|
||||
#define SIZE_ADDR 8
|
||||
#define SIZE_CHAR 1
|
||||
#define SIZE_BOOL 4 //TODO: Ask Carl what this size should be
|
||||
#define SIZE_BOOL 1
|
||||
|
||||
struct TableNode;
|
||||
typedef struct TFList TFList;
|
||||
typedef struct CGNode CGNode;
|
||||
|
||||
typedef struct Constant_Stack {
|
||||
struct TableNode *theType;
|
||||
@ -57,7 +65,6 @@ typedef struct ListOfTable {
|
||||
struct ListOfTable *next;
|
||||
} ListOfTable;
|
||||
|
||||
//Table node to store
|
||||
typedef struct TableNode {
|
||||
struct TableNode *theType;
|
||||
int tag;
|
||||
@ -89,12 +96,23 @@ typedef enum {
|
||||
TYPE_PRIMITIVE_TYPE = 12
|
||||
} types;
|
||||
|
||||
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);
|
||||
@ -110,19 +128,21 @@ 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 *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 *getTypeEntry(TableNode *tn);
|
||||
TableNode *addName(TableNode *tn, char *str);
|
||||
SymbolTable *setLineNumber(SymbolTable *st, int line);
|
||||
SymbolTable *setColumnNumber(SymbolTable *st, int column);
|
||||
TableNode *table_lookup(SymbolTable *table, char *x);
|
||||
TableNode *look_up(SymbolTable *table, char *x);
|
||||
void 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);
|
||||
@ -133,11 +153,7 @@ SymbolTable *getFirstChild(ListOfTable *lt);
|
||||
ListOfTable *getRestOfChildren(ListOfTable *lt);
|
||||
TableNode *getFirstEntry(SymbolTable *st);
|
||||
TableNode *getNextEntry(TableNode *tn);
|
||||
|
||||
TableNode *printTableNode(TableNode *tn);
|
||||
void printdebug_impl(char *file, int line, const char *format, ...);
|
||||
#define printdebug(format, ...) \
|
||||
printdebug_impl(__FILE__, __LINE__, format, ##__VA_ARGS__)
|
||||
|
||||
extern int yylex(void);
|
||||
extern char *yytext;
|
||||
|
@ -1,3 +1,6 @@
|
||||
/* Type Definitions */
|
||||
/* The Translators - Spring 2025 */
|
||||
|
||||
// identifier
|
||||
#define ID 101
|
||||
// type names
|
||||
|
29
test.alpha
29
test.alpha
@ -1,29 +0,0 @@
|
||||
|
||||
|
||||
|
||||
type a : 1 -> integers
|
||||
type t : integer -> a
|
||||
type r : integer -> integer
|
||||
|
||||
|
||||
|
||||
function foo : t
|
||||
function bar : r
|
||||
function entry :
|
||||
|
||||
bar(a) := {
|
||||
5 + bar(a - 1);
|
||||
return a * bar(a-1);
|
||||
}
|
||||
|
||||
foo(c) := {
|
||||
[a: arg]
|
||||
arg := reserve arg(c);
|
||||
return arg;
|
||||
}
|
||||
|
||||
entry(args) := {
|
||||
[a: b]
|
||||
b := foo(8);
|
||||
}
|
||||
|
4
test.sh
4
test.sh
@ -84,7 +84,7 @@ if [ $# -eq 0 ]; then
|
||||
if [ -f "$file" ]; then
|
||||
filename=$(basename -- "$file")
|
||||
echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}"
|
||||
./alpha -st -debug "$file"
|
||||
./alpha -cg "$file"
|
||||
echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n${WHITE}"
|
||||
switchfunc
|
||||
fi
|
||||
@ -154,7 +154,7 @@ else
|
||||
if [[ "$file" == *"$1"* ]]; then
|
||||
filename=$(basename -- "$file")
|
||||
echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}"
|
||||
./alpha -st -debug "$file"
|
||||
./alpha -cg -debug "$file"
|
||||
echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n"
|
||||
switchfunc
|
||||
fi
|
||||
|
@ -1,34 +1,50 @@
|
||||
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
|
||||
------------------------------:--------:--------:-----------------------------------:-----------------------------------:
|
||||
b : 005000 : 001001 : Boolean : Primitive Instance
|
||||
x : 005000 : 001001 : integer : Primitive Instance
|
||||
arg : 005000 : 001001 : integer : Primitive Instance
|
||||
undefined : 005000 : 001001 : integer : Primitive Instance
|
||||
------------------------------:--------:--------:-----------------------------------:-----------------------------------:
|
||||
: 023009 : 005000 : : Empty Scope
|
||||
------------------------------:--------:--------:-----------------------------------:-----------------------------------:
|
||||
: 021014 : 005000 : : Empty Scope
|
||||
------------------------------:--------:--------:-----------------------------------:-----------------------------------:
|
||||
: 017009 : 005000 : : Empty Scope
|
||||
------------------------------:--------:--------:-----------------------------------:-----------------------------------:
|
||||
: 015017 : 005000 : : Empty Scope
|
||||
------------------------------:--------:--------:-----------------------------------:-----------------------------------:
|
||||
: 011012 : 005000 : : Empty Scope
|
||||
------------------------------:--------:--------:-----------------------------------:-----------------------------------:
|
||||
: 007015 : 005000 : : Empty Scope
|
||||
------------------------------:--------:--------:-----------------------------------:-----------------------------------:
|
||||
y : 001000 : 001001 : integer : Primitive Instance
|
||||
x : 001000 : 001001 : integer : Primitive Instance
|
||||
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: }
|
||||
|
@ -1,20 +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
|
||||
------------------------------:--------:--------:-----------------------------------:-----------------------------------:
|
||||
b1 : 004000 : 001001 : Boolean : Primitive Instance
|
||||
b2 : 004000 : 001001 : Boolean : Primitive Instance
|
||||
arr2 : 004000 : 001001 : address : Primitive Instance
|
||||
arr : 004000 : 001001 : address : Primitive Instance
|
||||
x : 004000 : 001001 : integer : Primitive Instance
|
||||
arg : 004000 : 001001 : string : Array Instance
|
||||
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: }
|
||||
|
@ -1,20 +1,13 @@
|
||||
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
|
||||
------------------------------:--------:--------:-----------------------------------:-----------------------------------:
|
||||
b1 : 004000 : 001001 : Boolean : Primitive Instance
|
||||
b2 : 004000 : 001001 : Boolean : Primitive Instance
|
||||
arr2 : 004000 : 001001 : address : Primitive Instance
|
||||
arr : 004000 : 001001 : address : Primitive Instance
|
||||
x : 004000 : 001001 : integer : Primitive Instance
|
||||
arg : 004000 : 001001 : string : Array Instance
|
||||
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: }
|
||||
|
@ -1,26 +1,25 @@
|
||||
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
|
||||
------------------------------:--------:--------:-----------------------------------:-----------------------------------:
|
||||
r : 006000 : 001001 : rec : Record Instance
|
||||
a : 006000 : 001001 : character : Primitive Instance
|
||||
b1 : 006000 : 001001 : Boolean : Primitive Instance
|
||||
b2 : 006000 : 001001 : Boolean : Primitive Instance
|
||||
arr2 : 006000 : 001001 : address : Primitive Instance
|
||||
arr : 006000 : 001001 : address : Primitive Instance
|
||||
x : 006000 : 001001 : integer : Primitive Instance
|
||||
arg : 006000 : 001001 : string : Array Instance
|
||||
------------------------------:--------:--------:-----------------------------------:-----------------------------------:
|
||||
y : 003000 : 001001 : integer : Primitive Instance
|
||||
x : 003000 : 001001 : integer : Primitive Instance
|
||||
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: }
|
||||
|
@ -1,20 +1,14 @@
|
||||
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
|
||||
------------------------------:--------:--------:-----------------------------------:-----------------------------------:
|
||||
b1 : 004000 : 001001 : Boolean : Primitive Instance
|
||||
b2 : 004000 : 001001 : Boolean : Primitive Instance
|
||||
arr2 : 004000 : 001001 : address : Primitive Instance
|
||||
arr : 004000 : 001001 : address : Primitive Instance
|
||||
x : 004000 : 001001 : integer : Primitive Instance
|
||||
arg : 004000 : 001001 : string : Array Instance
|
||||
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: }
|
||||
|
@ -6,12 +6,13 @@ type main: string -> integer
|
||||
function entry: main
|
||||
function bar: T2
|
||||
|
||||
bar2 (r,s) := {
|
||||
return r;
|
||||
bar (r,s) := {
|
||||
return 0;
|
||||
}
|
||||
|
||||
entry (arg) := {
|
||||
[ integer: result ; rec: w]
|
||||
result := bar(1,2);
|
||||
result := bar('c', 7);
|
||||
return 0;
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
type rec: [character: x; integer: y]
|
||||
|
||||
type T2: rec -> integer
|
||||
|
||||
type main: string -> integer
|
||||
function entry: main
|
||||
function bar: T2
|
||||
|
||||
bar2 (r,s) := {
|
||||
return s;
|
||||
}
|
||||
|
||||
entry (arg) := {
|
||||
[ integer: result ; rec: w]
|
||||
result := bar('c', 7);
|
||||
return 0;
|
||||
}
|
12
tests/sprint4/expected/sp4_cg_add.expected
Normal file
12
tests/sprint4/expected/sp4_cg_add.expected
Normal file
@ -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
|
20
tests/sprint4/expected/sp4_cg_and.expected
Normal file
20
tests/sprint4/expected/sp4_cg_and.expected
Normal file
@ -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
|
12
tests/sprint4/expected/sp4_cg_div.expected
Normal file
12
tests/sprint4/expected/sp4_cg_div.expected
Normal file
@ -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
|
13
tests/sprint4/expected/sp4_cg_equal_to.expected
Normal file
13
tests/sprint4/expected/sp4_cg_equal_to.expected
Normal file
@ -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
|
13
tests/sprint4/expected/sp4_cg_less_than.expected
Normal file
13
tests/sprint4/expected/sp4_cg_less_than.expected
Normal file
@ -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
|
12
tests/sprint4/expected/sp4_cg_mod.expected
Normal file
12
tests/sprint4/expected/sp4_cg_mod.expected
Normal file
@ -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
|
11
tests/sprint4/expected/sp4_cg_mult.expected
Normal file
11
tests/sprint4/expected/sp4_cg_mult.expected
Normal file
@ -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
|
8
tests/sprint4/expected/sp4_cg_neg.expected
Normal file
8
tests/sprint4/expected/sp4_cg_neg.expected
Normal file
@ -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
|
13
tests/sprint4/expected/sp4_cg_not.expected
Normal file
13
tests/sprint4/expected/sp4_cg_not.expected
Normal file
@ -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
|
21
tests/sprint4/expected/sp4_cg_or.expected
Normal file
21
tests/sprint4/expected/sp4_cg_or.expected
Normal file
@ -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
|
11
tests/sprint4/expected/sp4_cg_sub.expected
Normal file
11
tests/sprint4/expected/sp4_cg_sub.expected
Normal file
@ -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
|
10
tests/sprint4/test/sp4_cg_add.alpha
Normal file
10
tests/sprint4/test/sp4_cg_add.alpha
Normal file
@ -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;
|
||||
}
|
10
tests/sprint4/test/sp4_cg_and.alpha
Normal file
10
tests/sprint4/test/sp4_cg_and.alpha
Normal file
@ -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;
|
||||
}
|
10
tests/sprint4/test/sp4_cg_div.alpha
Normal file
10
tests/sprint4/test/sp4_cg_div.alpha
Normal file
@ -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;
|
||||
}
|
10
tests/sprint4/test/sp4_cg_equal_to.alpha
Normal file
10
tests/sprint4/test/sp4_cg_equal_to.alpha
Normal file
@ -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;
|
||||
}
|
10
tests/sprint4/test/sp4_cg_less_than.alpha
Normal file
10
tests/sprint4/test/sp4_cg_less_than.alpha
Normal file
@ -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;
|
||||
}
|
10
tests/sprint4/test/sp4_cg_mod.alpha
Normal file
10
tests/sprint4/test/sp4_cg_mod.alpha
Normal file
@ -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;
|
||||
}
|
10
tests/sprint4/test/sp4_cg_mult.alpha
Normal file
10
tests/sprint4/test/sp4_cg_mult.alpha
Normal file
@ -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;
|
||||
}
|
9
tests/sprint4/test/sp4_cg_neg.alpha
Normal file
9
tests/sprint4/test/sp4_cg_neg.alpha
Normal file
@ -0,0 +1,9 @@
|
||||
type main: integer -> integer
|
||||
function test: main
|
||||
|
||||
test (a) := {
|
||||
[integer:x; integer:y]
|
||||
x := 3;
|
||||
y := -x;
|
||||
return y;
|
||||
}
|
9
tests/sprint4/test/sp4_cg_not.alpha
Normal file
9
tests/sprint4/test/sp4_cg_not.alpha
Normal file
@ -0,0 +1,9 @@
|
||||
type main: integer -> integer
|
||||
function test: main
|
||||
|
||||
test (a) := {
|
||||
[Boolean: c; Boolean: d]
|
||||
c := true;
|
||||
d := !c;
|
||||
return 1;
|
||||
}
|
10
tests/sprint4/test/sp4_cg_or.alpha
Normal file
10
tests/sprint4/test/sp4_cg_or.alpha
Normal file
@ -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;
|
||||
}
|
10
tests/sprint4/test/sp4_cg_sub.alpha
Normal file
10
tests/sprint4/test/sp4_cg_sub.alpha
Normal file
@ -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;
|
||||
}
|
Reference in New Issue
Block a user