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:
scarlett
2025-04-26 20:18:37 -04:00
committed by GitHub
46 changed files with 2045 additions and 654 deletions

View File

@ -1,39 +1,74 @@
# ----- Definitions -----
CC := gcc CC := gcc
FLEX := flex FLEX := flex
BISON = bison
CFLAGS := -ggdb
BISONFLAGS := -d
LEX := src/lexicalStructure.lex LEX := src/lexicalStructure.lex
YACC := src/grammar.y
EXE := alpha 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-S1 := $(wildcard tests/sprint1/test/*.alpha)
TESTS-S2 := $(wildcard tests/sprint2/test/*.alpha) TESTS-S2 := $(wildcard tests/sprint2/test/*.alpha)
TESTS-S3 := $(wildcard tests/sprint3/test/*.alpha) TESTS-S3 := $(wildcard tests/sprint3/test/*.alpha)
TESTS-S4 := $(wildcard tests/sprint4/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 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) $(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 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 tmp/intermediate_code.o: src/intermediate_code.c src/intermediate_code.h
$(CC) $(CFLAGS) -o $(EXE) -g -ggdb tmp/runner.o tmp/grammar.tab.c tmp/lex.yy.c $(CC) $(CFLAGS) -c src/intermediate_code.c -o tmp/intermediate_code.o
debug: CFLAGS += -DDEBUG=1 tmp/codegen.o: src/codegen.c src/codegen.h
debug: clean compiler $(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: test:
chmod +x ./check.sh chmod +x ./check.sh
chmod +x ./test.sh chmod +x ./test.sh
@ -66,16 +101,4 @@ test-s4:
chmod +x ./test.sh chmod +x ./test.sh
./test.sh sp4 ./test.sh sp4
./check.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
View 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
View 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
View 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;

View File

@ -1,4 +1,3 @@
/* Syntax Analyzer with Bison (3.8.2) */ /* Syntax Analyzer with Bison (3.8.2) */
/* The Translators - Spring 2025 */ /* The Translators - Spring 2025 */
@ -17,13 +16,7 @@
// Please ask Scarlett if you are unsure of how to format something. Thanks! 😀 // Please ask Scarlett if you are unsure of how to format something. Thanks! 😀
%{ %{
#include "../src/symbol_table.c" #include "../src/grammar.h"
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, ...);
%} %}
%union { %union {
@ -113,6 +106,7 @@
program: program:
prototype_or_definition_list prototype_or_definition_list
| error { yyerrok; }
; ;
@ -122,12 +116,17 @@ prototype_or_definition_list:
| definition prototype_or_definition_list | definition prototype_or_definition_list
| prototype | prototype
| definition | definition
| error { yyerrok; }
; ;
prototype: 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"); printdebug("see function def rule 1\n");
TableNode *node = table_lookup(getAncestor(cur), $1); TableNode *node = table_lookup(getAncestor(cur), $1);
if (node == undefined) { if (node == undefined) {
error_type(undefined, undefined, "Undefined node declared."); printdebug("Undefined node declared.");
}else if(getAdInfoType(node) != TYPE_FUNCTION_DECLARATION){ }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 { else {
printdebug("setting as keyword to true"); printdebug("setting as keyword to true");
@ -188,7 +187,7 @@ definition:
//TableNode *parameter = getParameter(table_lookup(getAncestor(cur), getType(table_lookup(getAncestor(cur), $1)))); //TableNode *parameter = getParameter(table_lookup(getAncestor(cur), getType(table_lookup(getAncestor(cur), $1))));
printdebug("type of parameter: %s", getName(parameter)); printdebug("type of parameter: %s", getName(parameter));
if (parameter == undefined) { 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){ }else if(getAdInfoType(parameter) != TYPE_RECORD_TYPE){
int type_of_param_type = getAdInfoType(parameter);//this is an enum value defined in symbol_table.h int type_of_param_type = getAdInfoType(parameter);//this is an enum value defined in symbol_table.h
if( type_of_param_type == TYPE_UNDEFINED if( type_of_param_type == TYPE_UNDEFINED
@ -199,7 +198,7 @@ definition:
|| type_of_param_type == TYPE_SYSTEM_DEFINED || type_of_param_type == TYPE_SYSTEM_DEFINED
|| type_of_param_type == TYPE_RECORD || type_of_param_type == TYPE_RECORD
|| type_of_param_type == TYPE_STRING){ // note that strings are actually arrays so this is unused || 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 type_of_param_type = TYPE_UNDEFINED; // setting tag as undefined in these cases
} }
if(type_of_param_type == TYPE_UNDEFINED){ if(type_of_param_type == TYPE_UNDEFINED){
@ -227,7 +226,7 @@ definition:
|| type_of_param_type == TYPE_SYSTEM_DEFINED || type_of_param_type == TYPE_SYSTEM_DEFINED
|| type_of_param_type == TYPE_RECORD_TYPE || type_of_param_type == TYPE_RECORD_TYPE
|| type_of_param_type == TYPE_STRING){ // note that strings are actually arrays so this is unused || 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 type_of_param_type = TYPE_UNDEFINED; // setting tag as undefined in these cases
}else{ }else{
printdebug("type of parameter correctly being passed in to AS function definition is %s which is valid", getType(entry)); 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 { } idlist R_PAREN ASSIGN sblock {
TableNode *expected = getReturn(getTypeEntry(look_up(cur, $1))); TableNode *expected = getReturn(getTypeEntry(look_up(cur, $1)));
if ($8 == undefined) { 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) { } 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 { } else {
printdebug("CORRECT RETURN TYPE!!!"); printdebug("CORRECT RETURN TYPE!!!");
} }
@ -275,7 +274,7 @@ function_declaration:
CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $4), $2, CreateFunctionDeclarationInfo(-1, false)); CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $4), $2, CreateFunctionDeclarationInfo(-1, false));
} }
else{ 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)); 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)); CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $5), $3, CreateFunctionDeclarationInfo(-1, false));
} }
else{ 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)); 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("Type of entry is %s", getType(entry));
printdebug("tag is %d", getAdInfoType(entry)); printdebug("tag is %d", getAdInfoType(entry));
} }
| error { yyerrok; }
; ;
@ -398,6 +401,9 @@ sblock:
} }
R_BRACE R_BRACE
{$$ = $5;} {$$ = $5;}
| error { yyerrok; }
; ;
@ -415,13 +421,20 @@ dblock:
printdebug("Created a new scope when seeing a dblock"); printdebug("Created a new scope when seeing a dblock");
} }
} }
declaration_list R_BRACKET; declaration_list R_BRACKET
| error { yyerrok; }
;
declaration_list: declaration_list:
declaration SEMI_COLON declaration_list declaration SEMI_COLON declaration_list
| declaration | declaration
| error { yyerrok; }
; ;
@ -432,7 +445,8 @@ declaration:
printdebug("ID/TYPE: %s, ID: %s", getName((TableNode*)$1), $3) ; printdebug("ID/TYPE: %s, ID: %s", getName((TableNode*)$1), $3) ;
int d = getAdInfoType((TableNode*)$1); int d = getAdInfoType((TableNode*)$1);
if(d == TYPE_UNDEFINED) { 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)); CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1));
} }
else if(d == TYPE_FUNCTION_TYPE) { else if(d == TYPE_FUNCTION_TYPE) {
@ -455,10 +469,13 @@ declaration:
d = TYPE_PRIMITIVE; d = TYPE_PRIMITIVE;
CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1)); CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1));
}else { }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)); 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)); printdebug("string of type is %s in types pattern of id_or_type rule.",getName((TableNode*)$1));
$$ = (TableNode*)$1; $$ = (TableNode*)$1;
} }
| error { yyerrok; }
; ;
@ -510,6 +530,7 @@ compound_statement statement_list {
| simple_statement SEMI_COLON { | simple_statement SEMI_COLON {
$$ = $1; $$ = $1;
} }
; ;
@ -530,9 +551,11 @@ WHILE L_PAREN expression R_PAREN sblock {
$$ = undefined; $$ = undefined;
} }
} }
| sblock { | sblock {
$$ = $1; $$ = $1;
} }
; ;
@ -548,23 +571,26 @@ simple_statement:
node = ((TableNode*)$1); node = ((TableNode*)$1);
} else{ } else{
error_type(undefined, undefined, "Invalid type passed to assignable."); printdebug("Invalid type passed to assignable.");
node = undefined; node = undefined;
} }
if(getAdInfoType(node) == getAdInfoType((TableNode*)$3)){ 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)); printdebug("%s[☺] Passed type check; %s = %s", COLOR_GREEN, getName(node), getName((TableNode*)$3));
} else { } else {
error_type(node, (TableNode*)$3, ""); throw_error(ERROR_TYPE, "%s != %s", getName(node), getName((TableNode*)$3));
} }
$$ = undefined; $$ = undefined;
} }
| RETURN expression {$$ = getTypeEntry((TableNode*)$2);} | RETURN expression {$$ = getTypeEntry((TableNode*)$2);}
| error { yyerrok; }
; ;
@ -572,6 +598,9 @@ simple_statement:
rec_op: rec_op:
DOT DOT
| error { yyerrok; }
;
ablock: ablock:
@ -580,6 +609,9 @@ ablock:
$$ = $2; $$ = $2;
printdebug("ablock is %d", $$); printdebug("ablock is %d", $$);
} }
| error { yyerrok; }
; ;
@ -598,6 +630,9 @@ argument_list:
CreateEntry(cur,getAdInfoType((TableNode*)$1),(TableNode*)$1, getName((TableNode*)$1), NULL); CreateEntry(cur,getAdInfoType((TableNode*)$1),(TableNode*)$1, getName((TableNode*)$1), NULL);
$$ = 1; printdebug("[ARGUMENT_LIST] argument list is %d", $$); $$ = 1; printdebug("[ARGUMENT_LIST] argument list is %d", $$);
} }
| error { yyerrok; }
; ;
@ -615,12 +650,13 @@ expression:
if(getTypeEntry((TableNode*)$2) == integ) { if(getTypeEntry((TableNode*)$2) == integ) {
char* temp = temp_var_gen(); char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); 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) //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
//result of unary operation //result of unary operation
$$ = node; $$ = node;
} else { } else {
$$=undefined; $$=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) { if(getTypeEntry((TableNode*)$2) == boo) {
char* temp = temp_var_gen(); char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); 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) //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
//result of unary operation //result of unary operation
$$ = node; $$ = node;
} else { } else {
$$=undefined; $$=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) { if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) {
char* temp = temp_var_gen(); char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) emit_binary_op(E_ADD,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
//result of binary operation
$$ = node; $$ = node;
} else { } else {
$$=undefined; $$=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) { if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) {
char* temp = temp_var_gen(); char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) emit_binary_op(E_SUB,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
//result of binary operation
$$ = node; $$ = node;
} else { } else {
$$=undefined; $$=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) { if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) {
char* temp = temp_var_gen(); char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) emit_binary_op(E_MUL,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
//result of binary operation
$$ = node; $$ = node;
} else { } else {
$$=undefined; $$=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) { if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) {
char* temp = temp_var_gen(); char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) emit_binary_op(E_DIV,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
//result of binary operation
$$ = node; $$ = node;
} else { } else {
$$=undefined; $$=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) { if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) {
char* temp = temp_var_gen(); char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) emit_binary_op(E_MOD,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
//result of binary operation
$$ = node; $$ = node;
} else { } else {
$$=undefined; $$=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) { if((getTypeEntry((TableNode*)$1)==getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == boo) {
char* temp = temp_var_gen(); char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) emit_binary_op(E_AND,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
//result of comparison
$$ = node; $$ = node;
} else { } else {
$$=undefined; $$=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) { if((getTypeEntry((TableNode*)$1)==getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == boo) {
char* temp = temp_var_gen(); char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) emit_binary_op(E_OR,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
//result of comparison
$$ = node; $$ = node;
} else { } else {
$$=undefined; $$=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) { if(getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3) && getTypeEntry((TableNode*)$1)==integ) {
char* temp = temp_var_gen(); char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) emit_binary_op(E_LESS_THAN,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
//result of comparison
$$ = node; $$ = node;
} else { } else {
$$=undefined; $$=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) { if(getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3) && getTypeEntry((TableNode*)$1) != undefined) {
char* temp = temp_var_gen(); char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) emit_binary_op(E_EQUAL_TO,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
//result of compariosn
$$ = node; $$ = node;
} else { } else {
$$ = undefined; $$ = 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) //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
$$ = node; $$ = node;
} else { } else {
error_type(undefined, undefined, "Invalid memOp expression (%s).", getName((TableNode*)$2)); throw_error(ERROR_TYPE, "Invalid memOp expression (%s).", getName((TableNode*)$2));
$$=undefined; $$=undefined;
} }
} }
| error { yyerrok; }
; ;
//UPDATED $$ for tablenodes to this point //UPDATED $$ for tablenodes to this point
@ -811,6 +842,9 @@ assignable:
ID ID
{ {
TableNode* pass = look_up(cur,$1); TableNode* pass = look_up(cur,$1);
if(pass == undefined){
throw_error(ERROR_TYPE, "Undefined variable %s", $1);
}
$$ = pass; $$ = pass;
printdebug("[ASSIGNABLE - RULE 1] assignable = type: %s | ID = %s", getType(pass), getName(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)); 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"); printdebug("release expression");
} }
| error { yyerrok; }
; ;
@ -1005,7 +1043,7 @@ constant:
{ {
char* temp = temp_var_gen(); char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, stri, temp, NULL); 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); printdebug("string of C_STRING in constant is %s", $1);
$$ = node; $$ = node;
} }
@ -1014,7 +1052,7 @@ constant:
{ {
char* temp = temp_var_gen(); char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); 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); printdebug("number of C_INTEGER in constant is %d", $1);
$$ = node; $$ = node;
} }
@ -1023,7 +1061,7 @@ constant:
{ {
char* temp = temp_var_gen(); char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, addr, temp, NULL); 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"); printdebug("string of C_NULL in constant is NULL");
$$ = node; $$ = node;
} }
@ -1032,7 +1070,7 @@ constant:
{ {
char* temp = temp_var_gen(); char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, chara, temp, NULL); 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); printdebug("string of C_CHARACTER in constant is %s",$1);
$$ = node; $$ = node;
} }
@ -1041,7 +1079,8 @@ constant:
{ {
char* temp = temp_var_gen(); char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); 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"); printdebug("string of C_TRUE in constant is true");
$$ = node; $$ = node;
} }
@ -1050,7 +1089,8 @@ constant:
{ {
char* temp = temp_var_gen(); char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); 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"); printdebug("string of C_FALSE in constant is false");
$$ = node; $$ = node;
} }
@ -1083,43 +1123,81 @@ types:
$$ = $1; $$ = $1;
printdebug("string of T_BOOLEAN in types is %s",getName((TableNode*)$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 line = yylloc.first_line;
int column = yylloc.first_column; 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) { if (tc_flag) {
yyerror(""); insert_code_line(total_error_message, line);
if (strcmp(format, "") == 0) {
if (asc_flag != NULL) {
fprintf(asc_flag, "(%d:%d) ** TYPE ERROR: %s != %s\n", line, column, getName(left), getName(right));
} else { } else {
fprintf(stderr, "%s(%d:%d) ** TYPE ERROR%s: %s%s %s!= %s%s\n", if (error_type != ERROR_TYPE) {
COLOR_RED, line, column, COLOR_WHITE, COLOR_YELLOW, getName(left), COLOR_WHITE, COLOR_YELLOW, getName(right), COLOR_WHITE); insert_code_line(total_error_message, line);
}
} 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);
} }
} }
free(error_message);
free(error_message2);
free(total_error_message);
} }
} }
@ -1130,11 +1208,13 @@ void yyerror(const char *err) {
// Grammar Fallback Case // Grammar Fallback Case
if (strcmp(err, "syntax error") == 0) { if (strcmp(err, "syntax error") == 0) {
if (asc_flag != NULL) { 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 { else {
fprintf(stderr, "%s(%d:%d) ** SYNTAX ERROR%s: Incorrect syntax at token '%s%s%s'\n", fprintf(stderr, " LINE (%d:%d) ** SYNTAX ERROR: Incorrect syntax at token %s\n", line, column, yytext);
COLOR_RED, line, column, COLOR_WHITE, COLOR_YELLOW, yytext, COLOR_WHITE);
} }
} }
} }

