🤯🤯🤯🤯🤯🤯🤯🤯🤯
This commit is contained in:
44
genx.sh
44
genx.sh
@ -44,17 +44,57 @@ if [ ! -d "binaries" ]; then
|
|||||||
mkdir -p binaries
|
mkdir -p binaries
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
appendStd() {
|
||||||
|
if [ ! -f "$1" ]; then
|
||||||
|
echo "File not found: $1"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
backup_file="${1}.bak"
|
||||||
|
cp "$1" "$backup_file"
|
||||||
|
|
||||||
|
temp_file=$(mktemp)
|
||||||
|
|
||||||
|
while IFS= read -r line || [ -n "$line" ]; do
|
||||||
|
echo "$line" >> "$temp_file"
|
||||||
|
if [[ $line =~ ^#include\ \"[^\"]+\" ]]; then
|
||||||
|
include_file=$(echo "$line" | sed -n 's/.*"\([^"]*\)".*/\1/p')
|
||||||
|
if [[ $include_file == "std.alpha" ]]; then
|
||||||
|
echo -e "${GREEN}[GenX] ${WHITE}Including ${BLUE}std.alpha${WHITE}..."
|
||||||
|
if [ -f "library/std.alpha" ]; then
|
||||||
|
cat library/std.alpha >> "$temp_file"
|
||||||
|
else
|
||||||
|
echo -e "${RED}[GenX] ${YELLOW}File library/std.alpha not found!${WHITE}"
|
||||||
|
rm "$temp_file"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done < "$1"
|
||||||
|
|
||||||
|
mv "$temp_file" "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if [ $# -eq 1 ]; then
|
if [ $# -eq 1 ]; then
|
||||||
if [ -f "$1" ]; then
|
if [ -f "$1" ]; then
|
||||||
if [[ "$1" == *.alpha ]]; then
|
if [[ "$1" == *.alpha ]]; then
|
||||||
|
appendStd "$1"
|
||||||
./alpha -cg "$1"
|
./alpha -cg "$1"
|
||||||
|
backup_file="${1}.bak"
|
||||||
|
if [ -f "$backup_file" ]; then
|
||||||
|
mv "$backup_file" "$1"
|
||||||
|
echo -e "${GREEN}[GenX] ${WHITE}Reverted $1 to its original state."
|
||||||
|
fi
|
||||||
|
|
||||||
filename=$(basename -- "$1")
|
filename=$(basename -- "$1")
|
||||||
filename="${filename:0:${#filename}-6}"
|
filename="${filename:0:${#filename}-6}"
|
||||||
s_name="out/${filename}.s"
|
s_name="out/${filename}.s"
|
||||||
echo -e "${GREEN}[GenX] ${WHITE}Generated .s file..."
|
echo -e "${GREEN}[GenX] ${WHITE}Generated .s file."
|
||||||
gcc ${s_name} library/alpha_lib_reg.s library/alpha_driver.s -no-pie -o binaries/${filename}
|
gcc ${s_name} library/alpha_lib_reg.s library/alpha_driver.s -no-pie -o binaries/${filename}
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo -e "${GREEN}[GenX] ${WHITE}Generated executable file..."
|
echo -e "${GREEN}[GenX] ${WHITE}Generated executable file."
|
||||||
echo -e "${GREEN}[GenX] ${WHITE}Executable file: binaries/${filename}"
|
echo -e "${GREEN}[GenX] ${WHITE}Executable file: binaries/${filename}"
|
||||||
echo -e "${GREEN}[GenX] ${WHITE}Done!"
|
echo -e "${GREEN}[GenX] ${WHITE}Done!"
|
||||||
else
|
else
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
# Makefile to make executables from alpha source code files
|
|
||||||
# and also make executables from some sample assembly files execising the alpha library
|
|
||||||
#
|
|
||||||
# Carl Alphonce
|
|
||||||
# April 20, 2024
|
|
||||||
|
|
||||||
# The alpha compiler and flags (adjust the flags as needed)
|
|
||||||
AC := ./alpha
|
|
||||||
AFLAGS := -tok -asc -tc -st -ir -cg
|
|
||||||
|
|
||||||
# The preprocessor and flags (you should not adjust these)
|
|
||||||
CPP := cpp
|
|
||||||
CPPFLAGS := -P -x c
|
|
||||||
|
|
||||||
# Adjust for the library your team is using (register-based or stack-based parameter passing)
|
|
||||||
|
|
||||||
ALPHA_LIB = alpha_lib_reg.s ## Register-based parameter passing
|
|
||||||
#ALPHA_LIB = alpha_lib_st.s ## Stack-based parameter passing
|
|
||||||
|
|
||||||
# Adjust for the parameter passing approach your compiler uses:
|
|
||||||
# alpha_driver_reg.s for register-based parameter passing
|
|
||||||
# alpha_driver_st.s for stack-based parameter passing
|
|
||||||
# This file provides a main function that packages up argv[1] (or "") as an alpha string
|
|
||||||
# (type 1->character) and calls entry with that argument
|
|
||||||
|
|
||||||
ALPHA_DRIVER = alpha_driver_reg.s ## Register-based parameter passing
|
|
||||||
#ALPHA_DRIVER = alpha_driver_st.s ## Stack-based parameter passing
|
|
||||||
|
|
||||||
|
|
||||||
# Create an assembly (.s) file from an alpha source file
|
|
||||||
# This involves several steps:
|
|
||||||
%.s : %.alpha
|
|
||||||
@mv $< $<._temporary_ # 1. rename input file so we can us it as
|
|
||||||
@$(CPP) $(CPPFLAGS) $<._temporary_ > $< # 2. input to CPP, writing output to original filename
|
|
||||||
@$(AC) $(AFLAGS) $< # 3. run the alpha compiler on the pre-processed file
|
|
||||||
@mv $<._temporary_ $< # 4. restore the original input file
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Examples of assembly code using the alpha library files
|
|
||||||
# In these examples the calling code is in assembly, and defines main (so the driver is not included here)
|
|
||||||
|
|
||||||
# Example #1: calling the printBoolean function
|
|
||||||
printBoolean : printBoolean_reg.s
|
|
||||||
@gcc $< $(ALPHA_LIB) -no-pie -o $@
|
|
||||||
|
|
||||||
# Example #2: calling the printInt function
|
|
||||||
printInt : printInt_reg.s
|
|
||||||
@gcc $< $(ALPHA_LIB) -no-pie -o $@
|
|
||||||
|
|
||||||
# Example #3: calling the reserve and release functions
|
|
||||||
reserve_release : reserve_release_reg.s
|
|
||||||
@gcc $< $(ALPHA_LIB) -no-pie -o $@
|
|
||||||
|
|
||||||
|
|
||||||
# The rule for assembling .s files and linking them together (using the gcc compiler driver)
|
|
||||||
# to produce an executable (assuming no earlier make rule triggers first)
|
|
||||||
|
|
||||||
% : %.s $(ALPHA_LIB) $(ALPHA_DRIVER)
|
|
||||||
@gcc $< $(ALPHA_LIB) $(ALPHA_DRIVER) -no-pie -o $@
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
|||||||
.file "printBoolean.c"
|
|
||||||
.text
|
|
||||||
.globl main
|
|
||||||
.type main, @function
|
|
||||||
main:
|
|
||||||
.LFB0:
|
|
||||||
pushq %rbp
|
|
||||||
movq %rsp, %rbp
|
|
||||||
|
|
||||||
movb $1, %dil # the representation of 'true'
|
|
||||||
call printBoolean
|
|
||||||
movb $10, %dil
|
|
||||||
call printCharacter
|
|
||||||
|
|
||||||
movb $0, %dil # the representation of 'false'
|
|
||||||
call printBoolean
|
|
||||||
movb $10, %dil
|
|
||||||
call printCharacter
|
|
||||||
|
|
||||||
movl $0, %eax
|
|
||||||
popq %rbp
|
|
||||||
ret
|
|
||||||
.LFE0:
|
|
||||||
.size main, .-main
|
|
||||||
.ident "GCC: (GNU) 6.4.0"
|
|
||||||
.section .note.GNU-stack,"",@progbits
|
|
@ -1,22 +0,0 @@
|
|||||||
.file "printInt.c"
|
|
||||||
.text
|
|
||||||
.globl main
|
|
||||||
.type main, @function
|
|
||||||
main:
|
|
||||||
.LFB0:
|
|
||||||
pushq %rbp
|
|
||||||
movq %rsp, %rbp
|
|
||||||
|
|
||||||
movl $10, %edi # Move the immediate value 10 to %edi
|
|
||||||
call printInteger # call the alpha_lib function printInteger
|
|
||||||
|
|
||||||
movl $10, %edi # Put the \n character (decimal 10) into %edi
|
|
||||||
call printCharacter # then call the alpha_lib function printCharacter
|
|
||||||
|
|
||||||
movl $0, %eax
|
|
||||||
popq %rbp
|
|
||||||
ret
|
|
||||||
.LFE0:
|
|
||||||
.size main, .-main
|
|
||||||
.ident "GCC: (GNU) 6.4.0"
|
|
||||||
.section .note.GNU-stack,"",@progbits
|
|
@ -1,37 +0,0 @@
|
|||||||
.file "reserve_release.c"
|
|
||||||
.text
|
|
||||||
.globl main
|
|
||||||
.type main, @function
|
|
||||||
main:
|
|
||||||
.LFB0:
|
|
||||||
pushq %rbp
|
|
||||||
movq %rsp, %rbp
|
|
||||||
subq $16, %rsp
|
|
||||||
|
|
||||||
movl $8, %edi # move sizeof(*a) into %edi
|
|
||||||
call reserve # call alpha_lib_reg function reserve
|
|
||||||
|
|
||||||
movq %rax, -8(%rbp) # put the returned pointer on the stack at offset -8
|
|
||||||
|
|
||||||
movq -8(%rbp), %rax # put base pointer of struct (a) into %rax
|
|
||||||
movl $20, (%rax) # put value 20 into location pointed at by %rax --> (*a).x
|
|
||||||
movq -8(%rbp), %rax # put base pointer of struct (a) into %rax
|
|
||||||
movl $45, 4(%rax) # put value 45 into location 4(%rax) --> (*a).y
|
|
||||||
movq -8(%rbp), %rax # put base pointer of struct (a) into %rax
|
|
||||||
movl 4(%rax), %eax # move (*a).y into %eax
|
|
||||||
movl %eax, %edi # and then into %edi
|
|
||||||
call printInteger # call alpha_lib_reg function printInteger
|
|
||||||
movl $10, %edi # move '\n' into %edi
|
|
||||||
call printCharacter # call alpha_lib_reg function printCharacter
|
|
||||||
|
|
||||||
movq -8(%rbp), %rax # put base pointer of struct (a) into %rax
|
|
||||||
movq %rax, %rdi # and then into %rdi
|
|
||||||
call release # call alpha_lib_reg function reserve
|
|
||||||
|
|
||||||
movl $0, %eax
|
|
||||||
leave
|
|
||||||
ret
|
|
||||||
.LFE0:
|
|
||||||
.size main, .-main
|
|
||||||
.ident "GCC: (GNU) 6.4.0"
|
|
||||||
.section .note.GNU-stack,"",@progbits
|
|
24
library/std.alpha
Normal file
24
library/std.alpha
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
(* Standard Alpha Library - Provided by Carl *)
|
||||||
|
|
||||||
|
type string: 1 -> character
|
||||||
|
type BooleanXBoolean: [Boolean: x; Boolean: y]
|
||||||
|
type characterXcharacter: [character: x; character: y]
|
||||||
|
type integerXinteger: [integer: x; integer: y]
|
||||||
|
|
||||||
|
type Boolean2Boolean: Boolean -> Boolean
|
||||||
|
type integer2integer: integer -> integer
|
||||||
|
type character2integer: character -> integer
|
||||||
|
type Boolean2integer: Boolean -> integer
|
||||||
|
type string2integer: string -> integer
|
||||||
|
type integerXinteger2integer: integerXinteger -> integer
|
||||||
|
type integerXinteger2Boolean: integerXinteger -> Boolean
|
||||||
|
type characterXcharacter2Boolean: characterXcharacter -> Boolean
|
||||||
|
type BooleanXBoolean2Boolean: BooleanXBoolean -> Boolean
|
||||||
|
type integer2address: integer -> address
|
||||||
|
type address2integer: address -> integer
|
||||||
|
|
||||||
|
external function printInteger: integer2integer
|
||||||
|
external function printCharacter: character2integer
|
||||||
|
external function printBoolean: Boolean2integer
|
||||||
|
|
||||||
|
function entry: string2integer
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "codegen.h"
|
#include "codegen.h"
|
||||||
|
|
||||||
int generate(){
|
int generate() {
|
||||||
offset = 0;
|
offset = 0;
|
||||||
currentsp = 0;
|
currentsp = 0;
|
||||||
Instruction *i = begin;
|
Instruction *i = begin;
|
||||||
@ -12,7 +12,7 @@ int generate(){
|
|||||||
fprintf(cg_flag, ".globl entry\n");
|
fprintf(cg_flag, ".globl entry\n");
|
||||||
|
|
||||||
while (i != NULL) {
|
while (i != NULL) {
|
||||||
switch(getOp(i)) {
|
switch (getOp(i)) {
|
||||||
case E_LABEL:
|
case E_LABEL:
|
||||||
generateLabel(i);
|
generateLabel(i);
|
||||||
break;
|
break;
|
||||||
@ -82,8 +82,7 @@ int generate(){
|
|||||||
case E_FUNC_START:
|
case E_FUNC_START:
|
||||||
generateFunctionStart(i);
|
generateFunctionStart(i);
|
||||||
break;
|
break;
|
||||||
default:
|
default:;
|
||||||
;
|
|
||||||
}
|
}
|
||||||
i = i->next;
|
i = i->next;
|
||||||
}
|
}
|
||||||
@ -133,7 +132,6 @@ CGNode *addCG(TableNode *tn, int sp) {
|
|||||||
return cg;
|
return cg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int generateLabel(Instruction *inst) {
|
int generateLabel(Instruction *inst) {
|
||||||
if (inst == NULL) {
|
if (inst == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -162,7 +160,6 @@ int generateAdd(Instruction *inst) {
|
|||||||
cg = addCG(getResult(inst), offset);
|
cg = addCG(getResult(inst), offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CGNode *op1CG = findCG(getTN(op1));
|
CGNode *op1CG = findCG(getTN(op1));
|
||||||
CGNode *op2CG = findCG(getTN(op2));
|
CGNode *op2CG = findCG(getTN(op2));
|
||||||
if (op1CG == NULL) {
|
if (op1CG == NULL) {
|
||||||
@ -217,7 +214,7 @@ int generateSub(Instruction *instruction) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int generateMult(Instruction *inst){
|
int generateMult(Instruction *inst) {
|
||||||
/*
|
/*
|
||||||
Both immediate:
|
Both immediate:
|
||||||
One immediate:
|
One immediate:
|
||||||
@ -286,7 +283,7 @@ int generateDiv(Instruction *inst) {
|
|||||||
|
|
||||||
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#division start\n", getAddress(op1CG)); //moves dividend into eax
|
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, "\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, "\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
|
fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\t#division end\n", getAddress(cg)); //stores result
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -323,7 +320,7 @@ int generateMod(Instruction *inst) {
|
|||||||
|
|
||||||
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#mod start\n", getAddress(op1CG)); //moves dividend into eax
|
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, "\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, "\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)
|
fprintf(cg_flag, "\tmovl\t%%edx, %d(%%rbp)\t#mod end\n", getAddress(cg)); //stores result from edx (remainder)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -486,7 +483,6 @@ int generateAssign(Instruction *inst) {
|
|||||||
TNodeOrConst *op1 = getOperand1(inst);
|
TNodeOrConst *op1 = getOperand1(inst);
|
||||||
CGNode *cg = findCG(getResult(inst));
|
CGNode *cg = findCG(getResult(inst));
|
||||||
|
|
||||||
|
|
||||||
if (op1 == NULL) {
|
if (op1 == NULL) {
|
||||||
printdebug("generateAssign failed, NULL operand");
|
printdebug("generateAssign failed, NULL operand");
|
||||||
return -1;
|
return -1;
|
||||||
@ -514,7 +510,7 @@ int generateAssign(Instruction *inst) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int generateGoto(Instruction *inst){
|
int generateGoto(Instruction *inst) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -522,16 +518,16 @@ int generateCondGoto(Instruction *inst) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int generateIfTrue(Instruction *inst){
|
int generateIfTrue(Instruction *inst) {
|
||||||
return -1;
|
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
|
// 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 *inst){
|
int generateIfFalse(Instruction *inst) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int generateLessThan(Instruction *inst){
|
int generateLessThan(Instruction *inst) {
|
||||||
/*
|
/*
|
||||||
Both immediate:
|
Both immediate:
|
||||||
One immediate:
|
One immediate:
|
||||||
@ -569,7 +565,7 @@ int generateLessThan(Instruction *inst){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int generateEqualTo(Instruction *inst){
|
int generateEqualTo(Instruction *inst) {
|
||||||
/*
|
/*
|
||||||
Both immediate:
|
Both immediate:
|
||||||
One immediate:
|
One immediate:
|
||||||
@ -606,8 +602,7 @@ int generateEqualTo(Instruction *inst){
|
|||||||
fprintf(cg_flag, "\tmovb\t%%al, %d(%%rbp)\t#equal to end\n", getAddress(cg));
|
fprintf(cg_flag, "\tmovb\t%%al, %d(%%rbp)\t#equal to end\n", getAddress(cg));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int generateCall(Instruction *inst){
|
int generateCall(Instruction *inst) {
|
||||||
|
|
||||||
TNodeOrConst *op1 = getOperand1(inst);
|
TNodeOrConst *op1 = getOperand1(inst);
|
||||||
TNodeOrConst *op2 = getOperand2(inst);
|
TNodeOrConst *op2 = getOperand2(inst);
|
||||||
if (op1 == NULL) {
|
if (op1 == NULL) {
|
||||||
@ -630,7 +625,6 @@ int generateCall(Instruction *inst){
|
|||||||
// return -1;
|
// return -1;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
|
||||||
fprintf(cg_flag, "\tcall %s\n", getName(getTN(op1)));
|
fprintf(cg_flag, "\tcall %s\n", getName(getTN(op1)));
|
||||||
|
|
||||||
//now for the return
|
//now for the return
|
||||||
@ -643,13 +637,11 @@ int generateCall(Instruction *inst){
|
|||||||
fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\t#store return from call\n", getAddress(cg));
|
fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\t#store return from call\n", getAddress(cg));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
int generateReturn(Instruction *inst){
|
int generateReturn(Instruction *inst) {
|
||||||
TNodeOrConst *op1 = getOperand1(inst);
|
TNodeOrConst *op1 = getOperand1(inst);
|
||||||
CGNode *cg;
|
CGNode *cg;
|
||||||
|
|
||||||
|
|
||||||
if (op1 == NULL) {
|
if (op1 == NULL) {
|
||||||
printdebug("generateReturn failed, NULL operand");
|
printdebug("generateReturn failed, NULL operand");
|
||||||
return -1;
|
return -1;
|
||||||
@ -666,17 +658,17 @@ int generateReturn(Instruction *inst){
|
|||||||
fprintf(cg_flag, "\tret\n");
|
fprintf(cg_flag, "\tret\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int generateCopyRight(Instruction *inst){
|
int generateCopyRight(Instruction *inst) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int generateCopyLeft(Instruction *inst){
|
int generateCopyLeft(Instruction *inst) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int generateAddressOf(Instruction *inst){
|
int generateAddressOf(Instruction *inst) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int generateParam(Instruction *inst){
|
int generateParam(Instruction *inst) {
|
||||||
TNodeOrConst *op1 = getOperand1(inst);
|
TNodeOrConst *op1 = getOperand1(inst);
|
||||||
|
|
||||||
if (op1 == NULL) {
|
if (op1 == NULL) {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include "../src/symbol_table.h"
|
#include "../src/symbol_table.h"
|
||||||
extern FILE *asc_flag;
|
extern FILE *asc_flag;
|
||||||
extern bool tc_flag;
|
extern bool tc_flag;
|
||||||
extern void insert_code_line(char * error_message, int line_number);
|
extern void insert_code_line(char *error_message, int line_number);
|
||||||
extern bool contains_errors;
|
extern bool contains_errors;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -32,6 +32,6 @@ int offset;
|
|||||||
int currentsp;
|
int currentsp;
|
||||||
CGNode *cgList;
|
CGNode *cgList;
|
||||||
|
|
||||||
Stack* stack;
|
Stack *stack;
|
||||||
Stack* TrueList;
|
Stack *TrueList;
|
||||||
Stack* FalseList;
|
Stack *FalseList;
|
||||||
|
@ -3,20 +3,20 @@
|
|||||||
|
|
||||||
#include "intermediate_code.h"
|
#include "intermediate_code.h"
|
||||||
|
|
||||||
Stack * S_Init(){
|
Stack *S_Init() {
|
||||||
Stack * s = calloc(1, sizeof(*s));
|
Stack *s = calloc(1, sizeof(*s));
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void S_Free(Stack *s){
|
void S_Free(Stack *s) {
|
||||||
// since we are not responsible for the values we can just pop until
|
// since we are not responsible for the values we can just pop until
|
||||||
// NULL
|
// NULL
|
||||||
for (void * p = S_Pop(s); p != NULL; p = S_Pop(s));
|
for (void *p = S_Pop(s); p != NULL; p = S_Pop(s));
|
||||||
free(s);
|
free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void S_Push(Stack * s, void *v, int i) {
|
void S_Push(Stack *s, void *v, int i) {
|
||||||
__Node * n = calloc(1, sizeof(*n));
|
__Node *n = calloc(1, sizeof(*n));
|
||||||
n->v = v;
|
n->v = v;
|
||||||
n->next = s->n;
|
n->next = s->n;
|
||||||
s->n = n;
|
s->n = n;
|
||||||
@ -24,72 +24,70 @@ void S_Push(Stack * s, void *v, int i) {
|
|||||||
s->size = s->size + 1;
|
s->size = s->size + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void * S_Pop(Stack *s) {
|
void *S_Pop(Stack *s) {
|
||||||
if (s == NULL || S_IsEmpty(s)) {
|
if (s == NULL || S_IsEmpty(s)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
__Node * node = s->n;
|
__Node *node = s->n;
|
||||||
s->n = node->next;
|
s->n = node->next;
|
||||||
s->size = s->size - 1;
|
s->size = s->size - 1;
|
||||||
void * r = node->v;
|
void *r = node->v;
|
||||||
free(node);
|
free(node);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *S_Peek(Stack *s) {
|
||||||
void * S_Peek(Stack *s){
|
|
||||||
if (s == NULL || S_IsEmpty(s)) {
|
if (s == NULL || S_IsEmpty(s)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return s->n->v;
|
return s->n->v;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool S_IsEmpty(Stack *s){
|
bool S_IsEmpty(Stack *s) {
|
||||||
if(s == NULL || s->size == 0) {
|
if (s == NULL || s->size == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int S_Size(Stack *s){
|
int S_Size(Stack *s) {
|
||||||
if (s == NULL || S_IsEmpty(s)) {
|
if (s == NULL || S_IsEmpty(s)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return s->size;
|
return s->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void S_Merge(Stack *list){
|
void S_Merge(Stack *list) {
|
||||||
Stack* s1 = S_Pop(list);
|
Stack *s1 = S_Pop(list);
|
||||||
Stack* s2 = S_Peek(list);
|
Stack *s2 = S_Peek(list);
|
||||||
if(s1 == NULL){
|
if (s1 == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(s2 == NULL){
|
if (s2 == NULL) {
|
||||||
S_Push(list, s1, 0);
|
S_Push(list, s1, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (Instruction * i = S_Pop(s1); i; i = S_Pop(s1)){
|
for (Instruction *i = S_Pop(s1); i; i = S_Pop(s1)) {
|
||||||
S_Push(s2, i, 1);
|
S_Push(s2, i, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void emit_backpatch(Stack * s, int l){
|
void emit_backpatch(Stack *s, int l) {
|
||||||
for (Instruction * i = S_Pop(s); i; i = S_Pop(s)){
|
for (Instruction *i = S_Pop(s); i; i = S_Pop(s)) {
|
||||||
i->label = l;
|
i->label = l;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//_______________________________________________________________________
|
//_______________________________________________________________________
|
||||||
|
|
||||||
char * temp = NULL;
|
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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void emit_push_all(Stack * s){
|
void emit_push_all(Stack *s) {
|
||||||
for (Instruction * i = S_Pop(s); i; i = S_Pop(s)){
|
for (Instruction *i = S_Pop(s); i; i = S_Pop(s)) {
|
||||||
current->next = i;
|
current->next = i;
|
||||||
i->prev = current;
|
i->prev = current;
|
||||||
i->index = current->index + 1;
|
i->index = current->index + 1;
|
||||||
@ -98,52 +96,52 @@ void emit_push_all(Stack * s){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_detach(){
|
void emit_detach() {
|
||||||
current = current->prev;
|
current = current->prev;
|
||||||
current->next = NULL;
|
current->next = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void backpatch(Stack *s, int l){
|
void backpatch(Stack *s, int l) {
|
||||||
while (!S_IsEmpty(s)){
|
while (!S_IsEmpty(s)) {
|
||||||
Instruction * i = S_Pop(s);
|
Instruction *i = S_Pop(s);
|
||||||
set_label(i, l);
|
set_label(i, l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TNodeOrConst * getOperand1(Instruction * i){
|
TNodeOrConst *getOperand1(Instruction *i) {
|
||||||
return i->operand1;
|
return i->operand1;
|
||||||
}
|
}
|
||||||
|
|
||||||
TNodeOrConst * getOperand2(Instruction * i){
|
TNodeOrConst *getOperand2(Instruction *i) {
|
||||||
return i->operand2;
|
return i->operand2;
|
||||||
}
|
}
|
||||||
|
|
||||||
TableNode * getResult(Instruction * i){
|
TableNode *getResult(Instruction *i) {
|
||||||
return i->result;
|
return i->result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Op getOp(Instruction * i){
|
Op getOp(Instruction *i) {
|
||||||
return i->opcode;
|
return i->opcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getLabel(Instruction * i){
|
int getLabel(Instruction *i) {
|
||||||
return i->label;
|
return i->label;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_index(Instruction * i){
|
int get_index(Instruction *i) {
|
||||||
return i->index;
|
return i->index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_label(Instruction * i, int label){
|
void set_label(Instruction *i, int label) {
|
||||||
i->label = label;
|
i->label = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isConst(TNodeOrConst * tnc) {
|
bool isConst(TNodeOrConst *tnc) {
|
||||||
return tnc->d != NODE;
|
return tnc->d != NODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
TNodeOrConst * tn_or_const(Discriminant d, void * tnc) {
|
TNodeOrConst *tn_or_const(Discriminant d, void *tnc) {
|
||||||
TNodeOrConst * count = calloc(1, sizeof(*count));
|
TNodeOrConst *count = calloc(1, sizeof(*count));
|
||||||
count->d = d;
|
count->d = d;
|
||||||
count->tnc_union = calloc(1, sizeof(*count->tnc_union));
|
count->tnc_union = calloc(1, sizeof(*count->tnc_union));
|
||||||
switch (d) {
|
switch (d) {
|
||||||
@ -157,21 +155,21 @@ TNodeOrConst * tn_or_const(Discriminant d, void * tnc) {
|
|||||||
count->tnc_union->string = tnc;
|
count->tnc_union->string = tnc;
|
||||||
break;
|
break;
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
count->tnc_union->integer = *(int*)tnc;
|
count->tnc_union->integer = *(int *)tnc;
|
||||||
break;
|
break;
|
||||||
case CHARACTER:
|
case CHARACTER:
|
||||||
count->tnc_union->character = *(char*)tnc;
|
count->tnc_union->character = *(char *)tnc;
|
||||||
break;
|
break;
|
||||||
case BOOLEAN:
|
case BOOLEAN:
|
||||||
count->tnc_union->Boolean = *(uint_least8_t*)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 {
|
||||||
@ -184,40 +182,39 @@ static void emit_helper(void){
|
|||||||
|
|
||||||
void emit_binary_op(
|
void emit_binary_op(
|
||||||
Op op,
|
Op op,
|
||||||
TableNode * result,
|
TableNode *result,
|
||||||
TNodeOrConst * arg1,
|
TNodeOrConst *arg1,
|
||||||
TNodeOrConst * arg2
|
TNodeOrConst *arg2) {
|
||||||
){
|
|
||||||
emit_helper();
|
emit_helper();
|
||||||
current->opcode = op;
|
current->opcode = op;
|
||||||
// TODO: create temp and remove result from param list
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_goto(int i){
|
void emit_goto(int i) {
|
||||||
emit_helper();
|
emit_helper();
|
||||||
current->opcode = E_GOTO;
|
current->opcode = E_GOTO;
|
||||||
current->label = i;
|
current->label = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_assignment(TableNode * target, TNodeOrConst * source){
|
void emit_assignment(TableNode *target, TNodeOrConst *source) {
|
||||||
emit_helper();
|
emit_helper();
|
||||||
current->opcode = E_ASSIGN;
|
current->opcode = E_ASSIGN;
|
||||||
current->result = target;
|
current->result = target;
|
||||||
current->operand1 = source;
|
current->operand1 = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
char * get_string(TNodeOrConst * tc){
|
char *get_string(TNodeOrConst *tc) {
|
||||||
char * s;
|
char *s;
|
||||||
switch (tc->d) {
|
switch (tc->d) {
|
||||||
case NODE:
|
case NODE:
|
||||||
return getName(tc->tnc_union->node);
|
return getName(tc->tnc_union->node);
|
||||||
@ -234,26 +231,26 @@ char * get_string(TNodeOrConst * tc){
|
|||||||
sprintf(s, "%c", tc->tnc_union->character);
|
sprintf(s, "%c", tc->tnc_union->character);
|
||||||
return s;
|
return s;
|
||||||
case BOOLEAN:
|
case BOOLEAN:
|
||||||
if(tc->tnc_union->Boolean){
|
if (tc->tnc_union->Boolean) {
|
||||||
return strdup("true");
|
return strdup("true");
|
||||||
}
|
}
|
||||||
return strdup("false");
|
return strdup("false");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_label(int label){
|
void emit_label(int label) {
|
||||||
emit_helper();
|
emit_helper();
|
||||||
current->opcode = E_LABEL;
|
current->opcode = E_LABEL;
|
||||||
current->label = label;
|
current->label = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
@ -261,14 +258,16 @@ 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:
|
||||||
|
case E_IF_X_FALSE:
|
||||||
n1 = va_arg(argptr, TNodeOrConst *);
|
n1 = va_arg(argptr, TNodeOrConst *);
|
||||||
current->operand1 = n1;
|
current->operand1 = n1;
|
||||||
break;
|
break;
|
||||||
case E_LESS_THAN: case E_EQUAL_TO:
|
case E_LESS_THAN:
|
||||||
|
case E_EQUAL_TO:
|
||||||
n1 = va_arg(argptr, TNodeOrConst *);
|
n1 = va_arg(argptr, TNodeOrConst *);
|
||||||
n2 = va_arg(argptr, TNodeOrConst *);
|
n2 = va_arg(argptr, TNodeOrConst *);
|
||||||
current->operand1 = n1;
|
current->operand1 = n1;
|
||||||
@ -278,23 +277,22 @@ void emit_conditional_jump(Op condition, int label, ...){
|
|||||||
va_end(argptr);
|
va_end(argptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_function_start(TableNode * name){
|
void emit_function_start(TableNode *name) {
|
||||||
emit_helper();
|
emit_helper();
|
||||||
current->opcode = E_FUNC_START;
|
current->opcode = E_FUNC_START;
|
||||||
current->result = name;
|
current->result = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_function_call(
|
void emit_function_call(
|
||||||
TableNode * result,
|
TableNode *result,
|
||||||
int param_count,
|
int param_count,
|
||||||
TNodeOrConst * name
|
TNodeOrConst *name) {
|
||||||
){
|
|
||||||
emit_helper();
|
emit_helper();
|
||||||
current->opcode = E_CALL;
|
current->opcode = E_CALL;
|
||||||
current->operand1 = name;
|
current->operand1 = name;
|
||||||
@ -302,50 +300,50 @@ void emit_function_call(
|
|||||||
current->result = result;
|
current->result = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_reserve(TableNode * result, TNodeOrConst * size){
|
void emit_reserve(TableNode *result, TNodeOrConst *size) {
|
||||||
// this needs to change
|
// this needs to change
|
||||||
// we need to take a int
|
// we need to take a int
|
||||||
emit_parameter(size);
|
emit_parameter(size);
|
||||||
emit_function_call(result, 1, tn_or_const(NODE, look_up(cur, "reserve")));
|
emit_function_call(result, 1, tn_or_const(NODE, look_up(cur, "reserve")));
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_release(TableNode * pointer){
|
void emit_release(TableNode *pointer) {
|
||||||
emit_parameter(tn_or_const(NODE, pointer));
|
emit_parameter(tn_or_const(NODE, pointer));
|
||||||
emit_function_call(pointer, 1, tn_or_const(NODE, look_up(cur, "release")));
|
emit_function_call(pointer, 1, tn_or_const(NODE, look_up(cur, "release")));
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_deref_right(TableNode * x, TNodeOrConst * y){
|
void emit_deref_right(TableNode *x, TNodeOrConst *y) {
|
||||||
emit_helper();
|
emit_helper();
|
||||||
current->opcode = E_DEREF_RIGHT;
|
current->opcode = E_DEREF_RIGHT;
|
||||||
current->result = x;
|
current->result = x;
|
||||||
current->operand1 = y;
|
current->operand1 = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_deref_left(TableNode * x, TNodeOrConst * y){
|
void emit_deref_left(TableNode *x, TNodeOrConst *y) {
|
||||||
emit_helper();
|
emit_helper();
|
||||||
current->opcode = E_DEREF_LEFT;
|
current->opcode = E_DEREF_LEFT;
|
||||||
current->result = x;
|
current->result = x;
|
||||||
current->operand1 = y;
|
current->operand1 = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_address_of(TableNode * x, TNodeOrConst * y){
|
void emit_address_of(TableNode *x, TNodeOrConst *y) {
|
||||||
emit_helper();
|
emit_helper();
|
||||||
current->opcode = E_ADDRESS_OF;
|
current->opcode = E_ADDRESS_OF;
|
||||||
current->result = x;
|
current->result = x;
|
||||||
current->operand1 = y;
|
current->operand1 = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_field_access(char* result, char* record, char* field){
|
void emit_field_access(char *result, char *record, char *field) {
|
||||||
emit_helper();
|
emit_helper();
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_array_access(Op op, TableNode * result, TNodeOrConst * array, TNodeOrConst * index){
|
void emit_array_access(Op op, TableNode *result, TNodeOrConst *array, TNodeOrConst *index) {
|
||||||
emit_helper();
|
emit_helper();
|
||||||
current->opcode = op;
|
current->opcode = op;
|
||||||
current->result = result;
|
current->result = result;
|
||||||
@ -354,7 +352,7 @@ void emit_array_access(Op op, TableNode * result, TNodeOrConst * array, TNodeOrC
|
|||||||
// TODO: Still don't know what to do with the dimentions
|
// TODO: Still don't know what to do with the dimentions
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_bounds_check(TNodeOrConst * index, TNodeOrConst * arr){
|
void emit_bounds_check(TNodeOrConst *index, TNodeOrConst *arr) {
|
||||||
/*
|
/*
|
||||||
{[string: 5]
|
{[string: 5]
|
||||||
.
|
.
|
||||||
@ -392,34 +390,32 @@ void emit_bounds_check(TNodeOrConst * index, TNodeOrConst * arr){
|
|||||||
|
|
||||||
// * Implement temp variable generator function that produces unique names (t1, t2, etc.)
|
// * Implement temp variable generator function that produces unique names (t1, t2, etc.)
|
||||||
|
|
||||||
int label_gen(){
|
int label_gen() {
|
||||||
label_count++;
|
label_count++;
|
||||||
return label_count;
|
return label_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_as_file(FILE * out_file, Instruction * i){
|
void emit_as_file(FILE *out_file, Instruction *i) {
|
||||||
if (out_file == NULL){
|
if (out_file == NULL) {
|
||||||
fprintf(stderr, "Error: output file is NULL\n");
|
fprintf(stderr, "Error: output file is NULL\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(i == NULL){
|
if (i == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch(i->opcode){
|
switch (i->opcode) {
|
||||||
case E_FUNC_START:
|
case E_FUNC_START:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
"%4.d: func : %s\n",
|
"%4.d: func : %s\n",
|
||||||
i->index,
|
i->index,
|
||||||
getName(i->result)
|
getName(i->result));
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case E_LABEL:
|
case E_LABEL:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
"%4.d: Label : %d\n",
|
"%4.d: Label : %d\n",
|
||||||
i->index,
|
i->index,
|
||||||
i->label
|
i->label);
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case E_ADD:
|
case E_ADD:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
@ -427,8 +423,7 @@ void emit_as_file(FILE * out_file, Instruction * i){
|
|||||||
i->index,
|
i->index,
|
||||||
getName(i->result),
|
getName(i->result),
|
||||||
get_string(i->operand1),
|
get_string(i->operand1),
|
||||||
get_string(i->operand2)
|
get_string(i->operand2));
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case E_SUB:
|
case E_SUB:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
@ -436,8 +431,7 @@ void emit_as_file(FILE * out_file, Instruction * i){
|
|||||||
i->index,
|
i->index,
|
||||||
getName(i->result),
|
getName(i->result),
|
||||||
get_string(i->operand1),
|
get_string(i->operand1),
|
||||||
get_string(i->operand2)
|
get_string(i->operand2));
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case E_MUL:
|
case E_MUL:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
@ -445,8 +439,7 @@ void emit_as_file(FILE * out_file, Instruction * i){
|
|||||||
i->index,
|
i->index,
|
||||||
getName(i->result),
|
getName(i->result),
|
||||||
get_string(i->operand1),
|
get_string(i->operand1),
|
||||||
get_string(i->operand2)
|
get_string(i->operand2));
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case E_DIV:
|
case E_DIV:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
@ -454,8 +447,7 @@ void emit_as_file(FILE * out_file, Instruction * i){
|
|||||||
i->index,
|
i->index,
|
||||||
getName(i->result),
|
getName(i->result),
|
||||||
get_string(i->operand1),
|
get_string(i->operand1),
|
||||||
get_string(i->operand2)
|
get_string(i->operand2));
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case E_MOD:
|
case E_MOD:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
@ -463,8 +455,7 @@ void emit_as_file(FILE * out_file, Instruction * i){
|
|||||||
i->index,
|
i->index,
|
||||||
getName(i->result),
|
getName(i->result),
|
||||||
get_string(i->operand1),
|
get_string(i->operand1),
|
||||||
get_string(i->operand2)
|
get_string(i->operand2));
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case E_OR:
|
case E_OR:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
@ -472,8 +463,7 @@ void emit_as_file(FILE * out_file, Instruction * i){
|
|||||||
i->index,
|
i->index,
|
||||||
getName(i->result),
|
getName(i->result),
|
||||||
get_string(i->operand1),
|
get_string(i->operand1),
|
||||||
get_string(i->operand2)
|
get_string(i->operand2));
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case E_AND:
|
case E_AND:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
@ -481,55 +471,48 @@ void emit_as_file(FILE * out_file, Instruction * i){
|
|||||||
i->index,
|
i->index,
|
||||||
getName(i->result),
|
getName(i->result),
|
||||||
get_string(i->operand1),
|
get_string(i->operand1),
|
||||||
get_string(i->operand2)
|
get_string(i->operand2));
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case E_NEG:
|
case E_NEG:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
"%4.d: %s = -%s\n",
|
"%4.d: %s = -%s\n",
|
||||||
i->index,
|
i->index,
|
||||||
getName(i->result),
|
getName(i->result),
|
||||||
get_string(i->operand1)
|
get_string(i->operand1));
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case E_NOT:
|
case E_NOT:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
"%4.d: %s = !%s\n",
|
"%4.d: %s = !%s\n",
|
||||||
i->index,
|
i->index,
|
||||||
getName(i->result),
|
getName(i->result),
|
||||||
get_string(i->operand1)
|
get_string(i->operand1));
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case E_ASSIGN:
|
case E_ASSIGN:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
"%4.d: %s = %s\n",
|
"%4.d: %s = %s\n",
|
||||||
i->index,
|
i->index,
|
||||||
getName(i->result),
|
getName(i->result),
|
||||||
get_string(i->operand1)
|
get_string(i->operand1));
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case E_GOTO:
|
case E_GOTO:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
"%4.d: GOTO : %d\n",
|
"%4.d: GOTO : %d\n",
|
||||||
i->index,
|
i->index,
|
||||||
i->label
|
i->label);
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case E_IF_X_TRUE:
|
case E_IF_X_TRUE:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
"%4.d: if %s True GOTO %d\n",
|
"%4.d: if %s True GOTO %d\n",
|
||||||
i->index,
|
i->index,
|
||||||
get_string(i->operand1),
|
get_string(i->operand1),
|
||||||
i->label
|
i->label);
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case E_IF_X_FALSE:
|
case E_IF_X_FALSE:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
"%4.d: if %s False GOTO %d\n",
|
"%4.d: if %s False GOTO %d\n",
|
||||||
i->index,
|
i->index,
|
||||||
get_string(i->operand1),
|
get_string(i->operand1),
|
||||||
i->label
|
i->label);
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case E_LESS_THAN:
|
case E_LESS_THAN:
|
||||||
// this feels wrong I need to TODO: this
|
// this feels wrong I need to TODO: this
|
||||||
@ -538,8 +521,7 @@ void emit_as_file(FILE * out_file, Instruction * i){
|
|||||||
i->index,
|
i->index,
|
||||||
getName(i->result),
|
getName(i->result),
|
||||||
get_string(i->operand1),
|
get_string(i->operand1),
|
||||||
get_string(i->operand2)
|
get_string(i->operand2));
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case E_EQUAL_TO:
|
case E_EQUAL_TO:
|
||||||
// this feels wrong I need to TODO: this
|
// this feels wrong I need to TODO: this
|
||||||
@ -548,30 +530,26 @@ void emit_as_file(FILE * out_file, Instruction * i){
|
|||||||
i->index,
|
i->index,
|
||||||
getName(i->result),
|
getName(i->result),
|
||||||
get_string(i->operand1),
|
get_string(i->operand1),
|
||||||
get_string(i->operand2)
|
get_string(i->operand2));
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case E_CALL:
|
case E_CALL:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
"%4.d: call : %s %s\n",
|
"%4.d: call : %s %s\n",
|
||||||
i->index,
|
i->index,
|
||||||
get_string(i->operand1),
|
get_string(i->operand1),
|
||||||
get_string(i->operand2)
|
get_string(i->operand2));
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case E_PARAM:
|
case E_PARAM:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
"%4.d: param %s \n",
|
"%4.d: param %s \n",
|
||||||
i->index,
|
i->index,
|
||||||
get_string(i->operand1)
|
get_string(i->operand1));
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case E_RETURN:
|
case E_RETURN:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
"%4.d: return : %s\n",
|
"%4.d: return : %s\n",
|
||||||
i->index,
|
i->index,
|
||||||
get_string(i->operand1)
|
get_string(i->operand1));
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case E_INDEX_COPY_RIGHT:
|
case E_INDEX_COPY_RIGHT:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
@ -579,8 +557,7 @@ void emit_as_file(FILE * out_file, Instruction * i){
|
|||||||
i->index,
|
i->index,
|
||||||
getName(i->result),
|
getName(i->result),
|
||||||
get_string(i->operand1),
|
get_string(i->operand1),
|
||||||
get_string(i->operand2)
|
get_string(i->operand2));
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case E_INDEX_COPY_LEFT:
|
case E_INDEX_COPY_LEFT:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
@ -595,42 +572,36 @@ void emit_as_file(FILE * out_file, Instruction * i){
|
|||||||
"%4.d: %s = &%s\n",
|
"%4.d: %s = &%s\n",
|
||||||
i->index,
|
i->index,
|
||||||
getName(i->result),
|
getName(i->result),
|
||||||
get_string(i->operand1)
|
get_string(i->operand1));
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case E_DEREF_RIGHT:
|
case E_DEREF_RIGHT:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
"%4.d: %s = *%s\n",
|
"%4.d: %s = *%s\n",
|
||||||
i->index,
|
i->index,
|
||||||
getName(i->result),
|
getName(i->result),
|
||||||
get_string(i->operand1)
|
get_string(i->operand1));
|
||||||
);
|
|
||||||
case E_DEREF_LEFT:
|
case E_DEREF_LEFT:
|
||||||
fprintf(out_file,
|
fprintf(out_file,
|
||||||
"%4.d: *%s = %s\n",
|
"%4.d: *%s = %s\n",
|
||||||
i->index,
|
i->index,
|
||||||
getName(i->result),
|
getName(i->result),
|
||||||
get_string(i->operand1)
|
get_string(i->operand1));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emit_as_file(out_file, i->next);
|
emit_as_file(out_file, i->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TableNode *getTN(TNodeOrConst *tnc) {
|
||||||
|
|
||||||
TableNode* getTN(TNodeOrConst* tnc) {
|
|
||||||
if (tnc->d == NODE) {
|
if (tnc->d == NODE) {
|
||||||
return tnc->tnc_union->node;
|
return tnc->tnc_union->node;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getConst(TNodeOrConst* tnc) {
|
int getConst(TNodeOrConst *tnc) {
|
||||||
if (tnc->d == INTEGER) {
|
if (tnc->d == INTEGER) {
|
||||||
return tnc->tnc_union->integer;
|
return tnc->tnc_union->integer;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -16,20 +16,20 @@ typedef struct Stack Stack;
|
|||||||
typedef struct __Node __Node;
|
typedef struct __Node __Node;
|
||||||
|
|
||||||
typedef struct __Node {
|
typedef struct __Node {
|
||||||
void * v;
|
void *v;
|
||||||
__Node * next;
|
__Node *next;
|
||||||
} __Node;
|
} __Node;
|
||||||
|
|
||||||
typedef struct Stack {
|
typedef struct Stack {
|
||||||
__Node * n;
|
__Node *n;
|
||||||
int w;
|
int w;
|
||||||
int size;
|
int size;
|
||||||
} Stack;
|
} Stack;
|
||||||
Stack * S_Init();
|
Stack *S_Init();
|
||||||
void S_Free(Stack *s);
|
void S_Free(Stack *s);
|
||||||
void S_Push(Stack * s, void *v, int i);
|
void S_Push(Stack *s, void *v, int i);
|
||||||
void * S_Pop(Stack *s);
|
void *S_Pop(Stack *s);
|
||||||
void * S_Peek(Stack *s);
|
void *S_Peek(Stack *s);
|
||||||
bool S_IsEmpty(Stack *s);
|
bool S_IsEmpty(Stack *s);
|
||||||
int S_Size(Stack *s);
|
int S_Size(Stack *s);
|
||||||
void S_Merge(Stack *list);
|
void S_Merge(Stack *list);
|
||||||
@ -39,7 +39,6 @@ typedef union TNConstUnion TNConstUnion;
|
|||||||
typedef struct Instruction Instruction;
|
typedef struct Instruction Instruction;
|
||||||
typedef struct TNodeOrConst TNodeOrConst;
|
typedef struct TNodeOrConst TNodeOrConst;
|
||||||
|
|
||||||
|
|
||||||
// these are from page 364
|
// these are from page 364
|
||||||
|
|
||||||
typedef enum { // these are from page 364
|
typedef enum { // these are from page 364
|
||||||
@ -81,95 +80,89 @@ typedef enum {
|
|||||||
} Discriminant;
|
} Discriminant;
|
||||||
|
|
||||||
typedef union TNConstUnion {
|
typedef union TNConstUnion {
|
||||||
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 TNodeOrConst {
|
typedef struct TNodeOrConst {
|
||||||
Discriminant d;
|
Discriminant d;
|
||||||
TNConstUnion * tnc_union;
|
TNConstUnion *tnc_union;
|
||||||
} TNodeOrConst;
|
} TNodeOrConst;
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
|
||||||
// NOTE We are not using this We are using the Stack api
|
// NOTE We are not using this We are using the Stack api
|
||||||
typedef struct TFList {
|
typedef struct TFList {
|
||||||
Instruction * i;
|
Instruction *i;
|
||||||
TFList * next;
|
TFList *next;
|
||||||
} TFList;
|
} TFList;
|
||||||
|
|
||||||
// TFList * make_list(Instruction * i);
|
// TFList * make_list(Instruction * i);
|
||||||
// - makelist(i) function to create instruction lists
|
// - makelist(i) function to create instruction lists
|
||||||
// void merge(TFList * l1, TFList * l2);
|
// void merge(TFList * l1, TFList * l2);
|
||||||
// - merge(p1,p2) function to concatenate lists
|
// - merge(p1,p2) function to concatenate lists
|
||||||
// void backpatch(TFList * l, int label);
|
// void backpatch(TFList * l, int label);
|
||||||
// - backpatch(p,i) function to fill in jump targets
|
// - backpatch(p,i) function to fill in jump targets
|
||||||
// void bp_temp(int n);
|
// void bp_temp(int n);
|
||||||
|
|
||||||
|
extern Instruction *begin;
|
||||||
extern Instruction * begin;
|
extern Instruction *current;
|
||||||
extern Instruction * current;
|
|
||||||
extern int label_count;
|
extern int label_count;
|
||||||
extern bool code_gen;
|
extern bool code_gen;
|
||||||
extern FILE * ir_flag;
|
extern FILE *ir_flag;
|
||||||
|
|
||||||
|
TNodeOrConst *tn_or_const(Discriminant, void *);
|
||||||
TNodeOrConst * tn_or_const(Discriminant , void * );
|
void emit_binary_op(Op op, TableNode *result, TNodeOrConst *arg1, TNodeOrConst *arg2);
|
||||||
void emit_binary_op(Op op, TableNode * result, TNodeOrConst * arg1, TNodeOrConst * arg2);
|
void emit_unary_op(Op op, TableNode *result, TNodeOrConst *arg);
|
||||||
void emit_unary_op(Op op, TableNode * result, TNodeOrConst * arg);
|
void emit_assignment(TableNode *target, TNodeOrConst *source);
|
||||||
void emit_assignment(TableNode * target, TNodeOrConst * source);
|
void emit_as_file(FILE *out_file, Instruction *instr_arr);
|
||||||
void emit_as_file(FILE * out_file, Instruction * instr_arr);
|
|
||||||
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(TableNode* name);
|
void emit_function_start(TableNode *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(TableNode *result, TNodeOrConst *size);
|
||||||
void emit_release(TableNode * pointer);
|
void emit_release(TableNode *pointer);
|
||||||
void emit_field_access(char* result, char* record, char* field);
|
void emit_field_access(char *result, char *record, char *field);
|
||||||
void emit_array_access(Op op, TableNode * result, TNodeOrConst * array, TNodeOrConst * index);
|
void emit_array_access(Op op, TableNode *result, TNodeOrConst *array, TNodeOrConst *index);
|
||||||
void emit_bounds_check(TNodeOrConst * index, TNodeOrConst * arr);
|
void emit_bounds_check(TNodeOrConst *index, TNodeOrConst *arr);
|
||||||
void emit_goto(int i);
|
void emit_goto(int i);
|
||||||
void emit_detach();
|
void emit_detach();
|
||||||
void emit_push_all(Stack * s);
|
void emit_push_all(Stack *s);
|
||||||
|
|
||||||
|
int getLabel(Instruction *i);
|
||||||
|
TableNode *getTN(TNodeOrConst *tnc);
|
||||||
|
int getConst(TNodeOrConst *tnc);
|
||||||
|
|
||||||
int getLabel(Instruction * i);
|
TNodeOrConst *getOperand1(Instruction *i);
|
||||||
TableNode* getTN(TNodeOrConst* tnc);
|
TNodeOrConst *getOperand2(Instruction *i);
|
||||||
int getConst(TNodeOrConst* tnc);
|
TableNode *getResult(Instruction *i);
|
||||||
|
Op getOp(Instruction *i);
|
||||||
|
int getLabel(Instruction *i);
|
||||||
|
int get_index(Instruction *i);
|
||||||
TNodeOrConst * getOperand1(Instruction * i);
|
void set_label(Instruction *i, int label);
|
||||||
TNodeOrConst * getOperand2(Instruction * i);
|
bool isConst(TNodeOrConst *tnc);
|
||||||
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);
|
|
||||||
int label_gen();
|
int label_gen();
|
||||||
void backpatch(Stack *s, int l);
|
void backpatch(Stack *s, int l);
|
||||||
void emit_backpatch(Stack *s, int l);
|
void emit_backpatch(Stack *s, int l);
|
||||||
extern int offset;
|
extern int offset;
|
||||||
extern int currentsp;
|
extern int currentsp;
|
||||||
extern CGNode* cgList;
|
extern CGNode *cgList;
|
||||||
|
@ -25,10 +25,11 @@ int line_number = 1;
|
|||||||
int column_number = 1;
|
int column_number = 1;
|
||||||
int yycolumn = 1;
|
int yycolumn = 1;
|
||||||
|
|
||||||
#define YY_USER_ACTION { \
|
#define YY_USER_ACTION \
|
||||||
|
{ \
|
||||||
yylloc.first_line = yylineno; \
|
yylloc.first_line = yylineno; \
|
||||||
yylloc.last_line = yylineno; \
|
yylloc.last_line = yylineno; \
|
||||||
yylloc.first_column = yycolumn; \
|
yylloc.first_column = yycolumn; \
|
||||||
yylloc.last_column = yycolumn + yyleng - 1; \
|
yylloc.last_column = yycolumn + yyleng - 1; \
|
||||||
yycolumn += yyleng; \
|
yycolumn += yyleng; \
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,6 @@ int run(FILE *alpha) {
|
|||||||
int token;
|
int token;
|
||||||
top = cur = init(CreateScope(NULL, 1, 1));
|
top = cur = init(CreateScope(NULL, 1, 1));
|
||||||
|
|
||||||
|
|
||||||
// If file is not found
|
// If file is not found
|
||||||
if (alpha == NULL) {
|
if (alpha == NULL) {
|
||||||
fprintf(stderr, "INPUT FILE NOT FOUND\n");
|
fprintf(stderr, "INPUT FILE NOT FOUND\n");
|
||||||
|
12
src/runner.h
12
src/runner.h
@ -59,8 +59,8 @@ bool DEBUG = false;
|
|||||||
int no_flag = 0;
|
int no_flag = 0;
|
||||||
int arg;
|
int arg;
|
||||||
bool contains_errors = false;
|
bool contains_errors = false;
|
||||||
char * cg_name;
|
char *cg_name;
|
||||||
char * ir_name;
|
char *ir_name;
|
||||||
|
|
||||||
TableNode *funprime;
|
TableNode *funprime;
|
||||||
TableNode *arrayprim;
|
TableNode *arrayprim;
|
||||||
@ -73,9 +73,9 @@ TableNode *recprime;
|
|||||||
TableNode *funtypeprime;
|
TableNode *funtypeprime;
|
||||||
TableNode *undefined;
|
TableNode *undefined;
|
||||||
extern Instruction *begin;
|
extern Instruction *begin;
|
||||||
extern Stack* stack;
|
extern Stack *stack;
|
||||||
extern Stack* TrueList;
|
extern Stack *TrueList;
|
||||||
extern Stack* FalseList;
|
extern Stack *FalseList;
|
||||||
|
|
||||||
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);
|
||||||
@ -112,6 +112,6 @@ typedef struct CodeLine {
|
|||||||
CodeLine *code_head;
|
CodeLine *code_head;
|
||||||
|
|
||||||
char *file_read_line(FILE *fp);
|
char *file_read_line(FILE *fp);
|
||||||
void insert_code_line(char * error_message, int line_number);
|
void insert_code_line(char *error_message, int line_number);
|
||||||
void append_code_line(CodeLine *code_line);
|
void append_code_line(CodeLine *code_line);
|
||||||
void print_code_lines();
|
void print_code_lines();
|
||||||
|
@ -116,15 +116,15 @@ int getPrimSize(TableNode *definition) {
|
|||||||
"Invalid.");
|
"Invalid.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(getAdInfoType(definition) == TYPE_ARRAY_TYPE){
|
if (getAdInfoType(definition) == TYPE_ARRAY_TYPE) {
|
||||||
//special case to return size for reference to an array
|
//special case to return size for reference to an array
|
||||||
return 8;
|
return 8;
|
||||||
}
|
}
|
||||||
if(getAdInfoType(definition) == TYPE_FUNCTION_TYPE){
|
if (getAdInfoType(definition) == TYPE_FUNCTION_TYPE) {
|
||||||
//special case to return size for reference to a function
|
//special case to return size for reference to a function
|
||||||
return 8;
|
return 8;
|
||||||
}
|
}
|
||||||
if(getAdInfoType(definition) == TYPE_RECORD_TYPE){
|
if (getAdInfoType(definition) == TYPE_RECORD_TYPE) {
|
||||||
//special case to return size for reference to a record
|
//special case to return size for reference to a record
|
||||||
return getRecTotal(definition);
|
return getRecTotal(definition);
|
||||||
}
|
}
|
||||||
@ -469,7 +469,7 @@ int getRecSize(SymbolTable *tn) {
|
|||||||
// multiple inputs Below function also has the line number where the function is
|
// multiple inputs Below function also has the line number where the function is
|
||||||
// first defined
|
// first defined
|
||||||
AdInfo *CreateFunctionDeclarationInfo(int line, bool asorregular, SymbolTable *scope) {
|
AdInfo *CreateFunctionDeclarationInfo(int line, bool asorregular, SymbolTable *scope) {
|
||||||
AdInfo *info = (AdInfo *)calloc(1,sizeof(AdInfo));
|
AdInfo *info = (AdInfo *)calloc(1, sizeof(AdInfo));
|
||||||
info->FunDecAdInfo = (function_declaration_info *)malloc(
|
info->FunDecAdInfo = (function_declaration_info *)malloc(
|
||||||
sizeof(function_declaration_info));
|
sizeof(function_declaration_info));
|
||||||
info->FunDecAdInfo->startlinenumber = line;
|
info->FunDecAdInfo->startlinenumber = line;
|
||||||
@ -561,12 +561,12 @@ SymbolTable *getFunScope(TableNode *definition) {
|
|||||||
"node has NULL additionalinfo. Invalid.");
|
"node has NULL additionalinfo. Invalid.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if(definition->additionalinfo->FunDecAdInfo == NULL) {
|
if (definition->additionalinfo->FunDecAdInfo == NULL) {
|
||||||
printdebug(
|
printdebug(
|
||||||
"node has NULL additionalinfo. Invalid.");
|
"node has NULL additionalinfo. Invalid.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if(definition->additionalinfo->FunDecAdInfo->scope == NULL) {
|
if (definition->additionalinfo->FunDecAdInfo->scope == NULL) {
|
||||||
printdebug(
|
printdebug(
|
||||||
"node has no scope initialized.");
|
"node has no scope initialized.");
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -587,17 +587,17 @@ TableNode *setFunScope(TableNode *tn, SymbolTable *scope) {
|
|||||||
"invalid");
|
"invalid");
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
if(tn->additionalinfo == NULL) {
|
if (tn->additionalinfo == NULL) {
|
||||||
printdebug(
|
printdebug(
|
||||||
"node has NULL additionalinfo. Invalid.");
|
"node has NULL additionalinfo. Invalid.");
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
if(tn->additionalinfo->FunDecAdInfo == NULL) {
|
if (tn->additionalinfo->FunDecAdInfo == NULL) {
|
||||||
printdebug(
|
printdebug(
|
||||||
"node has NULL additionalinfo. Invalid.");
|
"node has NULL additionalinfo. Invalid.");
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
if(scope == NULL) {
|
if (scope == NULL) {
|
||||||
printdebug(
|
printdebug(
|
||||||
"passed in an empty scope.");
|
"passed in an empty scope.");
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -705,7 +705,7 @@ TableNode *getReturn(TableNode *definition) {
|
|||||||
"node has NULL additionalinfo. Invalid.");
|
"node has NULL additionalinfo. Invalid.");
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
printdebug("function:%s with return type %s\n",getName(definition),getName(definition->additionalinfo->FunTypeAdInfo->returntype));
|
printdebug("function:%s with return type %s\n", getName(definition), getName(definition->additionalinfo->FunTypeAdInfo->returntype));
|
||||||
return definition->additionalinfo->FunTypeAdInfo->returntype;
|
return definition->additionalinfo->FunTypeAdInfo->returntype;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -862,10 +862,10 @@ SymbolTable *init(SymbolTable *start) {
|
|||||||
chara->additionalinfo = CreatePrimitiveInfo(SIZE_CHAR);
|
chara->additionalinfo = CreatePrimitiveInfo(SIZE_CHAR);
|
||||||
stri->additionalinfo = CreateArrayInfo(1, chara);
|
stri->additionalinfo = CreateArrayInfo(1, chara);
|
||||||
boo->additionalinfo = CreatePrimitiveInfo(SIZE_BOOL);
|
boo->additionalinfo = CreatePrimitiveInfo(SIZE_BOOL);
|
||||||
reserve->additionalinfo = CreateFunctionDeclarationInfo(0, false,NULL);
|
reserve->additionalinfo = CreateFunctionDeclarationInfo(0, false, NULL);
|
||||||
reservetype->additionalinfo = CreateFunctionTypeInfo(integ, addr);
|
reservetype->additionalinfo = CreateFunctionTypeInfo(integ, addr);
|
||||||
releasetype->additionalinfo = CreateFunctionTypeInfo(addr, integ);
|
releasetype->additionalinfo = CreateFunctionTypeInfo(addr, integ);
|
||||||
release->additionalinfo = CreateFunctionDeclarationInfo(0, false,NULL);
|
release->additionalinfo = CreateFunctionDeclarationInfo(0, false, NULL);
|
||||||
|
|
||||||
integ->tag = TYPE_PRIMITIVE_TYPE; // explicitly set the type for integ
|
integ->tag = TYPE_PRIMITIVE_TYPE; // explicitly set the type for integ
|
||||||
addr->tag = TYPE_PRIMITIVE_TYPE; // explicitly set the type for addr
|
addr->tag = TYPE_PRIMITIVE_TYPE; // explicitly set the type for addr
|
||||||
@ -1031,7 +1031,7 @@ TableNode *CreateEntry(SymbolTable *table, int tag, TableNode *typeOf, char *id,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
if((id != NULL) && table_lookup(cur,id)!=undefined){
|
if ((id != NULL) && table_lookup(cur, id) != undefined) {
|
||||||
printdebug("This name is already defined in the current scope");
|
printdebug("This name is already defined in the current scope");
|
||||||
//throw_error(ERROR_TYPE, "Already defined.");
|
//throw_error(ERROR_TYPE, "Already defined.");
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -1062,7 +1062,7 @@ TableNode *CreateEntry(SymbolTable *table, int tag, TableNode *typeOf, char *id,
|
|||||||
printdebug("[CreateEntry] Adding %s to the symbol table", id);
|
printdebug("[CreateEntry] Adding %s to the symbol table", id);
|
||||||
return newEntry;
|
return newEntry;
|
||||||
} else {
|
} else {
|
||||||
TableNode*oldEntry = table->entries;
|
TableNode *oldEntry = table->entries;
|
||||||
while (oldEntry->next != NULL) {
|
while (oldEntry->next != NULL) {
|
||||||
oldEntry = oldEntry->next;
|
oldEntry = oldEntry->next;
|
||||||
}
|
}
|
||||||
@ -1309,7 +1309,7 @@ void print_symbol_table(SymbolTable *table, FILE *file_ptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (; entry != NULL; entry = getNextEntry(entry)) {
|
for (; entry != NULL; entry = getNextEntry(entry)) {
|
||||||
if((getName(entry)[0] == '$' || getName(entry)[0] == '&') && ir_flag == NULL){
|
if ((getName(entry)[0] == '$' || getName(entry)[0] == '&') && ir_flag == NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (getAdInfoType(entry) == TYPE_ARRAY_TYPE) {
|
if (getAdInfoType(entry) == TYPE_ARRAY_TYPE) {
|
||||||
@ -1391,11 +1391,11 @@ void print_symbol_table(SymbolTable *table, FILE *file_ptr) {
|
|||||||
if (getAdInfoType(entry) == TYPE_FUNCTION_DECLARATION) {
|
if (getAdInfoType(entry) == TYPE_FUNCTION_DECLARATION) {
|
||||||
char *functiontype = (char *)malloc(100);
|
char *functiontype = (char *)malloc(100);
|
||||||
sprintf(functiontype, " %s", getName(getTypeEntry(entry)));
|
sprintf(functiontype, " %s", getName(getTypeEntry(entry)));
|
||||||
char* functionScope = (char *)malloc(100);
|
char *functionScope = (char *)malloc(100);
|
||||||
if(getLine(getFunScope(entry)) < 1){
|
if (getLine(getFunScope(entry)) < 1) {
|
||||||
sprintf(functionScope, " Function not defined before runtime");
|
sprintf(functionScope, " Function not defined before runtime");
|
||||||
}else{
|
} else {
|
||||||
sprintf(functionScope, " Function Definition that starts at line %d",getLine(getFunScope(entry)));
|
sprintf(functionScope, " Function Definition that starts at line %d", getLine(getFunScope(entry)));
|
||||||
}
|
}
|
||||||
if (parentScopeNum == 0) {
|
if (parentScopeNum == 0) {
|
||||||
st_fprint(file_ptr, getName(entry), currentScopeNum, -100, functiontype, functionScope);
|
st_fprint(file_ptr, getName(entry), currentScopeNum, -100, functiontype, functionScope);
|
||||||
@ -1545,7 +1545,13 @@ SymbolTable *getParent(SymbolTable *st) {
|
|||||||
ListOfTable *getChildren(SymbolTable *st) { return st->Children_Scope; }
|
ListOfTable *getChildren(SymbolTable *st) { return st->Children_Scope; }
|
||||||
SymbolTable *getFirstChild(ListOfTable *lt) { return lt->table; }
|
SymbolTable *getFirstChild(ListOfTable *lt) { return lt->table; }
|
||||||
ListOfTable *getRestOfChildren(ListOfTable *lt) { return lt->next; }
|
ListOfTable *getRestOfChildren(ListOfTable *lt) { return lt->next; }
|
||||||
TableNode *getFirstEntry(SymbolTable *st) { return st->entries; }
|
TableNode *getFirstEntry(SymbolTable *st) {
|
||||||
|
if (st == NULL || st->entries == NULL) {
|
||||||
|
printdebug("passed a NULL symbol table to getFirstEntry");
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return st->entries;
|
||||||
|
}
|
||||||
|
|
||||||
// Segfaults when passed an invalid table node!
|
// Segfaults when passed an invalid table node!
|
||||||
TableNode *getNextEntry(TableNode *tn) {
|
TableNode *getNextEntry(TableNode *tn) {
|
||||||
|
@ -48,7 +48,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
int startlinenumber;
|
int startlinenumber;
|
||||||
bool regularoras;
|
bool regularoras;
|
||||||
SymbolTable* scope;
|
SymbolTable *scope;
|
||||||
} function_declaration_info;
|
} function_declaration_info;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -122,7 +122,7 @@ int getRecLength(TableNode *definition);
|
|||||||
SymbolTable *getRecList(TableNode *definition);
|
SymbolTable *getRecList(TableNode *definition);
|
||||||
TableNode *setRecSize(TableNode *tn, int n);
|
TableNode *setRecSize(TableNode *tn, int n);
|
||||||
int getRecSize(SymbolTable *tn);
|
int getRecSize(SymbolTable *tn);
|
||||||
AdInfo *CreateFunctionDeclarationInfo(int line, bool asorregular,SymbolTable *scope);
|
AdInfo *CreateFunctionDeclarationInfo(int line, bool asorregular, SymbolTable *scope);
|
||||||
TableNode *setFunScope(TableNode *tn, SymbolTable *scope);
|
TableNode *setFunScope(TableNode *tn, SymbolTable *scope);
|
||||||
SymbolTable *getFunScope(TableNode *definition);
|
SymbolTable *getFunScope(TableNode *definition);
|
||||||
int getStartLine(TableNode *definition);
|
int getStartLine(TableNode *definition);
|
||||||
|
1
tests/programs/test/fib.alpha
Normal file
1
tests/programs/test/fib.alpha
Normal file
@ -0,0 +1 @@
|
|||||||
|
(* TODO: Prints out fib sequence. *)
|
1
tests/programs/test/ll.alpha
Normal file
1
tests/programs/test/ll.alpha
Normal file
@ -0,0 +1 @@
|
|||||||
|
(* TODO: creates a linked list and prints out the chain. *)
|
@ -1,35 +1,14 @@
|
|||||||
(* TEST: [-asc -tc -cg -ir] *)
|
(* TEST: [-asc -tc -cg -ir] *)
|
||||||
|
|
||||||
type string: 1 -> character
|
#include "std.alpha"
|
||||||
type BooleanXBoolean: [Boolean: x; Boolean: y]
|
|
||||||
type characterXcharacter: [character: x; character: y]
|
|
||||||
type integerXinteger: [integer: x; integer: y]
|
|
||||||
|
|
||||||
type Boolean2Boolean: Boolean -> Boolean
|
|
||||||
type integer2integer: integer -> integer
|
|
||||||
type character2integer: character -> integer
|
|
||||||
type Boolean2integer0: Boolean -> integer
|
|
||||||
type string2integer: string -> integer
|
|
||||||
type integerXinteger2integer: integerXinteger -> integer
|
|
||||||
type integerXinteger2Boolean: integerXinteger -> Boolean
|
|
||||||
type characterXcharacter2Boolean: characterXcharacter -> Boolean
|
|
||||||
type BooleanXBoolean2Boolean: BooleanXBoolean -> Boolean
|
|
||||||
type integer2address: integer -> address
|
|
||||||
type address2integer: address -> integer
|
|
||||||
|
|
||||||
external function printInteger: integer2integer
|
|
||||||
external function printCharacter: character2integer
|
|
||||||
external function printBoolean: Boolean2integer
|
|
||||||
|
|
||||||
function entry: string2integer
|
|
||||||
|
|
||||||
entry (arg) := {
|
entry (arg) := {
|
||||||
[integer:x; integer:y; integer: result]
|
[integer:x; integer:y; integer: result]
|
||||||
|
|
||||||
y := 1;
|
y := 1;
|
||||||
x := 3;
|
x := 3;
|
||||||
y := x + y;
|
y := x + y;
|
||||||
|
|
||||||
result := printInteger(y);
|
result := printInteger(y);
|
||||||
|
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
@ -1,11 +1,13 @@
|
|||||||
(* TEST: [-asc -tc -cg -ir] *)
|
(* TEST: [-asc -tc -cg -ir] *)
|
||||||
type main: integer -> integer
|
|
||||||
function test: main
|
|
||||||
|
|
||||||
test (a) := {
|
#include "std.alpha"
|
||||||
|
|
||||||
|
entry (arg) := {
|
||||||
[Boolean:b; Boolean: c; Boolean: d]
|
[Boolean:b; Boolean: c; Boolean: d]
|
||||||
c := true;
|
|
||||||
|
z := true;
|
||||||
d := false;
|
d := false;
|
||||||
d := c & d;
|
d := c & d;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
@ -1,8 +0,0 @@
|
|||||||
type main: string -> integer
|
|
||||||
function entry: main
|
|
||||||
|
|
||||||
entry(arg) := {
|
|
||||||
[integer:x]
|
|
||||||
x := 3 + 2 * 8;
|
|
||||||
return x;
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
type main: string -> integer
|
|
||||||
function entry: main
|
|
||||||
|
|
||||||
entry(arg) := {
|
|
||||||
[integer:x; Boolean b]
|
|
||||||
x := 3 + 2 * 8;
|
|
||||||
b := x < 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,11 +1,13 @@
|
|||||||
(* TEST: [-asc -tc -cg -ir] *)
|
(* TEST: [-asc -tc -cg -ir] *)
|
||||||
type main: integer -> integer
|
|
||||||
function test: main
|
|
||||||
|
|
||||||
test (a) := {
|
#include "std.alpha"
|
||||||
|
|
||||||
|
entry (arg) := {
|
||||||
[integer:x; integer:y]
|
[integer:x; integer:y]
|
||||||
|
|
||||||
y := 1;
|
y := 1;
|
||||||
x := 3;
|
x := 3;
|
||||||
y := x / y;
|
y := x / y;
|
||||||
|
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
@ -1,11 +1,13 @@
|
|||||||
(* TEST: [-asc -tc -cg -ir] *)
|
(* TEST: [-asc -tc -cg -ir] *)
|
||||||
type main: integer -> integer
|
|
||||||
function test: main
|
|
||||||
|
|
||||||
test (a) := {
|
#include "std.alpha"
|
||||||
|
|
||||||
|
entry (arg) := {
|
||||||
[Boolean: b; integer: x; integer: y]
|
[Boolean: b; integer: x; integer: y]
|
||||||
|
|
||||||
x := 1;
|
x := 1;
|
||||||
y := 2;
|
y := 2;
|
||||||
b := x = y;
|
b := x = y;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
@ -1,18 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
|||||||
(* TEST: [-asc -tc -cg -ir] *)
|
(* TEST: [-asc -tc -cg -ir] *)
|
||||||
type main: integer -> integer
|
|
||||||
function test: main
|
|
||||||
|
|
||||||
test (a) := {
|
#include "std.alpha"
|
||||||
|
|
||||||
|
entry (arg) := {
|
||||||
[Boolean: b; integer: x; integer: y]
|
[Boolean: b; integer: x; integer: y]
|
||||||
character x := 1;
|
|
||||||
|
x := 1;
|
||||||
y := 2;
|
y := 2;
|
||||||
b := x < y;
|
b := x < y;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
(* TEST: [-asc -tc -cg -ir] *)
|
(* TEST: [-asc -tc -cg -ir] *)
|
||||||
type main: integer -> integer
|
|
||||||
function test: main
|
|
||||||
|
|
||||||
test (a) := {
|
#include "std.alpha"
|
||||||
|
|
||||||
|
entry (arg) := {
|
||||||
[integer:x; integer:y]
|
[integer:x; integer:y]
|
||||||
|
|
||||||
y := 1;
|
y := 1;
|
||||||
x := 3;
|
x := 3;
|
||||||
y := x % y;
|
y := x % y;
|
||||||
|
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
@ -1,11 +1,13 @@
|
|||||||
(* TEST: [-asc -tc -cg -ir] *)
|
(* TEST: [-asc -tc -cg -ir] *)
|
||||||
type main: integer -> integer
|
|
||||||
function test: main
|
|
||||||
|
|
||||||
test (a) := {
|
#include "std.alpha"
|
||||||
|
|
||||||
|
entry (arg) := {
|
||||||
[integer:x; integer:y]
|
[integer:x; integer:y]
|
||||||
|
|
||||||
y := 1;
|
y := 1;
|
||||||
x := 3;
|
x := 3;
|
||||||
y := x * x;
|
y := x * x;
|
||||||
|
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
@ -1,10 +1,12 @@
|
|||||||
(* TEST: [-asc -tc -cg -ir] *)
|
(* TEST: [-asc -tc -cg -ir] *)
|
||||||
type main: integer -> integer
|
|
||||||
function test: main
|
|
||||||
|
|
||||||
test (a) := {
|
#include "std.alpha"
|
||||||
|
|
||||||
|
entry (arg) := {
|
||||||
[integer:x; integer:y]
|
[integer:x; integer:y]
|
||||||
|
|
||||||
x := 3;
|
x := 3;
|
||||||
y := -x;
|
y := -x;
|
||||||
|
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
@ -1,10 +1,12 @@
|
|||||||
(* TEST: [-asc -tc -cg -ir] *)
|
(* TEST: [-asc -tc -cg -ir] *)
|
||||||
type main: integer -> integer
|
|
||||||
function test: main
|
|
||||||
|
|
||||||
test (a) := {
|
#include "std.alpha"
|
||||||
|
|
||||||
|
entry (arg) := {
|
||||||
[Boolean: c; Boolean: d]
|
[Boolean: c; Boolean: d]
|
||||||
|
|
||||||
c := true;
|
c := true;
|
||||||
d := !c;
|
d := !c;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
@ -1,11 +1,13 @@
|
|||||||
(* TEST: [-asc -tc -cg -ir] *)
|
(* TEST: [-asc -tc -cg -ir] *)
|
||||||
type main: integer -> integer
|
|
||||||
function test: main
|
|
||||||
|
|
||||||
test (a) := {
|
#include "std.alpha"
|
||||||
|
|
||||||
|
entry (arg) := {
|
||||||
[Boolean:b; Boolean: c; Boolean: d]
|
[Boolean:b; Boolean: c; Boolean: d]
|
||||||
|
|
||||||
c := true;
|
c := true;
|
||||||
d := false;
|
d := false;
|
||||||
d := c | d;
|
d := c | d;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
}
|
}
|
@ -1,11 +1,13 @@
|
|||||||
(* TEST: [-asc -tc -cg -ir] *)
|
(* TEST: [-asc -tc -cg -ir] *)
|
||||||
type main: integer -> integer
|
|
||||||
function test: main
|
|
||||||
|
|
||||||
test (a) := {
|
#include "std.alpha"
|
||||||
|
|
||||||
|
entry (arg) := {
|
||||||
[integer:x; integer:y]
|
[integer:x; integer:y]
|
||||||
|
|
||||||
y := 1;
|
y := 1;
|
||||||
x := 3;
|
x := 3;
|
||||||
y := x - y;
|
y := x - y;
|
||||||
|
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
Reference in New Issue
Block a user