View File

@ -1,19 +1,48 @@
#include <stdio.h> /* Intermediate Code */
/* The Translators - Spring 2025 */
#include "intermediate_code.h" #include "intermediate_code.h"
Instruction * begin;
Instruction * current;
char * temp = NULL;
// TODO: this is here to bring your attention to the comment bellow. // 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 // 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. // 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) {
TNodeOrConst * count = calloc(1, sizeof(*count)); return i->operand2;
count->d = op; }
switch (op) {
TableNode* getResult(Instruction* i) {
return i->result;
}
Op getOp(Instruction* i) {
return i->opcode;
}
int getLabel(Instruction* i) {
return i->label;
}
int get_index(Instruction* i) {
return i->index;
}
void set_label(Instruction* i, int label) {
i->label = label;
}
bool isConst(TNodeOrConst* tnc) {
return tnc->d != NODE;
}
TNodeOrConst* tn_or_const(Discriminant d, void* tnc) {
TNodeOrConst* count = calloc(1, sizeof(*count));
count->d = d;
count->tnc_union = calloc(1, sizeof(*count->tnc_union));
switch (d) {
case NODE: case NODE:
count->tnc_union->node = tnc; count->tnc_union->node = tnc;
break; break;
@ -30,74 +59,199 @@ TNodeOrConst * tn_or_const(Op op, void * tnc) {
count->tnc_union->character = *(char*)tnc; count->tnc_union->character = *(char*)tnc;
break; break;
case BOOLEAN: case BOOLEAN:
count->tnc_union->Boolean = *(bool*)tnc; count->tnc_union->Boolean = *(uint_least8_t*)tnc;
break; break;
} }
return count; return count;
} }
static void emit_helper(void){ static void emit_helper(void) {
Instruction * inst = calloc(1, sizeof(*inst)); Instruction* inst = calloc(1, sizeof(*inst));
if(begin == NULL){ if (begin == NULL) {
begin = current = inst; begin = current = inst;
current->index = 1; current->index = 1;
} else { } else {
current->next = inst; current->next = inst;
inst->prev = current; inst->prev = current;
inst->index = current->index++; inst->index = current->index + 1;
current = inst; current = inst;
} }
} }
void emit_binary_op(Op op, TableNode * result, TNodeOrConst * arg1, TNodeOrConst * arg2){ void emit_binary_op(Op op, TableNode* result, TNodeOrConst* arg1, TNodeOrConst* arg2) {
emit_helper(); emit_helper();
current->opcode = op; current->opcode = op;
// TODO: create temp and remove result from param list
current->result = result; current->result = result;
current->operand1 = arg1; current->operand1 = arg1;
current->operand2 = arg2; current->operand2 = arg2;
return; }
}
void emit_unary_op(Op op, TableNode * result, TNodeOrConst * arg){ void emit_unary_op(Op op, TableNode* result, TNodeOrConst* arg) {
emit_helper(); emit_helper();
current->opcode = op; current->opcode = op;
current->result = result; current->result = result;
current->operand1 = arg; current->operand1 = arg;
return;
}
void emit_assignment(TableNode * target, TNodeOrConst * source){
emit_helper();
current->opcode = E_ASSIGN; // TODO: replace with move
current->result = target;
current->operand1 = source;
return;
}
void emit_as_file(FILE * out_file, Instruction * instr_arr){
if(instr_arr == NULL){
return;
}
//fprintf(out_file,
return;
} }
void emit_assignment(TableNode* target, TNodeOrConst* source) {
emit_helper();
current->opcode = E_ASSIGN;
current->result = target;
current->operand1 = source;
}
void emit_label(int label){ char* get_string(TNodeOrConst* tc) {
char* s;
switch (tc->d) {
case NODE:
return getName(tc->tnc_union->node);
case ADDRESS:
return strdup("null");
case STRING:
return tc->tnc_union->string;
case INTEGER:
s = calloc(10, sizeof(char));
sprintf(s, "%d", tc->tnc_union->integer);
return s;
case CHARACTER:
s = calloc(2, sizeof(char));
sprintf(s, "%c", tc->tnc_union->character);
return s;
case BOOLEAN:
if (tc->tnc_union->Boolean) {
return strdup("true");
}
return strdup("false");
}
}
void emit_as_file(FILE* out_file, Instruction* i) {
if (i == NULL) {
return;
}
switch (i->opcode) {
case E_LABEL:
break;
// this is a terrible one to start with
// fprintf(out_file, "%04.d: %d ", i->index, i->label);
case E_ADD:
fprintf(out_file, "%4.d: %s = %s + %s\n",
i->index, getName(i->result),
get_string(i->operand1),
get_string(i->operand2));
break;
case E_SUB:
fprintf(out_file, "%4.d: %s = %s - %s\n",
i->index, getName(i->result),
get_string(i->operand1),
get_string(i->operand2));
break;
case E_MUL:
fprintf(out_file, "%4.d: %s = %s * %s\n",
i->index, getName(i->result),
get_string(i->operand1),
get_string(i->operand2));
break;
case E_DIV:
fprintf(out_file, "%4.d: %s = %s / %s\n",
i->index, getName(i->result),
get_string(i->operand1),
get_string(i->operand2));
break;
case E_MOD:
fprintf(out_file, "%4.d: %s = %s %% %s\n",
i->index, getName(i->result),
get_string(i->operand1),
get_string(i->operand2));
break;
case E_OR:
fprintf(out_file, "%4.d: %s = %s | %s\n",
i->index, getName(i->result),
get_string(i->operand1),
get_string(i->operand2));
break;
case E_AND:
fprintf(out_file, "%4.d: %s = %s & %s\n",
i->index, getName(i->result),
get_string(i->operand1),
get_string(i->operand2));
break;
case E_NEG:
fprintf(out_file, "%4.d: %s = -%s\n",
i->index, getName(i->result),
get_string(i->operand1));
break;
case E_NOT:
fprintf(out_file, "%4.d: %s = !%s\n",
i->index, getName(i->result),
get_string(i->operand1));
break;
case E_ASSIGN:
fprintf(out_file, "%4.d: %s = %s\n",
i->index, getName(i->result),
get_string(i->operand1));
break;
case E_GOTO:
// are we ever going to use this?
// yes we do look at bounds checking
case E_IF_X_TRUE:
fprintf(out_file, "%4.d: if %s goto %d\n",
i->index, get_string(i->operand1),
i->label);
break;
case E_IF_X_FALSE:
fprintf(out_file, "%4.d: if %s false goto %d\n",
i->index, get_string(i->operand1),
i->label);
break;
case E_LESS_THAN:
fprintf(out_file, "%4.d: if %s < %s goto %d\n",
i->index, get_string(i->operand1),
get_string(i->operand2), i->label);
break;
case E_EQUAL_TO:
fprintf(out_file, "%4.d: if %s = %s goto %d\n",
i->index, get_string(i->operand1),
get_string(i->operand2), i->label);
break;
case E_CALL:
fprintf(out_file, "%4.d: call %s %s\n",
i->index, get_string(i->operand1),
get_string(i->operand2));
break;
case E_PARAM:
fprintf(out_file, "%4.d: param %s \n",
i->index, get_string(i->operand1));
break;
case E_RETURN:
case E_INDEX_COPY_RIGHT:
case E_INDEX_COPY_LEFT:
case E_ADDRESS_OF:
case E_DEREF_RIGHT:
case E_DEREF_LEFT:
}
emit_as_file(out_file, i->next);
}
void emit_label(int label) {
emit_helper(); emit_helper();
current->opcode = E_LABEL; current->opcode = E_LABEL;
current->label = label; current->label = label;
return;
} }
void emit_jump(int label){
void emit_jump(int label) {
emit_helper(); emit_helper();
current->opcode = E_GOTO; current->opcode = E_GOTO;
current->label = label; current->label = label;
return;
} }
void emit_conditional_jump(Op condition, int label, ...){ void emit_conditional_jump(Op condition, int label, ...) {
// when this instruction is a conditional jump then the imput looks like (Op, int, TNodeOrConst *). // when this instruction is a conditional jump then the imput looks like (Op, int, TNodeOrConst *).
// when the inst is a cond with a Relational operation then the input looks like (Op, int, TNodeOrConst *, TNodeOrConst *) // when the inst is a cond with a Relational operation then the input looks like (Op, int, TNodeOrConst *, TNodeOrConst *)
emit_helper(); emit_helper();
@ -105,88 +259,142 @@ void emit_conditional_jump(Op condition, int label, ...){
va_start(argptr, label); va_start(argptr, label);
current->opcode = condition; current->opcode = condition;
current->label = label; current->label = label;
TNodeOrConst * n1; TNodeOrConst* n1;
TNodeOrConst * n2; TNodeOrConst* n2;
switch (condition) { switch (condition) {
case E_IF_X_TRUE: case E_IF_X_FALSE: case E_IF_X_TRUE:
n1 = va_arg(argptr, TNodeOrConst *); case E_IF_X_FALSE:
n1 = va_arg(argptr, TNodeOrConst*);
current->operand1 = n1; current->operand1 = n1;
break; break;
case E_LESSTHEN: case E_EQUALTO: case E_LESS_THAN:
n1 = va_arg(argptr, TNodeOrConst *); case E_EQUAL_TO:
n2 = va_arg(argptr, TNodeOrConst *); n1 = va_arg(argptr, TNodeOrConst*);
n2 = va_arg(argptr, TNodeOrConst*);
current->operand1 = n1; current->operand1 = n1;
current->operand2 = n2; current->operand2 = n2;
break; break;
} }
va_end(argptr); va_end(argptr);
return;
} }
void emit_function_start(int name){ void emit_function_start(TNodeOrConst * name) {
emit_helper(); emit_helper();
current->opcode = E_LABEL; // I think this is right TODO: ask current->opcode = E_LABEL; // I think this is right TODO: ask
current->label = name; current->operand1 = name;
// this is probabaly a func decleration // this is probabaly a func declaration
return;
} }
void emit_parameter(TNodeOrConst * param){ void emit_parameter(TNodeOrConst* param) {
emit_helper(); emit_helper();
current->opcode = E_PARAM; current->opcode = E_PARAM;
current->operand1 = param; current->operand1 = param;
return;
} }
void emit_function_call(TableNode * result, int param_count, TNodeOrConst * name){ void emit_function_call(TableNode* result, int param_count, TNodeOrConst* name) {
emit_helper(); emit_helper();
current->opcode = E_CALL; current->opcode = E_CALL;
current->operand1 = tn_or_const(INTEGER, &param_count); current->operand1 = tn_or_const(INTEGER, &param_count);
current->operand2 = name; current->operand2 = name;
current->result = result; current->result = result;
return;
} }
void emit_return(TNodeOrConst * value){
void emit_return(TNodeOrConst* value) {
emit_helper(); emit_helper();
current->opcode = E_RETURN; current->opcode = E_RETURN;
current->operand1 = value; current->operand1 = value;
return;
} }
void emit_reserve(char* result, char* type_name, int size){
emit_helper(); void emit_reserve(TableNode* result, TNodeOrConst* size) {
return; 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; return;
} }
void emit_deref_left() {
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; return;
} }
void emit_field_access(char* result, char* record, char* field) {
emit_helper();
}
// * Implement temp variable generator function that produces unique names (t1, t2, etc.) void emit_array_access(Op op, TableNode* result, TNodeOrConst* array, TNodeOrConst* index) {
emit_helper();
current->opcode;
current->result = result;
current->operand1 = array;
current->operand2 = index;
// TODO: Still don't know what to do with the dimentions
}
void emit_bounds_check(TNodeOrConst* index, TNodeOrConst* arr) {
/*
{[string: 5]
.
.
s:= reserve s(5);
s(0) := 'H';
s(1) := 'e';
.
.
s._0 num of dims Known at compile time
s._1 size Known at run time
s._1 int | 1 byte
+-------+---+---+---+---+---+
| 5 | H | e | l | l | o |
+-------+---+---+---+---+---+
size
^
|
p
s._0 ok
s._1 ok
s._2 not ok
t_0 is index
t_1 = *(int *)p = s._1
if t_0 < 0 GOTO ERROR
if t_0 < s._1 GOTO access array
GOTO ERROR
*/
//emit_conditional_jump(E_LESS_THAN, );
//emit_conditional_jump(E_LESS_THAN, );
//emit_jump();
/* We need a label ERROR to jump to
*/
}
/*// * Implement temp variable generator function that produces unique names (t1, t2, etc.)
char * temp_var_gen(){ char * temp_var_gen(){
char * ret = calloc(9, sizeof(*ret)); char * ret = calloc(9, sizeof(*ret));
sprintf(ret, "$t%d", temp_count); sprintf(ret, "$t%d", temp_count);
temp_count++; temp_count++;
return ret; return ret;
} }
*/
char * label_gen(){ int label_gen(){
char * ret = calloc( 9, sizeof(*ret));
sprintf(ret, "L_%d", label_count);
label_count++; 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;
} }

View File

@ -1,9 +1,16 @@
// Track 1: Core Infrastructure & Basic Expressions /* Intermediate Code */
// * Add Bison actions for arithmetic expressions: /* The Translators - Spring 2025 */
// - Addition: $$ = new_temp(); emit_binary_op($$, "ADD", $1, $3);
// - Subtraction, multiplication, division, modulo #pragma once
#include "runner.h"
#include <stdarg.h> #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 // these are from page 364
typedef enum { 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_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_TRUE, // 5
E_IF_X_FALSE, // 5 E_IF_X_FALSE, // 5
E_LESSTHEN, // 6 rule 1 + 5 E_LESS_THAN, // 6 rule 1 + 5
E_EQUALTO, // 6 rule 1 + 5 E_EQUAL_TO, // 6 rule 1 + 5
E_CALL, // 7 E_CALL, // 7
E_PARAM, // 7 E_PARAM, // 7
E_RETURN, // 7 E_RETURN, // 7
E_INDEX_COPY_RIGHT, // 8 E_INDEX_COPY_RIGHT, // 8 this is x = y[i]
E_INDEX_COPY_LEFT, // 8 E_INDEX_COPY_LEFT, // 8 x[i] = y
E_ADDRESS_OF // 9 E_ADDRESS_OF, // 9 x = &y
/* for x = *y and *y = x we can just use index copy right and left with E_DEREF_RIGHT, // 9 x = *y
index 0*/ E_DEREF_LEFT // 9 x* = y
} Op; } Op;
typedef enum { typedef enum {
@ -44,67 +51,74 @@ typedef enum {
} Discriminant; } Discriminant;
typedef union { typedef union {
TableNode * node; TableNode* node;
int integer; int integer;
char * string; char* string;
char character; char character;
void * address; void* address;
bool Boolean; bool Boolean;
} TNConstUnion; } TNConstUnion;
typedef struct { typedef struct {
Discriminant d; Discriminant d;
TNConstUnion * tnc_union; TNConstUnion* tnc_union;
} TNodeOrConst; } TNodeOrConst;
typedef struct Instruction Instruction; typedef struct Instruction Instruction;
typedef struct Instruction { typedef struct Instruction {
Op opcode; Op opcode;
TableNode * result; TableNode* result;
TNodeOrConst * operand1; TNodeOrConst* operand1;
TNodeOrConst * operand2; TNodeOrConst* operand2;
int label; int label;
int index; int index;
Instruction * prev; Instruction* prev;
Instruction * next; Instruction* next;
} Instruction; } Instruction;
extern Instruction * begin; typedef struct TFList {
extern Instruction * current; Instruction* i;
int temp_count = 0; TFList* next;
int label_count = 0; } TFList;
bool code_gen = true;
TNodeOrConst * tn_or_const(Op op, void * tnc);
void emit_binary_op(Op op, TableNode * result, TNodeOrConst * arg1, TNodeOrConst * arg2);
void emit_unary_op(Op op, TableNode * result, TNodeOrConst * arg);
void emit_assignment(TableNode * target, TNodeOrConst * source);
// 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
TNodeOrConst* getOperand1(Instruction* i);
TNodeOrConst* getOperand2(Instruction* i);
TableNode* getResult(Instruction* i);
Op getOp(Instruction* i);
int getLabel(Instruction* i);
int get_index(Instruction* i);
void set_label(Instruction* i, int label);
bool isConst(TNodeOrConst* tnc);
TNodeOrConst* tn_or_const(Discriminant d, void* tnc);
static void emit_helper(void);
void emit_binary_op(Op op, TableNode* result, TNodeOrConst* arg1, TNodeOrConst* arg2);
void emit_unary_op(Op op, TableNode* result, TNodeOrConst* arg);
void emit_assignment(TableNode* target, TNodeOrConst* source);
char* get_string(TNodeOrConst* tc);
void emit_as_file(FILE* out_file, Instruction* i);
void emit_label(int label); void emit_label(int label);
void emit_jump(int label); void emit_jump(int label);
void emit_conditional_jump(Op condition, int label, ...); void emit_conditional_jump(Op condition, int label, ...);
void emit_function_start(TNodeOrConst * name);
void emit_function_start(int name); void emit_parameter(TNodeOrConst* param);
void emit_parameter(TNodeOrConst * param); void emit_function_call(TableNode* result, int param_count, TNodeOrConst* name);
void emit_function_call(TableNode * result, int param_count, TNodeOrConst * name); void emit_return(TNodeOrConst* value);
void emit_return(TNodeOrConst * value); void emit_reserve(TableNode* result, TNodeOrConst* size);
void emit_reserve(char* result, char* type_name, int size); void emit_release(TableNode* pointer);
void emit_release(char* pointer); void emit_deref_right();
void emit_deref_left();
void emit_field_access(char* result, char* record, char* field); void emit_field_access(char* result, char* record, char* field);
void emit_array_access(char* result, char* array, char* index, char* dimension); void emit_array_access(Op op, TableNode* result, TNodeOrConst* array, TNodeOrConst* index);
void emit_bounds_check(char* index, char* size, char* error_label); 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
View 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; \
}

View File

@ -6,34 +6,7 @@
%option yylineno %option yylineno
%{ %{
#include "../tmp/grammar.tab.h" #include "../src/lexicalStructure.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; }
%} %}
STARCOM [^\*]|\*+[^\)\*]+ STARCOM [^\*]|\*+[^\)\*]+
@ -46,63 +19,63 @@ SCHAR \\n|\\t|\\\"|[^\"\n\\]
%% %%
"integer" {if(DEBUG) {printf( "T_INTEGER: %s (%d)\n", yytext, T_INTEGER);} else {if(tok_flag != NULL){print_tok(T_INTEGER);}incr(line_number,column_number,T_INTEGER);yylval.tn = integ;return T_INTEGER;}} "integer" { 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;}} "address" { 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;}} "Boolean" { 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;}} "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;}} "while" { 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;}} "if" { 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;}} "then" { 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;}} "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;}} "type" { 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;}} "function" { 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;}} "return" { 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;}} "external" { 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;}} "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;}} "release" { 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;}} "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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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;}} {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(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;}} '{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(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;}} \"{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(DEBUG) {printf( "COMMENT: %s (%d)\n", yytext, COMMENT);} else {if(tok_flag != NULL){print_tok(COMMENT);}incr(line_number,column_number,COMMENT);/*return COMMENT;*/}} {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(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(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(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(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(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(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;}} "true" { 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;}} "false" { 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;}} "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);} \n { yycolumn = 1; incr(line_number,column_number,0); }
\t {incr(line_number,column_number,0);} \t { incr(line_number,column_number,0); }
" " {incr(line_number,column_number,0);} " " { incr(line_number,column_number,0); }
. {incr(line_number,column_number,0);} . { incr(line_number,column_number,0); }
%% %%

View File

@ -22,8 +22,7 @@ int main(int argc, char *argv[]) {
} }
else { else {
if (is_alpha_file(argv[argc - 1], strlen(argv[argc - 1])) != if (is_alpha_file(argv[argc - 1], strlen(argv[argc - 1])) != 0) {
0) {
fprintf(stderr, INVALID); fprintf(stderr, INVALID);
return -1; return -1;
} else { } else {
@ -109,6 +108,23 @@ int run(FILE *alpha) {
fprintf(stderr, "INPUT FILE NOT FOUND\n"); fprintf(stderr, "INPUT FILE NOT FOUND\n");
return -1; 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; yyin = alpha;
yyparse(); yyparse();
@ -120,12 +136,14 @@ int run(FILE *alpha) {
} }
if (st_flag != NULL) { if (st_flag != NULL) {
printdebug("[-st] Symbol Table is enabled.");
print_symbol_table(top, st_flag); print_symbol_table(top, st_flag);
fclose(st_flag); fclose(st_flag);
} }
if (asc_flag != NULL) { if (asc_flag != NULL) {
printdebug("[-asc] Annotated Source Code is enabled."); printdebug("[-asc] Annotated Source Code is enabled.");
print_code_lines();
fclose(asc_flag); fclose(asc_flag);
} }
@ -134,12 +152,14 @@ int run(FILE *alpha) {
} }
if (ir_flag != NULL) { 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); fclose(ir_flag);
} }
if (cg_flag != NULL) { if (cg_flag != NULL) {
printf("Flag -cg is not implemented yet\n"); printdebug("[-cg] Code generation is enabled.");
generate();
fclose(cg_flag); fclose(cg_flag);
} }
@ -226,3 +246,89 @@ int is_alpha_file(char *alpha, int file_len) {
} }
return 0; // is alpha file 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;
}

View File

@ -1,6 +1,8 @@
/* Runner File - Compiles alpha Compiler */ /* Runner File - Compiles alpha Compiler */
/* The Translators - Spring 2025 */ /* The Translators - Spring 2025 */
#pragma once
#define ALPHA_OFFSET 6 #define ALPHA_OFFSET 6
#define TOK_LEN 3 #define TOK_LEN 3
#define ST_LEN 2 #define ST_LEN 2
@ -33,9 +35,12 @@
#include "../tmp/flex.h" #include "../tmp/flex.h"
#include "../tmp/grammar.tab.h" #include "../tmp/grammar.tab.h"
#include "codegen.h"
#include "intermediate_code.h"
#include "symbol_table.h" #include "symbol_table.h"
extern int line_number, column_number; extern int line_number;
extern int column_number;
extern char *yytext; extern char *yytext;
extern FILE *yyin; extern FILE *yyin;
extern bool DEBUG; extern bool DEBUG;
@ -46,9 +51,9 @@ SymbolTable *cur;
FILE *alpha_file; FILE *alpha_file;
FILE *tok_flag = NULL; FILE *tok_flag = NULL;
FILE *st_flag = NULL; FILE *st_flag = NULL;
FILE *asc_flag = NULL;
FILE *ir_flag = NULL; FILE *ir_flag = NULL;
FILE *cg_flag = NULL; FILE *cg_flag = NULL;
FILE *asc_flag = NULL;
bool tc_flag = false; bool tc_flag = false;
bool DEBUG = false; bool DEBUG = false;
int no_flag = 0; int no_flag = 0;
@ -64,6 +69,7 @@ TableNode *boo;
TableNode *recprime; TableNode *recprime;
TableNode *funtypeprime; TableNode *funtypeprime;
TableNode *undefined; TableNode *undefined;
extern Instruction *begin;
int main(int argc, char *argv[]); int main(int argc, char *argv[]);
int check_flag(char *arg, char *alpha); 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_LIGHTPURPLE = "\033[1;35m";
char *COLOR_LIGHTCYAN = "\033[1;36m"; char *COLOR_LIGHTCYAN = "\033[1;36m";
char *COLOR_WHITE = "\033[1;37m"; 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();

View File

@ -3,7 +3,7 @@
#include "symbol_table.h" #include "symbol_table.h"
Constant_Stack* head = NULL; Constant_Stack *head = NULL;
int temp2_count = 0; int temp2_count = 0;
void printdebug_impl(char *file, int line, const char *format, ...) { void printdebug_impl(char *file, int line, const char *format, ...) {
@ -18,8 +18,8 @@ void printdebug_impl(char *file, int line, const char *format, ...) {
} }
} }
char * temp_var_gen(){ char *temp_var_gen() {
char * ret = calloc(9, sizeof(*ret)); char *ret = calloc(9, sizeof(*ret));
sprintf(ret, "$t%d", temp2_count); sprintf(ret, "$t%d", temp2_count);
temp2_count++; temp2_count++;
return ret; return ret;
@ -36,10 +36,10 @@ Constant_Stack *Push(TableNode *type, void *value, bool isConst) {
cs->theType = type; cs->theType = type;
cs->theValue = value; cs->theValue = value;
cs->isConst = isConst; cs->isConst = isConst;
if(head == NULL){ if (head == NULL) {
head = cs; head = cs;
cs->next = NULL; cs->next = NULL;
}else{ } else {
cs->next = head; cs->next = head;
head = cs; head = cs;
} }
@ -57,36 +57,36 @@ Constant_Stack *Pop() {
return cs; return cs;
} }
Constant_Stack* Print_Stack(){ Constant_Stack *Print_Stack() {
if (head == NULL) { if (head == NULL) {
printdebug("cannot print an empty stack. Invalid."); printdebug("cannot print an empty stack. Invalid.");
return NULL; return NULL;
} }
Constant_Stack *cs = head; Constant_Stack *cs = head;
while (cs != NULL) { while (cs != NULL) {
if(cs->theValue == NULL){ if (cs->theValue == NULL) {
printf("Type: %s, Value: NULL", getName(cs->theType)); printf("Type: %s, Value: NULL", getName(cs->theType));
} }
if(cs->theType == stri){ if (cs->theType == stri) {
printf("Type: %s, Value: %s\n", getName(cs->theType), *(char*)(cs->theValue)); printf("Type: %s, Value: %s\n", getName(cs->theType), *(char *)(cs->theValue));
} }
if(cs->theType == integ){ if (cs->theType == integ) {
printf("Type: %s, Value: %d\n", getName(cs->theType), (int *)(cs->theValue)); printf("Type: %s, Value: %d\n", getName(cs->theType), (int *)(cs->theValue));
} }
if(cs->theType == chara){ if (cs->theType == chara) {
printf("Type: %s, Value: %c\n", getName(cs->theType), *(char *)cs->theValue); printf("Type: %s, Value: %c\n", getName(cs->theType), *(char *)cs->theValue);
} }
if(cs->theType == boo){ if (cs->theType == boo) {
if(*(bool *)cs->theValue == true){ if (*(bool *)cs->theValue == true) {
printf("Type: %s, Value: true\n", getName(cs->theType));} printf("Type: %s, Value: true\n", getName(cs->theType));
else{ } else {
printf("Type: %s, Value: false\n", getName(cs->theType)); printf("Type: %s, Value: false\n", getName(cs->theType));
} }
} }
cs = cs->next; cs = cs->next;
} }
return cs; return cs;
} }
// primitive additional info only stores the size of that type // primitive additional info only stores the size of that type
AdInfo *CreatePrimitiveInfo(int size) { AdInfo *CreatePrimitiveInfo(int size) {
@ -1143,9 +1143,7 @@ TableNode *look_up(SymbolTable *table, char *x) {
x, getLine(table), getColumn(table)); x, getLine(table), getColumn(table));
return look_up(table->Parent_Scope, x); return look_up(table->Parent_Scope, x);
} }
int col_widths[5] = {30, 8, 8, 35, 35}; int col_widths[5] = {30, 8, 8, 35, 35};
void printline(FILE *file_ptr, bool b);
void printline(FILE *file_ptr, bool b) { void printline(FILE *file_ptr, bool b) {
if (b) { if (b) {
fprintf(file_ptr, "oop\n"); fprintf(file_ptr, "oop\n");
@ -1160,7 +1158,6 @@ void printline(FILE *file_ptr, bool b) {
fprintf(file_ptr, "\n"); 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) { void st_fprint(FILE *file_ptr, char *label1, int label2, int label3, char *label4, char *label5) {
if (label3 == -100) { if (label3 == -100) {
fprintf(file_ptr, "%-*s: %0*d : %*s :%-*s:%-*s\n", fprintf(file_ptr, "%-*s: %0*d : %*s :%-*s:%-*s\n",

View File

@ -1,5 +1,11 @@
/* Symbol Table */
/* The Translators - Spring 2025 */
#pragma once
#include <stdarg.h> #include <stdarg.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -7,9 +13,11 @@
#define SIZE_INT 4 #define SIZE_INT 4
#define SIZE_ADDR 8 #define SIZE_ADDR 8
#define SIZE_CHAR 1 #define SIZE_CHAR 1
#define SIZE_BOOL 4 //TODO: Ask Carl what this size should be #define SIZE_BOOL 1
struct TableNode; struct TableNode;
typedef struct TFList TFList;
typedef struct CGNode CGNode;
typedef struct Constant_Stack { typedef struct Constant_Stack {
struct TableNode *theType; struct TableNode *theType;
@ -57,7 +65,6 @@ typedef struct ListOfTable {
struct ListOfTable *next; struct ListOfTable *next;
} ListOfTable; } ListOfTable;
//Table node to store
typedef struct TableNode { typedef struct TableNode {
struct TableNode *theType; struct TableNode *theType;
int tag; int tag;
@ -89,12 +96,23 @@ typedef enum {
TYPE_PRIMITIVE_TYPE = 12 TYPE_PRIMITIVE_TYPE = 12
} types; } 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); AdInfo *CreatePrimitiveInfo(int size);
int getPrimSize(TableNode *definition); int getPrimSize(TableNode *definition);
AdInfo *CreateArrayInfo(int dim, TableNode *type); AdInfo *CreateArrayInfo(int dim, TableNode *type);
int getNumArrDim(TableNode *definition); int getNumArrDim(TableNode *definition);
TableNode *getArrType(TableNode *definition); TableNode *getArrType(TableNode *definition);
AdInfo *CreateRecordInfo(int length, SymbolTable *recordScope); AdInfo *CreateRecordInfo(int length, SymbolTable *recordScope);
int getRecTotal(TableNode *node);
TableNode *setRecOffsetInfo(SymbolTable *scope, TableNode *node);
int *getRecOffsets(TableNode *node);
int getRecLength(TableNode *definition); int getRecLength(TableNode *definition);
SymbolTable *getRecList(TableNode *definition); SymbolTable *getRecList(TableNode *definition);
TableNode *setRecSize(TableNode *tn, int n); TableNode *setRecSize(TableNode *tn, int n);
@ -110,19 +128,21 @@ TableNode *getReturn(TableNode *definition);
SymbolTable *CreateScope(SymbolTable *ParentScope, int Line, int Column); SymbolTable *CreateScope(SymbolTable *ParentScope, int Line, int Column);
SymbolTable *init(SymbolTable *start); SymbolTable *init(SymbolTable *start);
TableNode *populateTypeAndInfo(TableNode *tn, TableNode *type, AdInfo *info); TableNode *populateTypeAndInfo(TableNode *tn, TableNode *type, AdInfo *info);
AdInfo *getAdInfo(TableNode *tn);
int getAdInfoType(TableNode *tn); int getAdInfoType(TableNode *tn);
TableNode *CreateEntry(SymbolTable *table, int tag, TableNode *typeOf, char *id, TableNode *CreateEntry(SymbolTable *table, int tag, TableNode *typeOf, char *id, AdInfo *ad);
AdInfo *ad); TableNode *getTypeEntry(TableNode *tn);
char *getType(TableNode *tn); char *getType(TableNode *tn);
char *getName(TableNode *tn); char *getName(TableNode *tn);
int getLine(SymbolTable *st); int getLine(SymbolTable *st);
int getColumn(SymbolTable *st); int getColumn(SymbolTable *st);
TableNode *getTypeEntry(TableNode *tn);
TableNode *addName(TableNode *tn, char *str); TableNode *addName(TableNode *tn, char *str);
SymbolTable *setLineNumber(SymbolTable *st, int line); SymbolTable *setLineNumber(SymbolTable *st, int line);
SymbolTable *setColumnNumber(SymbolTable *st, int column); SymbolTable *setColumnNumber(SymbolTable *st, int column);
TableNode *table_lookup(SymbolTable *table, char *x); TableNode *table_lookup(SymbolTable *table, char *x);
TableNode *look_up(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); void print_symbol_table(SymbolTable *table, FILE *file_ptr);
SymbolTable *getAncestor(SymbolTable *table); SymbolTable *getAncestor(SymbolTable *table);
SymbolTable *removeEntry(SymbolTable *scope, char *search); SymbolTable *removeEntry(SymbolTable *scope, char *search);
@ -133,11 +153,7 @@ SymbolTable *getFirstChild(ListOfTable *lt);
ListOfTable *getRestOfChildren(ListOfTable *lt); ListOfTable *getRestOfChildren(ListOfTable *lt);
TableNode *getFirstEntry(SymbolTable *st); TableNode *getFirstEntry(SymbolTable *st);
TableNode *getNextEntry(TableNode *tn); TableNode *getNextEntry(TableNode *tn);
TableNode *printTableNode(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 int yylex(void);
extern char *yytext; extern char *yytext;

View File

@ -1,3 +1,6 @@
/* Type Definitions */
/* The Translators - Spring 2025 */
// identifier // identifier
#define ID 101 #define ID 101
// type names // type names

View File

@ -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);
}

View File

@ -84,7 +84,7 @@ if [ $# -eq 0 ]; then
if [ -f "$file" ]; then if [ -f "$file" ]; then
filename=$(basename -- "$file") filename=$(basename -- "$file")
echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" 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}" echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n${WHITE}"
switchfunc switchfunc
fi fi
@ -154,7 +154,7 @@ else
if [[ "$file" == *"$1"* ]]; then if [[ "$file" == *"$1"* ]]; then
filename=$(basename -- "$file") filename=$(basename -- "$file")
echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" 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" echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n"
switchfunc switchfunc
fi fi

View File

@ -1,34 +1,50 @@
NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : 001: type rec: [integer: x; integer: y]
------------------------------:--------:--------:-----------------------------------:-----------------------------------: 002: type main: rec -> integer
test : 001001 : : undefined : Function Definition 003: function test: main
main : 001001 : : rec -> integer : Type of Function 004:
rec : 001001 : : Record Type : elements-2 size-8 bytes 005: test (arg) := {
integer : 001001 : : Primitive Type : size-4 bytes 006: [integer:x; Boolean: b]
address : 001001 : : Primitive Type : size-8 bytes 007: while (true) {
character : 001001 : : Primitive Type : size-1 bytes 008: x := 0;
string : 001001 : : 1 -> character : Type of Array 009: }
Boolean : 001001 : : Primitive Type : size-4 bytes 010:
reserve type : 001001 : : integer -> address : Type of Function 011: while (7) {
reserve : 001001 : : undefined : Function Definition 012: x := 1;
release type : 001001 : : address -> integer : Type of Function 013: }
release : 001001 : : undefined : Function Definition 014:
------------------------------:--------:--------:-----------------------------------:-----------------------------------: 015: if (true) then {
b : 005000 : 001001 : Boolean : Primitive Instance 016: x := 1;
x : 005000 : 001001 : integer : Primitive Instance 017: } else {
arg : 005000 : 001001 : integer : Primitive Instance 018: x := 0;
undefined : 005000 : 001001 : integer : Primitive Instance 019: }
------------------------------:--------:--------:-----------------------------------:-----------------------------------: 020:
: 023009 : 005000 : : Empty Scope 021: if (x) then {
------------------------------:--------:--------:-----------------------------------:-----------------------------------: 022: x := 0;
: 021014 : 005000 : : Empty Scope 023: } else {
------------------------------:--------:--------:-----------------------------------:-----------------------------------: 024: x := 1;
: 017009 : 005000 : : Empty Scope 025: }
------------------------------:--------:--------:-----------------------------------:-----------------------------------: 026:
: 015017 : 005000 : : Empty Scope 027: b := b | b;
------------------------------:--------:--------:-----------------------------------:-----------------------------------: 028: b := b & b;
: 011012 : 005000 : : Empty Scope 029: b := 1 | b;
------------------------------:--------:--------:-----------------------------------:-----------------------------------: LINE (29:12) ** TYPE ERROR: b != undefined
: 007015 : 005000 : : Empty Scope
------------------------------:--------:--------:-----------------------------------:-----------------------------------: 030: b := b | 1;
y : 001000 : 001001 : integer : Primitive Instance LINE (30:12) ** TYPE ERROR: b != undefined
x : 001000 : 001001 : integer : Primitive Instance
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: }

View File

@ -1,20 +1,16 @@
NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : 001: type main: string -> integer
------------------------------:--------:--------:-----------------------------------:-----------------------------------: 002: function entry: main
entry : 001001 : : undefined : Function Definition 003:
main : 001001 : : string -> integer : Type of Function 004: entry (arg) := {
integer : 001001 : : Primitive Type : size-4 bytes 005: [integer:x; address: arr; address: arr2; Boolean : b2; Boolean : b1]
address : 001001 : : Primitive Type : size-8 bytes 006:
character : 001001 : : Primitive Type : size-1 bytes 007: b2 := 3 < x;
string : 001001 : : 1 -> character : Type of Array 008: b1 := arr = 2;
Boolean : 001001 : : Primitive Type : size-4 bytes LINE (8:18) ** TYPE ERROR: b1 != undefined
reserve type : 001001 : : integer -> address : Type of Function
reserve : 001001 : : undefined : Function Definition 009: b1 := 6<7 & arr2=7;
release type : 001001 : : address -> integer : Type of Function LINE (9:23) ** TYPE ERROR: b1 != undefined
release : 001001 : : undefined : Function Definition
------------------------------:--------:--------:-----------------------------------:-----------------------------------: 010:
b1 : 004000 : 001001 : Boolean : Primitive Instance 011: return 0;
b2 : 004000 : 001001 : Boolean : Primitive Instance 012: }
arr2 : 004000 : 001001 : address : Primitive Instance
arr : 004000 : 001001 : address : Primitive Instance
x : 004000 : 001001 : integer : Primitive Instance
arg : 004000 : 001001 : string : Array Instance

View File

@ -1,20 +1,13 @@
NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : 001: type main: string -> integer
------------------------------:--------:--------:-----------------------------------:-----------------------------------: 002: function entry: main
entry : 001001 : : undefined : Function Definition 003:
main : 001001 : : string -> integer : Type of Function 004: entry (arg) := {
integer : 001001 : : Primitive Type : size-4 bytes 005: [integer:x; address: arr; address: arr2; Boolean : b2; Boolean : b1]
address : 001001 : : Primitive Type : size-8 bytes 006:
character : 001001 : : Primitive Type : size-1 bytes 007: b2 := !(3 < 2);
string : 001001 : : 1 -> character : Type of Array 008: b1 := !5;
Boolean : 001001 : : Primitive Type : size-4 bytes LINE (8:13) ** TYPE ERROR: b1 != undefined
reserve type : 001001 : : integer -> address : Type of Function
reserve : 001001 : : undefined : Function Definition 009:
release type : 001001 : : address -> integer : Type of Function 010: return 0;
release : 001001 : : undefined : Function Definition 011: }
------------------------------:--------:--------:-----------------------------------:-----------------------------------:
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

View File

@ -1,26 +1,25 @@
NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : 001: type main: string -> integer
------------------------------:--------:--------:-----------------------------------:-----------------------------------: 002:
entry : 001001 : : undefined : Function Definition 003: type rec: [integer: x; integer: y]
rec : 001001 : : Record Type : elements-2 size-8 bytes 004: function entry: main
main : 001001 : : string -> integer : Type of Function 005:
integer : 001001 : : Primitive Type : size-4 bytes 006: entry (arg) := {
address : 001001 : : Primitive Type : size-8 bytes 007: [integer:x; address: arr; address: arr2; Boolean : b2; Boolean : b1; character : a; rec : r]
character : 001001 : : Primitive Type : size-1 bytes 008:
string : 001001 : : 1 -> character : Type of Array 009: x := 3 + 2 * 8;
Boolean : 001001 : : Primitive Type : size-4 bytes 010: x := 3 - 2 / 8;
reserve type : 001001 : : integer -> address : Type of Function 011: x := a * 2 % 8;
reserve : 001001 : : undefined : Function Definition LINE (11:20) ** TYPE ERROR: x != undefined
release type : 001001 : : address -> integer : Type of Function
release : 001001 : : undefined : Function Definition 012: b2 := 3 * 2 % 8;
------------------------------:--------:--------:-----------------------------------:-----------------------------------: 013: x := 3 % 2 * 8;
r : 006000 : 001001 : rec : Record Instance 014: x := 3 + arr - 8;
a : 006000 : 001001 : character : Primitive Instance LINE (14:22) ** TYPE ERROR: x != undefined
b1 : 006000 : 001001 : Boolean : Primitive Instance
b2 : 006000 : 001001 : Boolean : Primitive Instance 015: x := r.x;
arr2 : 006000 : 001001 : address : Primitive Instance LINE (15:10) ** TYPE ERROR: x != r
arr : 006000 : 001001 : address : Primitive Instance
x : 006000 : 001001 : integer : Primitive Instance 016: x := a.x;
arg : 006000 : 001001 : string : Array Instance 017:
------------------------------:--------:--------:-----------------------------------:-----------------------------------: 018: return 0;
y : 003000 : 001001 : integer : Primitive Instance 019: }
x : 003000 : 001001 : integer : Primitive Instance

View File

@ -1,20 +1,14 @@
NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : 001: type main: string -> integer
------------------------------:--------:--------:-----------------------------------:-----------------------------------: 002: function entry: main
entry : 001001 : : undefined : Function Definition 003:
main : 001001 : : string -> integer : Type of Function 004: entry (arg) := {
integer : 001001 : : Primitive Type : size-4 bytes 005: [integer:x; address: arr; address: arr2; Boolean : b2; Boolean : b1]
address : 001001 : : Primitive Type : size-8 bytes 006:
character : 001001 : : Primitive Type : size-1 bytes 007: x := -8;
string : 001001 : : 1 -> character : Type of Array 008: x := -b1;
Boolean : 001001 : : Primitive Type : size-4 bytes LINE (8:10) ** TYPE ERROR: x != undefined
reserve type : 001001 : : integer -> address : Type of Function
reserve : 001001 : : undefined : Function Definition 009: b2 := -x;
release type : 001001 : : address -> integer : Type of Function 010:
release : 001001 : : undefined : Function Definition 011: return 0;
------------------------------:--------:--------:-----------------------------------:-----------------------------------: 012: }
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

View File

@ -6,12 +6,13 @@ type main: string -> integer
function entry: main function entry: main
function bar: T2 function bar: T2
bar2 (r,s) := { bar (r,s) := {
return r; return 0;
} }
entry (arg) := { entry (arg) := {
[ integer: result ; rec: w] [ integer: result ; rec: w]
result := bar(1,2);
result := bar('c', 7); result := bar('c', 7);
return 0; return 0;
} }

View File

@ -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;
}

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View File

@ -0,0 +1,9 @@
type main: integer -> integer
function test: main
test (a) := {
[integer:x; integer:y]
x := 3;
y := -x;
return y;
}

View File

@ -0,0 +1,9 @@
type main: integer -> integer
function test: main
test (a) := {
[Boolean: c; Boolean: d]
c := true;
d := !c;
return 1;
}

View 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;
}

View 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;
}