1
.gitignore
vendored
1
.gitignore
vendored
@ -9,3 +9,4 @@ out
|
|||||||
tmp
|
tmp
|
||||||
parser
|
parser
|
||||||
*.save
|
*.save
|
||||||
|
binaries
|
52
Makefile
52
Makefile
@ -3,19 +3,15 @@ CC := gcc
|
|||||||
FLEX := flex
|
FLEX := flex
|
||||||
BISON = bison
|
BISON = bison
|
||||||
|
|
||||||
CFLAGS := -ggdb
|
CFLAGS := -ggdb -g -O0 #-fsanitize=address
|
||||||
BISONFLAGS := -d
|
# LDFLAGS := -fsanitize=address
|
||||||
|
BISONFLAGS := -d -Wcounterexamples
|
||||||
|
|
||||||
LEX := src/lexicalStructure.lex
|
LEX := src/lexicalStructure.lex
|
||||||
YACC := src/grammar.y
|
YACC := src/grammar.y
|
||||||
EXE := alpha
|
EXE := alpha
|
||||||
|
|
||||||
OBJS := tmp/runner.o tmp/symbol_table.o tmp/grammar.tab.o tmp/lex.yy.o tmp/intermediate_code.o tmp/codegen.o
|
OBJS := tmp/runner.o tmp/symbol_table.o tmp/grammar.tab.o tmp/lex.yy.o tmp/intermediate_code.o tmp/codegen.o
|
||||||
|
|
||||||
TESTS-S1 := $(wildcard tests/sprint1/test/*.alpha)
|
|
||||||
TESTS-S2 := $(wildcard tests/sprint2/test/*.alpha)
|
|
||||||
TESTS-S3 := $(wildcard tests/sprint3/test/*.alpha)
|
|
||||||
TESTS-S4 := $(wildcard tests/sprint4/test/*.alpha)
|
|
||||||
# ----------
|
# ----------
|
||||||
|
|
||||||
|
|
||||||
@ -24,11 +20,14 @@ TESTS-S4 := $(wildcard tests/sprint4/test/*.alpha)
|
|||||||
all: compiler
|
all: compiler
|
||||||
|
|
||||||
compiler: clean tmp $(OBJS)
|
compiler: clean tmp $(OBJS)
|
||||||
$(CC) $(CFLAGS) -o $(EXE) $(OBJS)
|
$(CC) $(CFLAGS) -o $(EXE) $(OBJS) $(LDFLAGS)
|
||||||
|
chmod +x ./genx.sh
|
||||||
|
chmod +x ./test.sh
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(EXE)
|
rm -f $(EXE)
|
||||||
rm -rf out
|
rm -rf out
|
||||||
|
rm -rf binaries
|
||||||
rm -rf tmp
|
rm -rf tmp
|
||||||
rm -f *.s
|
rm -f *.s
|
||||||
rm -f *.out
|
rm -f *.out
|
||||||
@ -70,35 +69,36 @@ tmp/runner.o: src/runner.c src/runner.h tmp/flex.h tmp/grammar.tab.h
|
|||||||
|
|
||||||
# ----- Tests -----
|
# ----- Tests -----
|
||||||
test:
|
test:
|
||||||
chmod +x ./check.sh
|
|
||||||
chmod +x ./test.sh
|
chmod +x ./test.sh
|
||||||
$(foreach test, $(TESTS-S1), (./$(EXE) -tok -debug $(test) || true);)
|
chmod +x ./genx.sh
|
||||||
./test.sh sp2
|
./test.sh tests/sprint1/test/ -diff
|
||||||
./test.sh sp3
|
./test.sh tests/sprint2/test/ -diff
|
||||||
./test.sh sp4
|
./test.sh tests/sprint3/test/ -diff
|
||||||
./check.sh
|
./test.sh tests/sprint4/test/ -diff
|
||||||
|
./test.sh tests/given/test/ -diff
|
||||||
|
|
||||||
test-s1:
|
test-s1:
|
||||||
chmod +x ./check.sh
|
|
||||||
chmod +x ./test.sh
|
chmod +x ./test.sh
|
||||||
$(foreach test, $(TESTS-S1), (./$(EXE) -tok -debug $(test) || true);)
|
chmod +x ./genx.sh
|
||||||
./check.sh sp1
|
./test.sh tests/sprint1/test/ -diff
|
||||||
|
|
||||||
test-s2:
|
test-s2:
|
||||||
chmod +x ./check.sh
|
|
||||||
chmod +x ./test.sh
|
chmod +x ./test.sh
|
||||||
./test.sh sp2
|
chmod +x ./genx.sh
|
||||||
./check.sh sp2
|
./test.sh tests/sprint2/test/ -diff
|
||||||
|
|
||||||
test-s3:
|
test-s3:
|
||||||
chmod +x ./check.sh
|
|
||||||
chmod +x ./test.sh
|
chmod +x ./test.sh
|
||||||
./test.sh sp3
|
chmod +x ./genx.sh
|
||||||
./check.sh sp3
|
./test.sh tests/sprint3/test/ -diff
|
||||||
|
|
||||||
test-s4:
|
test-s4:
|
||||||
chmod +x ./check.sh
|
|
||||||
chmod +x ./test.sh
|
chmod +x ./test.sh
|
||||||
./test.sh sp4
|
chmod +x ./genx.sh
|
||||||
./check.sh sp4
|
./test.sh tests/sprint4/test/ -diff
|
||||||
|
|
||||||
|
test-given:
|
||||||
|
chmod +x ./test.sh
|
||||||
|
chmod +x ./genx.sh
|
||||||
|
./test.sh tests/given/test/ -diff
|
||||||
# -----------
|
# -----------
|
88
README.MD
88
README.MD
@ -1,17 +1,89 @@
|
|||||||
# The Translators α Compiler
|
# The Translators α Compiler
|
||||||
#### Members: Annie Slenker, Meyer Simon, Partho Bhattacharya, & Scarlett Kadan
|
#### Members: Annie Slenker, Meyer Simon, Partho Bhattacharya, & Scarlett Kadan
|
||||||
|
|
||||||
## Lexical Analyzer
|
## Alpha Compiler Flags & Expected Results:
|
||||||
* **Undefined Behavior:**
|
### -tok
|
||||||
* Spaces are not required between tokens. For instance, an INTEGER and an ID are valid even if there is no space between them
|
Prints the token stream provided by the Lexical Analyzer to a `.tok` file. Output can be found in `/out/<file>.tok`. Tokenization follows the specified format found in the alpha language spec.
|
||||||
|
|
||||||
|
### -st
|
||||||
|
Prints the symbol table to a file. Follows the format provided in the alpha language spec. if the `-ir` flag is also present, the symbol table will print out temporary variables. Output can be found in `out/<file>.st`.
|
||||||
|
|
||||||
|
### -asc
|
||||||
|
Prints the annotated alpha source code to a file. Will display any syntax errors that are present below the line they occur on. If more than one error is present, the messages will stack. Output can be found in `out/<file>.asc`.
|
||||||
|
|
||||||
|
### -tc
|
||||||
|
Throws type check errors to the asc output file. If the `-asc` flag is not present, no errors will be displayed. Output can be found in `out/<file>.asc`
|
||||||
|
|
||||||
|
### -ir
|
||||||
|
Prints the intermediate code representation stream to a file. Output can be found in `out/<file>.ir`. This flag modifies the `-st` flag, allowing for temporary variables to print out.
|
||||||
|
|
||||||
|
### -cg
|
||||||
|
Prints the alpha program's unique x86 assembly to a `.s` file. Assembly stream is valid x86 code that can be assembled and linked with other .s files. Output can be found in `out/<file>.s`
|
||||||
|
|
||||||
|
### -debug
|
||||||
|
Prints debug messages to the console if present. Our debug messages utilizes a wrapper function for `printf()` called `printdebug()`. This allows for us to file names, code lines, and colors!
|
||||||
|
|
||||||
|
### -help
|
||||||
|
Prints a general help message. (If you read this far, you probably won't need this flag)
|
||||||
|
|
||||||
|
|
||||||
|
## Alpha Tools: Testing & Building
|
||||||
|
We have built a few tools to aid in the development processes. These include `./test.sh` and `./genx.sh`. Below you can find information about each.
|
||||||
|
|
||||||
|
### ./test.sh
|
||||||
|
All tests under sprint 1, 2, 3, & 4 will work with the testing suite, along with running it directly with the alpha executable. These files do not use the `#include` directive, instead opting to define everything used within the file.
|
||||||
|
> **Arguments:**</br>
|
||||||
|
> `-exp` Generate expected output files</br>
|
||||||
|
> `-diff` Compare output files with expected output files</br>
|
||||||
|
> `-help` Show this help message</br>
|
||||||
|
|
||||||
|
> **Usage:**</br>
|
||||||
|
> `./test.sh <file.alpha> [flags]` Run the test on a single file</br>
|
||||||
|
> `./test.sh <directory> [flags]` Run the test on all files in a directory</br>
|
||||||
|
|
||||||
|
> **Examples:** </br>
|
||||||
|
> `./test.sh test.alpha` Runs test flags in header on test.alpha</br>
|
||||||
|
> `./test.sh test/` Runs test flags in header on all .alpha files in test/</br>
|
||||||
|
> `./test.sh test/ -exp` Runs test flags in header on all .alpha files in test/ and generates expected output files</br>
|
||||||
|
> `./test.sh test/ -diff` Runs test flags in header on all .alpha files in test/ and compares output files with expected output files</br>
|
||||||
|
> `./test.sh test/ -exp -diff` Runs test flags in header on all .alpha files in test/ and generates expected output files and compares output files with expected output files</br>
|
||||||
|
|
||||||
|
> **Notes:**</br>
|
||||||
|
> To create a test file, on the first line of the .alpha file, add:</br>
|
||||||
|
> `(* TEST: [ <test_flags> ] *)`</br>
|
||||||
|
> where <test_flags> are the alpha flags to be used. Ex:</br>
|
||||||
|
> `(* TEST: [ -debug -asc -tc ] *)`</br>
|
||||||
|
|
||||||
|
### ./genx.sh
|
||||||
|
GenX is our preprocessor tool. It is able to handle `#include` statements within an alpha file. The tool allows for includes of `.alpha`, `.s`, and `.c` files, given a relative path to them. You can also include our library file `std.alpha` which does not require a relative path.</br>
|
||||||
|
|
||||||
|
**NOTE:** *Due to the nature of include statements, running the alpha compiler on alpha files that use include statements will most likely result in syntax/type errors. When dealing with a file with include statements, it is advised to use GenX.*</br>
|
||||||
|
|
||||||
|
*You can also use the following command to preprocess a file:* `cpp -P -x c -o simple.cpp.alpha simple.alpha`
|
||||||
|
|
||||||
|
> **Arguments:** </br>
|
||||||
|
> `-help` Displays this message</br>
|
||||||
|
|
||||||
|
> **Usage:** </br>
|
||||||
|
> `./genx.sh <file.alpha || file.s>` </br>Generates executable file from <file.alpha></br>
|
||||||
|
|
||||||
|
> **Notes:** </br>
|
||||||
|
> Generates .s and links alpha driver and general library and other includes.</br>
|
||||||
|
|
||||||
|
## Other Notes:
|
||||||
|
|
||||||
|
### Lexical Analyzer:
|
||||||
|
**Undefined Behavior:**</br>
|
||||||
|
* Spaces are not required between tokens. For instance, an INTEGER and an ID are valid even if there is no space between them
|
||||||
```
|
```
|
||||||
Input: *5variable*
|
Input: *5variable*
|
||||||
Output: 2 14 301 "5"
|
Output: 2 14 301 "5"
|
||||||
1 1 101 "variable"
|
1 1 101 "variable"
|
||||||
```
|
```
|
||||||
|
* Added an `#include` token to stop syntax errors from being reported on certain alpha files.
|
||||||
|
|
||||||
## Syntax Analyzer
|
### CG/IR Not Implemented:
|
||||||
* *Incomplete*
|
* Arrays
|
||||||
|
* And conditionals not tested
|
||||||
## Symbol Table
|
* While loops may or may not be working (More testing needed)
|
||||||
* *TODO: Create diagram.*
|
* *...and other small issues*
|
67
check.sh
67
check.sh
@ -1,67 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Diff-Check Tool #
|
|
||||||
# Checks if outputed TOK = exp #
|
|
||||||
# The Translators - Spring 2025 #
|
|
||||||
|
|
||||||
TOK_DIR="out"
|
|
||||||
NOCOLOR='\033[0m'
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
ORANGE='\033[0;33m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
PURPLE='\033[0;35m'
|
|
||||||
CYAN='\033[0;36m'
|
|
||||||
LIGHTGRAY='\033[0;37m'
|
|
||||||
DARKGRAY='\033[1;30m'
|
|
||||||
LIGHTRED='\033[1;31m'
|
|
||||||
LIGHTGREEN='\033[1;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
LIGHTBLUE='\033[1;34m'
|
|
||||||
LIGHTPURPLE='\033[1;35m'
|
|
||||||
LIGHTCYAN='\033[1;36m'
|
|
||||||
WHITE='\033[1;37m'
|
|
||||||
|
|
||||||
compare_files() {
|
|
||||||
local file="$1"
|
|
||||||
local filename=$(basename -- "$file")
|
|
||||||
filename="${filename%.*}"
|
|
||||||
local num=${filename:2:1}
|
|
||||||
local exp="./tests/sprint$num/expected/$filename.expected"
|
|
||||||
|
|
||||||
if [[ -f "$exp" ]]; then
|
|
||||||
diff -q "$file" "$exp" > /dev/null
|
|
||||||
if [[ $? -eq 0 ]]; then
|
|
||||||
echo -e "${GREEN}[✔] ${PURPLE}$filename ${WHITE}passed.${NOCOLOR}"
|
|
||||||
elif [[ ! -s "$file" ]]; then
|
|
||||||
echo -e "${RED}[✘] ${PURPLE}$filename ${WHITE}failed with an empty file. (did it segfault?)${NOCOLOR}"
|
|
||||||
else
|
|
||||||
echo -e "\n${RED}[✘] ${PURPLE}$file ${WHITE}failed with an unexpected value...${NOCOLOR}"
|
|
||||||
diff --color=always "$file" "$exp"
|
|
||||||
echo -e ""
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo -e "${ORANGE}[-] ${PURPLE}$filename ${WHITE}does not have an expected value.${NOCOLOR}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ ! -d "$TOK_DIR" ]]; then
|
|
||||||
echo -e "${RED}[ERROR] ${YELLOW}Directory $TOK_DIR does not exist.${NOCOLOR}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $# -eq 0 ]]; then
|
|
||||||
for file in "$TOK_DIR"/*; do
|
|
||||||
compare_files "$file"
|
|
||||||
done
|
|
||||||
elif [[ $# -eq 1 ]]; then
|
|
||||||
prefix="$1"
|
|
||||||
for file in "$TOK_DIR"/"$prefix"*; do
|
|
||||||
if [[ -f "$file" ]]; then
|
|
||||||
compare_files "$file"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
else
|
|
||||||
echo -e "${LIGHTBLUE}Usage: $0 [sp#]${NOCOLOR}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
234
genx.sh
Executable file
234
genx.sh
Executable file
@ -0,0 +1,234 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# GenX Tool #
|
||||||
|
# The Translators - Spring 2025 #
|
||||||
|
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
ORANGE='\033[0;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
PURPLE='\033[0;35m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
LIGHTGRAY='\033[0;37m'
|
||||||
|
DARKGRAY='\033[1;30m'
|
||||||
|
LIGHTRED='\033[1;31m'
|
||||||
|
LIGHTGREEN='\033[1;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
LIGHTBLUE='\033[1;34m'
|
||||||
|
LIGHTPURPLE='\033[1;35m'
|
||||||
|
LIGHTCYAN='\033[1;36m'
|
||||||
|
WHITE='\033[1;37m'
|
||||||
|
|
||||||
|
alphaToInclude=()
|
||||||
|
cToInclude=()
|
||||||
|
sToInclude=()
|
||||||
|
cToBuild=()
|
||||||
|
sToInclude+=("library/alpha_lib_reg.s")
|
||||||
|
sToInclude+=("library/alpha_driver.s")
|
||||||
|
sToInclude+=("library/std.s")
|
||||||
|
sToInclude+=("library/boundscheck.s")
|
||||||
|
|
||||||
|
filename=""
|
||||||
|
s_name=""
|
||||||
|
backup_file=""
|
||||||
|
|
||||||
|
# -{ FUNC }----------------------------------------------------#
|
||||||
|
|
||||||
|
help() {
|
||||||
|
echo -e "${WHITE}-----{ ${BLUE}GenX.sh Help ${WHITE}}-----\n"
|
||||||
|
echo -e "${YELLOW} Arguments: ${WHITE}"
|
||||||
|
echo -e "${GREEN} -help ${WHITE} Displays this message\n"
|
||||||
|
echo -e "${YELLOW} Usage: ${WHITE}"
|
||||||
|
echo -e "${GREEN} ./genx.sh <file.alpha || file.s>${WHITE} Generates executable file from <file.alpha>\n"
|
||||||
|
echo -e "${YELLOW} Notes: ${WHITE}"
|
||||||
|
echo -e "${ORANGE} Generates .s and links alpha driver and general library and other includes.\n"
|
||||||
|
echo -e "${WHITE}-----------------------------------------\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
printLists() {
|
||||||
|
echo -e "${GREEN}[GenX] ${WHITE}Alpha files to include: ${BLUE}${alphaToInclude[@]}${WHITE}"
|
||||||
|
echo -e "${GREEN}[GenX] ${WHITE}C files to include: ${BLUE}${cToInclude[@]}${WHITE}"
|
||||||
|
echo -e "${GREEN}[GenX] ${WHITE}C files to build: ${BLUE}${cToBuild[@]}${WHITE}"
|
||||||
|
echo -e "${GREEN}[GenX] ${WHITE}S files to include: ${BLUE}${sToInclude[@]}${WHITE}"
|
||||||
|
}
|
||||||
|
|
||||||
|
getIncludes() {
|
||||||
|
while IFS= read -r line || [ -n "$line" ]; do
|
||||||
|
if [[ $line =~ ^#include\ \"[^\"]+\" ]]; then
|
||||||
|
between_quotes=$(echo "$line" | sed -n 's/.*"\([^"]*\)".*/\1/p')
|
||||||
|
extension="${between_quotes##*.}"
|
||||||
|
sed -i "\|$line|d" "$1"
|
||||||
|
|
||||||
|
if [[ $between_quotes == *".alpha" ]]; then
|
||||||
|
path=$(dirname "$1")
|
||||||
|
alpha_file=${path}"/"${between_quotes}
|
||||||
|
|
||||||
|
if [[ -f "library/$between_quotes" ]]; then
|
||||||
|
alphaToInclude+=("library/${between_quotes}")
|
||||||
|
|
||||||
|
elif [[ -f $alpha_file ]]; then
|
||||||
|
alphaToInclude+=("$alpha_file")
|
||||||
|
|
||||||
|
else
|
||||||
|
echo -e "${RED}[GenX] ${YELLOW}File $between_quotes not found!${WHITE}"
|
||||||
|
restoreFileFromBackup "$1"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
elif [[ $between_quotes == *".c" ]]; then
|
||||||
|
path=$(dirname "$1")
|
||||||
|
c_file=${path}"/"${between_quotes}
|
||||||
|
if [[ -f $c_file ]]; then
|
||||||
|
cToBuild+=("$c_file")
|
||||||
|
else
|
||||||
|
echo -e "${RED}[GenX] ${YELLOW}File $between_quotes not found!${WHITE}"
|
||||||
|
restoreFileFromBackup "$1"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
elif [[ $between_quotes == *".s" ]]; then
|
||||||
|
path=$(dirname "$1")
|
||||||
|
s_file=${path}"/"${between_quotes}
|
||||||
|
if [[ -f $s_file ]]; then
|
||||||
|
sToInclude+=("$s_file")
|
||||||
|
else
|
||||||
|
echo -e "${RED}[GenX] ${YELLOW}File $between_quotes not found!${WHITE}"
|
||||||
|
restoreFileFromBackup "$1"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
else
|
||||||
|
echo -e "${RED}[GenX] ${YELLOW}Not able to include file type $extension!${WHITE}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
done < "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ass_c() {
|
||||||
|
for c in "${cToBuild[@]}"; do
|
||||||
|
if [ -f "$c" ]; then
|
||||||
|
c_file_ass=$(basename "$c" .c)
|
||||||
|
c_file_ass=out/$c_file_ass.s
|
||||||
|
cToInclude+=($c_file_ass)
|
||||||
|
gcc -S $c -o $c_file_ass
|
||||||
|
else
|
||||||
|
echo -e "${RED}[GenX] ${YELLOW}File $c not found!${WHITE}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
appendStr() {
|
||||||
|
for alpha_file in "${alphaToInclude[@]}"; do
|
||||||
|
if [ -f "$alpha_file" ]; then
|
||||||
|
temp_file=$(mktemp)
|
||||||
|
cat "$alpha_file" > "$temp_file"
|
||||||
|
cat "$1" >> "$temp_file"
|
||||||
|
mv "$temp_file" "$1"
|
||||||
|
else
|
||||||
|
echo -e "${RED}[GenX] ${YELLOW}File $alpha_file not found!${WHITE}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
ass() {
|
||||||
|
sToInclude_string=$(printf "%s " "${sToInclude[@]}")
|
||||||
|
cToInclude_string=$(printf "%s " "${cToInclude[@]}")
|
||||||
|
gcc "$1" ${cToInclude_string} ${sToInclude_string} -no-pie -o binaries/${2}
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}[GenX] ${WHITE}Done!"
|
||||||
|
else
|
||||||
|
echo -e "${RED}[GenX] ${YELLOW}Error generating executable file!${WHITE}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
restoreFileFromBackup() {
|
||||||
|
if [[ -f "$backup_file" ]]; then
|
||||||
|
cp "$backup_file" "$1"
|
||||||
|
rm "$backup_file"
|
||||||
|
else
|
||||||
|
echo -e "${RED}[GenX] ${YELLOW}Backup file not found!${WHITE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# ----------------------------------------------------{ FUNC }-#
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# -{ INIT }----------------------------------------------------#
|
||||||
|
|
||||||
|
if [ ! -f "./alpha" ]; then
|
||||||
|
echo -e "${RED}[GenX] ${YELLOW}File ./alpha not found! Generating with 'make'.${WHITE}"
|
||||||
|
make
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
help
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "binaries" ]; then
|
||||||
|
mkdir -p binaries
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ----------------------------------------------------{ INIT }-#
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# -{ RUNNER }--------------------------------------------------#
|
||||||
|
|
||||||
|
if [ $# -eq 1 ]; then
|
||||||
|
if [ -f "$1" ]; then
|
||||||
|
filename=$(basename -- "$1")
|
||||||
|
backup_file="${1}.bak"
|
||||||
|
cp "$1" "$backup_file"
|
||||||
|
|
||||||
|
if [[ "$1" == *.alpha ]]; then
|
||||||
|
filename="${filename:0:${#filename}-6}"
|
||||||
|
s_name="out/${filename}.s"
|
||||||
|
|
||||||
|
getIncludes "$1"
|
||||||
|
appendStr "$1"
|
||||||
|
./alpha -ir -tc -asc -cg -st -tok "$1"
|
||||||
|
|
||||||
|
# include a grep here of asc to see if there are any errors
|
||||||
|
|
||||||
|
echo -e "${GREEN}[GenX] ${WHITE}Generated .s file."
|
||||||
|
restoreFileFromBackup "$1"
|
||||||
|
ass_c
|
||||||
|
ass "$s_name" "$filename"
|
||||||
|
printLists
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
elif [[ "$1" == *.s ]]; then
|
||||||
|
echo -e "${GREEN}[GenX] ${WHITE}File $1 is a .s file! (Skipping compiler)${WHITE}"
|
||||||
|
filename="${filename:0:${#filename}-2}"
|
||||||
|
s_name="out/${filename}.s"
|
||||||
|
ass "$s_name" "$filename"
|
||||||
|
restoreFileFromBackup "$1"
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
else
|
||||||
|
echo -e "${RED}[GenX] ${YELLOW}File $1 is not a .alpha file!${WHITE}"
|
||||||
|
restoreFileFromBackup "$1"
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
else
|
||||||
|
echo -e "${RED}[GenX] ${YELLOW}File $1 not found!${WHITE}"
|
||||||
|
restoreFileFromBackup "$1"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
else
|
||||||
|
help
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --------------------------------------------------{ RUNNER }-#
|
81
library/alpha_driver.s
Normal file
81
library/alpha_driver.s
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
.file "alpha_driver.c"
|
||||||
|
.text
|
||||||
|
.globl main
|
||||||
|
.type main, @function
|
||||||
|
main:
|
||||||
|
.LFB0:
|
||||||
|
endbr64
|
||||||
|
pushq %rbp
|
||||||
|
movq %rsp, %rbp
|
||||||
|
subq $48, %rsp
|
||||||
|
movl %edi, -36(%rbp)
|
||||||
|
movq %rsi, -48(%rbp)
|
||||||
|
movl $0, -32(%rbp)
|
||||||
|
cmpl $1, -36(%rbp)
|
||||||
|
jle .L2
|
||||||
|
movq -48(%rbp), %rax
|
||||||
|
addq $8, %rax
|
||||||
|
movq (%rax), %rax
|
||||||
|
movq %rax, %rdi
|
||||||
|
call strlen@PLT
|
||||||
|
movl %eax, -32(%rbp)
|
||||||
|
.L2:
|
||||||
|
movl -32(%rbp), %eax
|
||||||
|
cltq
|
||||||
|
addq $4, %rax
|
||||||
|
movq %rax, %rdi
|
||||||
|
call malloc@PLT
|
||||||
|
movq %rax, -16(%rbp)
|
||||||
|
movq -16(%rbp), %rax
|
||||||
|
movq %rax, -24(%rbp)
|
||||||
|
movq -24(%rbp), %rax
|
||||||
|
movl -32(%rbp), %edx
|
||||||
|
movl %edx, (%rax)
|
||||||
|
cmpl $1, -36(%rbp)
|
||||||
|
jle .L3
|
||||||
|
addq $4, -24(%rbp)
|
||||||
|
movq -48(%rbp), %rax
|
||||||
|
movq 8(%rax), %rax
|
||||||
|
movq %rax, -8(%rbp)
|
||||||
|
movl $0, -28(%rbp)
|
||||||
|
jmp .L4
|
||||||
|
.L5:
|
||||||
|
movl -28(%rbp), %eax
|
||||||
|
movslq %eax, %rdx
|
||||||
|
movq -8(%rbp), %rax
|
||||||
|
addq %rdx, %rax
|
||||||
|
movzbl (%rax), %edx
|
||||||
|
movq -24(%rbp), %rax
|
||||||
|
movb %dl, (%rax)
|
||||||
|
addq $1, -24(%rbp)
|
||||||
|
addl $1, -28(%rbp)
|
||||||
|
.L4:
|
||||||
|
movl -28(%rbp), %eax
|
||||||
|
cmpl -32(%rbp), %eax
|
||||||
|
jl .L5
|
||||||
|
.L3:
|
||||||
|
movq -16(%rbp), %rax
|
||||||
|
movq %rax, %rdi
|
||||||
|
call entry@PLT
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
.LFE0:
|
||||||
|
.size main, .-main
|
||||||
|
.ident "GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0"
|
||||||
|
.section .note.GNU-stack,"",@progbits
|
||||||
|
.section .note.gnu.property,"a"
|
||||||
|
.align 8
|
||||||
|
.long 1f - 0f
|
||||||
|
.long 4f - 1f
|
||||||
|
.long 5
|
||||||
|
0:
|
||||||
|
.string "GNU"
|
||||||
|
1:
|
||||||
|
.align 8
|
||||||
|
.long 0xc0000002
|
||||||
|
.long 3f - 2f
|
||||||
|
2:
|
||||||
|
.long 0x3
|
||||||
|
3:
|
||||||
|
.align 8
|
||||||
|
4:
|
115
library/alpha_lib_reg.s
Normal file
115
library/alpha_lib_reg.s
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
.file "alpha_lib.c"
|
||||||
|
.section .rodata
|
||||||
|
.LC0:
|
||||||
|
.string "%d"
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl printInteger
|
||||||
|
.type printInteger, @function
|
||||||
|
printInteger:
|
||||||
|
.LFB2:
|
||||||
|
pushq %rbp # push old base pointer
|
||||||
|
movq %rsp, %rbp # move base pointer
|
||||||
|
|
||||||
|
subq $16, %rsp # make room on stack
|
||||||
|
movl %edi, -4(%rbp) # spill arg to stack
|
||||||
|
movl -4(%rbp), %eax # move argument to %eax
|
||||||
|
movl %eax, %esi
|
||||||
|
movl $.LC0, %edi
|
||||||
|
movl $0, %eax
|
||||||
|
call printf
|
||||||
|
movl $0, %eax
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
.LFE2:
|
||||||
|
.size printInteger, .-printInteger
|
||||||
|
|
||||||
|
.globl printCharacter
|
||||||
|
.type printCharacter, @function
|
||||||
|
printCharacter:
|
||||||
|
.LFB4:
|
||||||
|
pushq %rbp
|
||||||
|
movq %rsp, %rbp
|
||||||
|
|
||||||
|
subq $16, %rsp
|
||||||
|
movb %dil, %al
|
||||||
|
movb %al, -4(%rbp)
|
||||||
|
movsbl -4(%rbp), %eax
|
||||||
|
movl %eax, %edi
|
||||||
|
call putchar
|
||||||
|
movl $0, %eax
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
.LFE4:
|
||||||
|
.size printCharacter, .-printCharacter
|
||||||
|
|
||||||
|
.section .rodata
|
||||||
|
.LC2:
|
||||||
|
.string "false"
|
||||||
|
.LC3:
|
||||||
|
.string "true"
|
||||||
|
.LC4:
|
||||||
|
.string "%s"
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl printBoolean
|
||||||
|
.type printBoolean, @function
|
||||||
|
printBoolean:
|
||||||
|
.LFB5:
|
||||||
|
pushq %rbp
|
||||||
|
movq %rsp, %rbp
|
||||||
|
subq $16, %rsp
|
||||||
|
movb %dil, -4(%rbp)
|
||||||
|
cmpb $0, -4(%rbp)
|
||||||
|
jne .L8
|
||||||
|
movl $.LC2, %eax
|
||||||
|
jmp .L9
|
||||||
|
.L8:
|
||||||
|
movl $.LC3, %eax
|
||||||
|
.L9:
|
||||||
|
movq %rax, %rsi
|
||||||
|
movl $.LC4, %edi
|
||||||
|
movl $0, %eax
|
||||||
|
call printf
|
||||||
|
movl $0, %eax
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
.LFE5:
|
||||||
|
.size printBoolean, .-printBoolean
|
||||||
|
|
||||||
|
.globl reserve
|
||||||
|
.type reserve, @function
|
||||||
|
reserve:
|
||||||
|
.LFB8:
|
||||||
|
pushq %rbp
|
||||||
|
movq %rsp, %rbp
|
||||||
|
subq $16, %rsp
|
||||||
|
movl %edi, -4(%rbp)
|
||||||
|
movl -4(%rbp), %eax
|
||||||
|
cltq
|
||||||
|
movq %rax, %rdi
|
||||||
|
call malloc
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
.LFE8:
|
||||||
|
.size reserve, .-reserve
|
||||||
|
|
||||||
|
.globl release
|
||||||
|
.type release, @function
|
||||||
|
release:
|
||||||
|
.LFB9:
|
||||||
|
pushq %rbp
|
||||||
|
movq %rsp, %rbp
|
||||||
|
subq $16, %rsp
|
||||||
|
movq %rdi, -8(%rbp)
|
||||||
|
movq -8(%rbp), %rax
|
||||||
|
movq %rax, %rdi
|
||||||
|
call free
|
||||||
|
movl $0, %eax
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
.LFE9:
|
||||||
|
.size release, .-release
|
||||||
|
|
||||||
|
.ident "GCC: (GNU) 6.4.0"
|
||||||
|
.section .note.GNU-stack,"",@progbits
|
61
library/alphastdio.c
Normal file
61
library/alphastdio.c
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int printS(char *str) {
|
||||||
|
if (str == NULL) return -1;
|
||||||
|
printf("%s", str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *inS() {
|
||||||
|
char *buffer = malloc(100);
|
||||||
|
if (buffer == NULL) return NULL;
|
||||||
|
if (fgets(buffer, 100, stdin) == NULL) {
|
||||||
|
free(buffer);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
buffer[strcspn(buffer, "\n")] = 0;
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int printI(int i) {
|
||||||
|
printf("%d", i);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int inI() {
|
||||||
|
int i;
|
||||||
|
char buffer[100];
|
||||||
|
if (fgets(buffer, sizeof(buffer), stdin) == NULL) return 0;
|
||||||
|
if (sscanf(buffer, "%d", &i) != 1) return 0;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int printC(char c) {
|
||||||
|
printf("%c", c);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char inC() {
|
||||||
|
char c;
|
||||||
|
if (scanf(" %c", &c) != 1) return 0;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int printB(bool b) {
|
||||||
|
if (b)
|
||||||
|
printf("true");
|
||||||
|
else
|
||||||
|
printf("false");
|
||||||
|
return 0;
|
||||||
|
}
|
23
library/boundscheck.c
Normal file
23
library/boundscheck.c
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int BoundsError(int d){
|
||||||
|
printf("You are trying to access memory that isn't yours.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoundsCheck(int argc, void * start, ...){
|
||||||
|
va_list argptr;
|
||||||
|
va_start(argptr, start);
|
||||||
|
int index = 0;
|
||||||
|
while (argc){
|
||||||
|
argc--;
|
||||||
|
index = va_arg(argptr, int);
|
||||||
|
if(index > *(int*)start){
|
||||||
|
BoundsError(index);
|
||||||
|
}
|
||||||
|
start += sizeof(int);
|
||||||
|
}
|
||||||
|
va_end(argptr);
|
||||||
|
}
|
112
library/boundscheck.s
Normal file
112
library/boundscheck.s
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
.file "boundscheck.c"
|
||||||
|
.text
|
||||||
|
.section .rodata
|
||||||
|
.align 8
|
||||||
|
.LC0:
|
||||||
|
.string "You are trying to access memory that isn't yours."
|
||||||
|
.text
|
||||||
|
.globl BoundsError
|
||||||
|
.type BoundsError, @function
|
||||||
|
BoundsError:
|
||||||
|
.LFB6:
|
||||||
|
.cfi_startproc
|
||||||
|
pushq %rbp
|
||||||
|
.cfi_def_cfa_offset 16
|
||||||
|
.cfi_offset 6, -16
|
||||||
|
movq %rsp, %rbp
|
||||||
|
.cfi_def_cfa_register 6
|
||||||
|
subq $16, %rsp
|
||||||
|
movl %edi, -4(%rbp)
|
||||||
|
leaq .LC0(%rip), %rax
|
||||||
|
movq %rax, %rdi
|
||||||
|
call puts@PLT
|
||||||
|
movl $1, %edi
|
||||||
|
call exit@PLT
|
||||||
|
.cfi_endproc
|
||||||
|
.LFE6:
|
||||||
|
.size BoundsError, .-BoundsError
|
||||||
|
.globl BoundsCheck
|
||||||
|
.type BoundsCheck, @function
|
||||||
|
BoundsCheck:
|
||||||
|
.LFB7:
|
||||||
|
.cfi_startproc
|
||||||
|
pushq %rbp
|
||||||
|
.cfi_def_cfa_offset 16
|
||||||
|
.cfi_offset 6, -16
|
||||||
|
movq %rsp, %rbp
|
||||||
|
.cfi_def_cfa_register 6
|
||||||
|
subq $240, %rsp
|
||||||
|
movl %edi, -228(%rbp)
|
||||||
|
movq %rsi, -240(%rbp)
|
||||||
|
movq %rdx, -160(%rbp)
|
||||||
|
movq %rcx, -152(%rbp)
|
||||||
|
movq %r8, -144(%rbp)
|
||||||
|
movq %r9, -136(%rbp)
|
||||||
|
testb %al, %al
|
||||||
|
je .L3
|
||||||
|
movaps %xmm0, -128(%rbp)
|
||||||
|
movaps %xmm1, -112(%rbp)
|
||||||
|
movaps %xmm2, -96(%rbp)
|
||||||
|
movaps %xmm3, -80(%rbp)
|
||||||
|
movaps %xmm4, -64(%rbp)
|
||||||
|
movaps %xmm5, -48(%rbp)
|
||||||
|
movaps %xmm6, -32(%rbp)
|
||||||
|
movaps %xmm7, -16(%rbp)
|
||||||
|
.L3:
|
||||||
|
movq %fs:40, %rax
|
||||||
|
movq %rax, -184(%rbp)
|
||||||
|
xorl %eax, %eax
|
||||||
|
movl $16, -208(%rbp)
|
||||||
|
movl $48, -204(%rbp)
|
||||||
|
leaq 16(%rbp), %rax
|
||||||
|
movq %rax, -200(%rbp)
|
||||||
|
leaq -176(%rbp), %rax
|
||||||
|
movq %rax, -192(%rbp)
|
||||||
|
movl $0, -212(%rbp)
|
||||||
|
jmp .L4
|
||||||
|
.L8:
|
||||||
|
subl $1, -228(%rbp)
|
||||||
|
movl -208(%rbp), %eax
|
||||||
|
cmpl $47, %eax
|
||||||
|
ja .L5
|
||||||
|
movq -192(%rbp), %rax
|
||||||
|
movl -208(%rbp), %edx
|
||||||
|
movl %edx, %edx
|
||||||
|
addq %rdx, %rax
|
||||||
|
movl -208(%rbp), %edx
|
||||||
|
addl $8, %edx
|
||||||
|
movl %edx, -208(%rbp)
|
||||||
|
jmp .L6
|
||||||
|
.L5:
|
||||||
|
movq -200(%rbp), %rax
|
||||||
|
leaq 8(%rax), %rdx
|
||||||
|
movq %rdx, -200(%rbp)
|
||||||
|
.L6:
|
||||||
|
movl (%rax), %eax
|
||||||
|
movl %eax, -212(%rbp)
|
||||||
|
movq -240(%rbp), %rax
|
||||||
|
movl (%rax), %eax
|
||||||
|
cmpl %eax, -212(%rbp)
|
||||||
|
jle .L7
|
||||||
|
movl -212(%rbp), %eax
|
||||||
|
movl %eax, %edi
|
||||||
|
call BoundsError
|
||||||
|
.L7:
|
||||||
|
addq $4, -240(%rbp)
|
||||||
|
.L4:
|
||||||
|
cmpl $0, -228(%rbp)
|
||||||
|
jne .L8
|
||||||
|
nop
|
||||||
|
movq -184(%rbp), %rax
|
||||||
|
subq %fs:40, %rax
|
||||||
|
je .L9
|
||||||
|
call __stack_chk_fail@PLT
|
||||||
|
.L9:
|
||||||
|
leave
|
||||||
|
.cfi_def_cfa 7, 8
|
||||||
|
ret
|
||||||
|
.cfi_endproc
|
||||||
|
.LFE7:
|
||||||
|
.size BoundsCheck, .-BoundsCheck
|
||||||
|
.ident "GCC: (GNU) 14.2.1 20250207"
|
||||||
|
.section .note.GNU-stack,"",@progbits
|
35
library/std.alpha
Normal file
35
library/std.alpha
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
(* Standard Alpha Library *)
|
||||||
|
|
||||||
|
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
|
||||||
|
type integer2string: integer -> string
|
||||||
|
type integer2character: integer -> character
|
||||||
|
type integer2Boolean: integer -> Boolean
|
||||||
|
|
||||||
|
|
||||||
|
external function printInteger: integer2integer
|
||||||
|
external function printCharacter: character2integer
|
||||||
|
external function printBoolean: Boolean2integer
|
||||||
|
|
||||||
|
external function printS: string2integer
|
||||||
|
external function printI: integer2integer
|
||||||
|
external function printC: character2integer
|
||||||
|
external function printB: Boolean2integer
|
||||||
|
|
||||||
|
external function inS: integer2string
|
||||||
|
external function inI: integer2integer
|
||||||
|
external function inC: integer2character
|
273
library/std.s
Normal file
273
library/std.s
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
.file "alphastdio.c"
|
||||||
|
.text
|
||||||
|
.section .rodata
|
||||||
|
.LC0:
|
||||||
|
.string "%s"
|
||||||
|
.text
|
||||||
|
.globl printS
|
||||||
|
.type printS, @function
|
||||||
|
printS:
|
||||||
|
.LFB6:
|
||||||
|
.cfi_startproc
|
||||||
|
pushq %rbp
|
||||||
|
.cfi_def_cfa_offset 16
|
||||||
|
.cfi_offset 6, -16
|
||||||
|
movq %rsp, %rbp
|
||||||
|
.cfi_def_cfa_register 6
|
||||||
|
subq $16, %rsp
|
||||||
|
movq %rdi, -8(%rbp)
|
||||||
|
cmpq $0, -8(%rbp)
|
||||||
|
jne .L2
|
||||||
|
movl $-1, %eax
|
||||||
|
jmp .L3
|
||||||
|
.L2:
|
||||||
|
movq -8(%rbp), %rax
|
||||||
|
movq %rax, %rsi
|
||||||
|
leaq .LC0(%rip), %rax
|
||||||
|
movq %rax, %rdi
|
||||||
|
movl $0, %eax
|
||||||
|
call printf@PLT
|
||||||
|
movl $0, %eax
|
||||||
|
.L3:
|
||||||
|
leave
|
||||||
|
.cfi_def_cfa 7, 8
|
||||||
|
ret
|
||||||
|
.cfi_endproc
|
||||||
|
.LFE6:
|
||||||
|
.size printS, .-printS
|
||||||
|
.section .rodata
|
||||||
|
.LC1:
|
||||||
|
.string "\n"
|
||||||
|
.text
|
||||||
|
.globl inS
|
||||||
|
.type inS, @function
|
||||||
|
inS:
|
||||||
|
.LFB7:
|
||||||
|
.cfi_startproc
|
||||||
|
pushq %rbp
|
||||||
|
.cfi_def_cfa_offset 16
|
||||||
|
.cfi_offset 6, -16
|
||||||
|
movq %rsp, %rbp
|
||||||
|
.cfi_def_cfa_register 6
|
||||||
|
subq $16, %rsp
|
||||||
|
movl $100, %edi
|
||||||
|
call malloc@PLT
|
||||||
|
movq %rax, -8(%rbp)
|
||||||
|
cmpq $0, -8(%rbp)
|
||||||
|
jne .L5
|
||||||
|
movl $0, %eax
|
||||||
|
jmp .L6
|
||||||
|
.L5:
|
||||||
|
movq stdin(%rip), %rdx
|
||||||
|
movq -8(%rbp), %rax
|
||||||
|
movl $100, %esi
|
||||||
|
movq %rax, %rdi
|
||||||
|
call fgets@PLT
|
||||||
|
testq %rax, %rax
|
||||||
|
jne .L7
|
||||||
|
movq -8(%rbp), %rax
|
||||||
|
movq %rax, %rdi
|
||||||
|
call free@PLT
|
||||||
|
movl $0, %eax
|
||||||
|
jmp .L6
|
||||||
|
.L7:
|
||||||
|
movq -8(%rbp), %rax
|
||||||
|
leaq .LC1(%rip), %rdx
|
||||||
|
movq %rdx, %rsi
|
||||||
|
movq %rax, %rdi
|
||||||
|
call strcspn@PLT
|
||||||
|
movq -8(%rbp), %rdx
|
||||||
|
addq %rdx, %rax
|
||||||
|
movb $0, (%rax)
|
||||||
|
movq -8(%rbp), %rax
|
||||||
|
.L6:
|
||||||
|
leave
|
||||||
|
.cfi_def_cfa 7, 8
|
||||||
|
ret
|
||||||
|
.cfi_endproc
|
||||||
|
.LFE7:
|
||||||
|
.size inS, .-inS
|
||||||
|
.section .rodata
|
||||||
|
.LC2:
|
||||||
|
.string "%d"
|
||||||
|
.text
|
||||||
|
.globl printI
|
||||||
|
.type printI, @function
|
||||||
|
printI:
|
||||||
|
.LFB8:
|
||||||
|
.cfi_startproc
|
||||||
|
pushq %rbp
|
||||||
|
.cfi_def_cfa_offset 16
|
||||||
|
.cfi_offset 6, -16
|
||||||
|
movq %rsp, %rbp
|
||||||
|
.cfi_def_cfa_register 6
|
||||||
|
subq $16, %rsp
|
||||||
|
movl %edi, -4(%rbp)
|
||||||
|
movl -4(%rbp), %eax
|
||||||
|
movl %eax, %esi
|
||||||
|
leaq .LC2(%rip), %rax
|
||||||
|
movq %rax, %rdi
|
||||||
|
movl $0, %eax
|
||||||
|
call printf@PLT
|
||||||
|
movl $0, %eax
|
||||||
|
leave
|
||||||
|
.cfi_def_cfa 7, 8
|
||||||
|
ret
|
||||||
|
.cfi_endproc
|
||||||
|
.LFE8:
|
||||||
|
.size printI, .-printI
|
||||||
|
.globl inI
|
||||||
|
.type inI, @function
|
||||||
|
inI:
|
||||||
|
.LFB9:
|
||||||
|
.cfi_startproc
|
||||||
|
pushq %rbp
|
||||||
|
.cfi_def_cfa_offset 16
|
||||||
|
.cfi_offset 6, -16
|
||||||
|
movq %rsp, %rbp
|
||||||
|
.cfi_def_cfa_register 6
|
||||||
|
addq $-128, %rsp
|
||||||
|
movq %fs:40, %rax
|
||||||
|
movq %rax, -8(%rbp)
|
||||||
|
xorl %eax, %eax
|
||||||
|
movq stdin(%rip), %rdx
|
||||||
|
leaq -112(%rbp), %rax
|
||||||
|
movl $100, %esi
|
||||||
|
movq %rax, %rdi
|
||||||
|
call fgets@PLT
|
||||||
|
testq %rax, %rax
|
||||||
|
jne .L11
|
||||||
|
movl $0, %eax
|
||||||
|
jmp .L14
|
||||||
|
.L11:
|
||||||
|
leaq -116(%rbp), %rdx
|
||||||
|
leaq -112(%rbp), %rax
|
||||||
|
leaq .LC2(%rip), %rcx
|
||||||
|
movq %rcx, %rsi
|
||||||
|
movq %rax, %rdi
|
||||||
|
movl $0, %eax
|
||||||
|
call __isoc99_sscanf@PLT
|
||||||
|
cmpl $1, %eax
|
||||||
|
je .L13
|
||||||
|
movl $0, %eax
|
||||||
|
jmp .L14
|
||||||
|
.L13:
|
||||||
|
movl -116(%rbp), %eax
|
||||||
|
.L14:
|
||||||
|
movq -8(%rbp), %rdx
|
||||||
|
subq %fs:40, %rdx
|
||||||
|
je .L15
|
||||||
|
call __stack_chk_fail@PLT
|
||||||
|
.L15:
|
||||||
|
leave
|
||||||
|
.cfi_def_cfa 7, 8
|
||||||
|
ret
|
||||||
|
.cfi_endproc
|
||||||
|
.LFE9:
|
||||||
|
.size inI, .-inI
|
||||||
|
.globl printC
|
||||||
|
.type printC, @function
|
||||||
|
printC:
|
||||||
|
.LFB10:
|
||||||
|
.cfi_startproc
|
||||||
|
pushq %rbp
|
||||||
|
.cfi_def_cfa_offset 16
|
||||||
|
.cfi_offset 6, -16
|
||||||
|
movq %rsp, %rbp
|
||||||
|
.cfi_def_cfa_register 6
|
||||||
|
subq $16, %rsp
|
||||||
|
movl %edi, %eax
|
||||||
|
movb %al, -4(%rbp)
|
||||||
|
movsbl -4(%rbp), %eax
|
||||||
|
movl %eax, %edi
|
||||||
|
call putchar@PLT
|
||||||
|
movl $0, %eax
|
||||||
|
leave
|
||||||
|
.cfi_def_cfa 7, 8
|
||||||
|
ret
|
||||||
|
.cfi_endproc
|
||||||
|
.LFE10:
|
||||||
|
.size printC, .-printC
|
||||||
|
.section .rodata
|
||||||
|
.LC3:
|
||||||
|
.string " %c"
|
||||||
|
.text
|
||||||
|
.globl inC
|
||||||
|
.type inC, @function
|
||||||
|
inC:
|
||||||
|
.LFB11:
|
||||||
|
.cfi_startproc
|
||||||
|
pushq %rbp
|
||||||
|
.cfi_def_cfa_offset 16
|
||||||
|
.cfi_offset 6, -16
|
||||||
|
movq %rsp, %rbp
|
||||||
|
.cfi_def_cfa_register 6
|
||||||
|
subq $16, %rsp
|
||||||
|
movq %fs:40, %rax
|
||||||
|
movq %rax, -8(%rbp)
|
||||||
|
xorl %eax, %eax
|
||||||
|
leaq -9(%rbp), %rax
|
||||||
|
movq %rax, %rsi
|
||||||
|
leaq .LC3(%rip), %rax
|
||||||
|
movq %rax, %rdi
|
||||||
|
movl $0, %eax
|
||||||
|
call __isoc99_scanf@PLT
|
||||||
|
cmpl $1, %eax
|
||||||
|
je .L19
|
||||||
|
movl $0, %eax
|
||||||
|
jmp .L21
|
||||||
|
.L19:
|
||||||
|
movzbl -9(%rbp), %eax
|
||||||
|
.L21:
|
||||||
|
movq -8(%rbp), %rdx
|
||||||
|
subq %fs:40, %rdx
|
||||||
|
je .L22
|
||||||
|
call __stack_chk_fail@PLT
|
||||||
|
.L22:
|
||||||
|
leave
|
||||||
|
.cfi_def_cfa 7, 8
|
||||||
|
ret
|
||||||
|
.cfi_endproc
|
||||||
|
.LFE11:
|
||||||
|
.size inC, .-inC
|
||||||
|
.section .rodata
|
||||||
|
.LC4:
|
||||||
|
.string "true"
|
||||||
|
.LC5:
|
||||||
|
.string "false"
|
||||||
|
.text
|
||||||
|
.globl printB
|
||||||
|
.type printB, @function
|
||||||
|
printB:
|
||||||
|
.LFB12:
|
||||||
|
.cfi_startproc
|
||||||
|
pushq %rbp
|
||||||
|
.cfi_def_cfa_offset 16
|
||||||
|
.cfi_offset 6, -16
|
||||||
|
movq %rsp, %rbp
|
||||||
|
.cfi_def_cfa_register 6
|
||||||
|
subq $16, %rsp
|
||||||
|
movl %edi, %eax
|
||||||
|
movb %al, -4(%rbp)
|
||||||
|
cmpb $0, -4(%rbp)
|
||||||
|
je .L24
|
||||||
|
leaq .LC4(%rip), %rax
|
||||||
|
movq %rax, %rdi
|
||||||
|
movl $0, %eax
|
||||||
|
call printf@PLT
|
||||||
|
jmp .L25
|
||||||
|
.L24:
|
||||||
|
leaq .LC5(%rip), %rax
|
||||||
|
movq %rax, %rdi
|
||||||
|
movl $0, %eax
|
||||||
|
call printf@PLT
|
||||||
|
.L25:
|
||||||
|
movl $0, %eax
|
||||||
|
leave
|
||||||
|
.cfi_def_cfa 7, 8
|
||||||
|
ret
|
||||||
|
.cfi_endproc
|
||||||
|
.LFE12:
|
||||||
|
.size printB, .-printB
|
||||||
|
.ident "GCC: (GNU) 14.2.1 20250207"
|
||||||
|
.section .note.GNU-stack,"",@progbits
|
404
src/codegen.c
404
src/codegen.c
@ -2,12 +2,18 @@
|
|||||||
/* The Translators - Spring 2025 */
|
/* The Translators - Spring 2025 */
|
||||||
|
|
||||||
#include "codegen.h"
|
#include "codegen.h"
|
||||||
|
int paramCount = 0;
|
||||||
int generate(){
|
int funDec = 0;
|
||||||
|
int generate() {
|
||||||
offset = 0;
|
offset = 0;
|
||||||
|
currentsp = 0;
|
||||||
Instruction *i = begin;
|
Instruction *i = begin;
|
||||||
|
funList = NULL;
|
||||||
|
// temporary
|
||||||
|
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;
|
||||||
@ -74,14 +80,35 @@ int generate(){
|
|||||||
case E_ADDRESS_OF:
|
case E_ADDRESS_OF:
|
||||||
generateAddressOf(i);
|
generateAddressOf(i);
|
||||||
break;
|
break;
|
||||||
default:
|
case E_FUNC_START:
|
||||||
;
|
generateFunctionStart(i);
|
||||||
|
break;
|
||||||
|
case E_FUNC_DEC:
|
||||||
|
generateFunctionDec(i);
|
||||||
|
break;
|
||||||
|
default:;
|
||||||
}
|
}
|
||||||
i = i->next;
|
i = i->next;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isAnActualFunction(TableNode *tn) {
|
||||||
|
FunDecList *fdl = funList;
|
||||||
|
while (fdl != NULL) {
|
||||||
|
printf("%s %s, %s %s\n", getName(fdl->tn), getType(fdl->tn), getName(tn), getType(tn));
|
||||||
|
if (tn == fdl->tn) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
fdl = fdl ->next;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void align(TableNode *tn) {
|
||||||
|
int size = getPrimSize(getTypeEntry(tn));
|
||||||
|
offset += offset % size;
|
||||||
|
}
|
||||||
CGNode *getNextCG(CGNode *cg) {
|
CGNode *getNextCG(CGNode *cg) {
|
||||||
if (cg == NULL) {
|
if (cg == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -118,16 +145,31 @@ CGNode *findCG(TableNode *tn) {
|
|||||||
CGNode *addCG(TableNode *tn, int sp) {
|
CGNode *addCG(TableNode *tn, int sp) {
|
||||||
CGNode *cg = calloc(1, sizeof(CGNode));
|
CGNode *cg = calloc(1, sizeof(CGNode));
|
||||||
cg->tn = tn;
|
cg->tn = tn;
|
||||||
offset += 4; // <- quick fix getPrimSize(getTypeEntry(tn))
|
align(tn);
|
||||||
|
offset += getPrimSize(getTypeEntry(tn));
|
||||||
cg->address = offset;
|
cg->address = offset;
|
||||||
cg->next = cgList;
|
cg->next = cgList;
|
||||||
cgList = cg;
|
cgList = cg;
|
||||||
return cg;
|
return cg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int generateFunctionDec(Instruction *i) {
|
||||||
|
FunDecList * fd = calloc(1, sizeof(FunDecList));
|
||||||
|
CGNode *cg = addCG(getResult(i),offset);
|
||||||
|
// printf("%d\n", getAddress(cg)+currentsp);
|
||||||
|
offset += 8;
|
||||||
|
fd->tn = getResult(i);
|
||||||
|
fd->next = funList;
|
||||||
|
funList = fd;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
int generateLabel(Instruction *inst) {
|
int generateLabel(Instruction *inst) {
|
||||||
|
if (inst == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
fprintf(cg_flag, ".L%d:\n", getLabel(inst));
|
fprintf(cg_flag, ".L%d:\n", getLabel(inst));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int generateAdd(Instruction *inst) {
|
int generateAdd(Instruction *inst) {
|
||||||
@ -149,9 +191,8 @@ 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(op1));
|
CGNode *op2CG = findCG(getTN(op2));
|
||||||
if (op1CG == NULL) {
|
if (op1CG == NULL) {
|
||||||
printdebug("generateAdd failed, %s is not initialized/in CG", getName(getTN(op1)));
|
printdebug("generateAdd failed, %s is not initialized/in CG", getName(getTN(op1)));
|
||||||
return -1;
|
return -1;
|
||||||
@ -161,9 +202,8 @@ int generateAdd(Instruction *inst) {
|
|||||||
printdebug("generateAdd failed, %s is not initialized/in CG", getName(getTN(op2)));
|
printdebug("generateAdd failed, %s is not initialized/in CG", getName(getTN(op2)));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#addition start\n", getAddress(op1CG));
|
fprintf(cg_flag, "\n\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%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));
|
fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\t#addition end\n", getAddress(cg));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -205,7 +245,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:
|
||||||
@ -274,7 +314,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;
|
||||||
}
|
}
|
||||||
@ -311,7 +351,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;
|
||||||
}
|
}
|
||||||
@ -349,10 +389,10 @@ int generateOr(Instruction *inst) {
|
|||||||
|
|
||||||
int label = label_gen();
|
int label = label_gen();
|
||||||
|
|
||||||
fprintf(cg_flag, "\tcmpl\t$0, %d(%%rbp)\t#start or\n", getAddress(op1CG));
|
fprintf(cg_flag, "\tcmpb\t$0, %d(%%rbp)\t#start or\n", getAddress(op1CG));
|
||||||
fprintf(cg_flag, "\tjne\t.L%dor2\n", label);
|
fprintf(cg_flag, "\tjne\t.L%dor2\n", label);
|
||||||
|
|
||||||
fprintf(cg_flag, "\tcmpl\t$0, %d(%%rbp)\n", getAddress(op2CG));
|
fprintf(cg_flag, "\tcmpb\t$0, %d(%%rbp)\n", getAddress(op2CG));
|
||||||
fprintf(cg_flag, "\tje\t.L%dor3\n", label);
|
fprintf(cg_flag, "\tje\t.L%dor3\n", label);
|
||||||
|
|
||||||
fprintf(cg_flag, ".L%dor2:\n", label);
|
fprintf(cg_flag, ".L%dor2:\n", label);
|
||||||
@ -400,10 +440,10 @@ int generateAnd(Instruction *inst) {
|
|||||||
}
|
}
|
||||||
int label = label_gen();
|
int label = label_gen();
|
||||||
|
|
||||||
fprintf(cg_flag, "\tcmpl\t$0, %d(%%rbp)\t#start and\n", getAddress(op1CG));
|
fprintf(cg_flag, "\tcmpb\t$0, %d(%%rbp)\t#start and\n", getAddress(op1CG));
|
||||||
fprintf(cg_flag, "\tje\t.L%dor2\n", label);
|
fprintf(cg_flag, "\tje\t.L%dor2\n", label);
|
||||||
|
|
||||||
fprintf(cg_flag, "\tcmpl\t$0, %d(%%rbp)\n", getAddress(op2CG));
|
fprintf(cg_flag, "\tcmpb\t$0, %d(%%rbp)\n", getAddress(op2CG));
|
||||||
fprintf(cg_flag, "\tje\t.L%dor2\n", label);
|
fprintf(cg_flag, "\tje\t.L%dor2\n", label);
|
||||||
|
|
||||||
fprintf(cg_flag, "\tmovl\t$1, %%eax\n");
|
fprintf(cg_flag, "\tmovl\t$1, %%eax\n");
|
||||||
@ -474,7 +514,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;
|
||||||
@ -484,43 +523,106 @@ int generateAssign(Instruction *inst) {
|
|||||||
cg = addCG(getResult(inst), offset);
|
cg = addCG(getResult(inst), offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CGNode *op1CG = findCG(getTN(op1));
|
||||||
|
|
||||||
//add option for constant assignment (should be easy)
|
//add option for constant assignment (should be easy)
|
||||||
if (isConst(op1) == true) {
|
if (isConst(op1) == true) {
|
||||||
fprintf(cg_flag, "\tmovl\t$%d, %d(%%rbp)\t#constant assign\n", getConst(op1), getAddress(cg));
|
char *movtype;
|
||||||
|
char *reg;
|
||||||
|
TableNode *typetn = getTypeEntry(getResult(inst));
|
||||||
|
if (typetn == integ) {
|
||||||
|
movtype = "movl";
|
||||||
|
reg = "%eax";
|
||||||
|
} else if (typetn == boo) {
|
||||||
|
movtype = "movb";
|
||||||
|
reg = "%al";
|
||||||
|
} else if (typetn == chara) {
|
||||||
|
movtype = "movb";
|
||||||
|
reg = "%al";
|
||||||
|
} else {
|
||||||
|
movtype = "movq";
|
||||||
|
reg = "%rax";
|
||||||
|
}
|
||||||
|
fprintf(cg_flag, "\t%s\t$%d, %d(%%rbp)\t#constant assign\n",movtype, getConst(op1), getAddress(cg));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGNode *op1CG = findCG(getTN(op1));
|
else if (op1CG == NULL) {
|
||||||
if (op1CG == NULL) {
|
printdebug("generateAssign failed, %s is not constant but not in CGlist", getName(getTN(op1)));
|
||||||
printf("failed here\n");
|
|
||||||
printdebug("generateAssign failed, op1 is not constant but not in CGlist");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (getAdInfoType(getTN(op1)) != TYPE_FUNCTION_DECLARATION || table_lookup(getAncestor(cur), getName(getTN(op1))) == undefined){
|
||||||
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#assign start\n", getAddress(op1CG));
|
char *movtype;
|
||||||
fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\t#assign end\n", getAddress(cg));
|
char *reg;
|
||||||
|
TableNode *typetn = getTypeEntry(getTN(op1));
|
||||||
|
if (typetn == integ) {
|
||||||
|
movtype = "movl";
|
||||||
|
reg = "%eax";
|
||||||
|
} else if (typetn == boo) {
|
||||||
|
movtype = "movb";
|
||||||
|
reg = "%al";
|
||||||
|
} else if (typetn == chara) {
|
||||||
|
movtype = "movb";
|
||||||
|
reg = "%al";
|
||||||
|
} else {
|
||||||
|
movtype = "movq";
|
||||||
|
reg = "%rax";
|
||||||
|
}
|
||||||
|
fprintf(cg_flag, "\t%s\t%d(%%rbp), %s\t#assign start\n",movtype, getAddress(op1CG), reg);
|
||||||
|
fprintf(cg_flag, "\t%s\t%s, %d(%%rbp)\t#assign end\n", movtype,reg,getAddress(cg));
|
||||||
|
} else {
|
||||||
|
fprintf(cg_flag, "\tmovl\t$%s,%%eax\t#assign function\n", getName(getTN(op1)));
|
||||||
|
fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\t#assign function end\n", getAddress(cg));
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int generateGoto(Instruction *instruction){
|
int generateGoto(Instruction *inst) {
|
||||||
|
fprintf(cg_flag, "\tjmp\t.L%d\n", getLabel(inst));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int generateCondGoto(Instruction *inst) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int generateCondGoto(Instruction *instruction) {
|
int generateIfTrue(Instruction *inst) {
|
||||||
|
TNodeOrConst *op1 = getOperand1(inst);
|
||||||
|
|
||||||
|
if (op1 == NULL) {
|
||||||
|
printdebug("%sgenerateIfTrue failed, NULL operand", COLOR_RED);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGNode *cg = findCG(getTN(op1));
|
||||||
|
if (cg == NULL) {
|
||||||
|
printdebug("generateIfTrue failed, operand not on stack");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(cg_flag, "\tcmpb\t$0, %d(%%rbp)\t#if true start\n", getAddress(cg));
|
||||||
|
fprintf(cg_flag, "\tjne\t.L%d\t\t#if true end\n", getLabel(inst));
|
||||||
}
|
}
|
||||||
|
|
||||||
int generateIfTrue(Instruction *instruction){
|
int generateIfFalse(Instruction *inst) {
|
||||||
|
TNodeOrConst *op1 = getOperand1(inst);
|
||||||
|
|
||||||
|
if (op1 == NULL) {
|
||||||
|
printdebug("%sgenerateIfFalse failed, NULL operand", COLOR_RED);
|
||||||
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
|
}
|
||||||
|
|
||||||
|
CGNode *cg = findCG(getTN(op1));
|
||||||
|
if (cg == NULL) {
|
||||||
|
printdebug("generateIfFalse failed, operand not on stack");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(cg_flag, "\tcmpb\t$0, %d(%%rbp)\t#if false start\n", getAddress(cg));
|
||||||
|
fprintf(cg_flag, "\tje\t.L%d\t\t#if false end\n", getLabel(inst));
|
||||||
}
|
}
|
||||||
|
|
||||||
int generateIfFalse(Instruction *instruction){
|
int generateLessThan(Instruction *inst) {
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int generateLessThan(Instruction *inst){
|
|
||||||
/*
|
/*
|
||||||
Both immediate:
|
Both immediate:
|
||||||
One immediate:
|
One immediate:
|
||||||
@ -558,7 +660,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:
|
||||||
@ -588,31 +690,233 @@ int generateEqualTo(Instruction *inst){
|
|||||||
printdebug("generateLessThan failed, %s is not initialized/in CG", getName(getTN(op2)));
|
printdebug("generateLessThan failed, %s is not initialized/in CG", getName(getTN(op2)));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
char *movtype;
|
||||||
|
char *reg;
|
||||||
|
char *cmptype;
|
||||||
|
TableNode *typetn = getTypeEntry(getTN(op1));
|
||||||
|
if (typetn == integ) {
|
||||||
|
movtype = "movl";
|
||||||
|
|
||||||
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#equal to start\n", getAddress(op1CG));
|
cmptype = "cmpl";
|
||||||
fprintf(cg_flag, "\tcmpl\t%d(%%rbp), %%eax\n", getAddress(op2CG));
|
reg = "%eax";
|
||||||
|
} else if (typetn == boo) {
|
||||||
|
cmptype = "cmpb";
|
||||||
|
movtype = "movb";
|
||||||
|
reg = "%al";
|
||||||
|
} else if (typetn == chara) {
|
||||||
|
cmptype = "cmpb";
|
||||||
|
movtype = "movb";
|
||||||
|
reg = "%al";
|
||||||
|
} else {
|
||||||
|
cmptype = "cmpq";
|
||||||
|
movtype = "movq";
|
||||||
|
reg = "%rax";
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(cg_flag, "\t%s\t%d(%%rbp), %s\t#equal to start\n", movtype, getAddress(op1CG), reg);
|
||||||
|
fprintf(cg_flag, "\t%s\t%d(%%rbp), %s\n", cmptype, getAddress(op2CG), reg);
|
||||||
fprintf(cg_flag, "\tsete\t%%al\n");
|
fprintf(cg_flag, "\tsete\t%%al\n");
|
||||||
|
fprintf(cg_flag, "\tmovb\t$0, %d(%%rbp)\n", getAddress(cg));
|
||||||
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 *instruction){
|
int generateCall(Instruction *inst) {
|
||||||
|
paramCount = 0;
|
||||||
|
TNodeOrConst *op1 = getOperand1(inst);
|
||||||
|
TNodeOrConst *op2 = getOperand2(inst);
|
||||||
|
if (op1 == NULL) {
|
||||||
|
printdebug("%sgenerateFunctionCall failed, NULL operand", COLOR_RED);
|
||||||
return -1;
|
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){
|
if (op1 == NULL) {
|
||||||
|
printdebug("%sgenerateFunctionCall failed, NULL operand", COLOR_RED);
|
||||||
return -1;
|
return -1;
|
||||||
//will movl the result into the appropriate register and move the stack pointer/offset stuff back to correct value
|
}
|
||||||
|
|
||||||
|
if (getTN(op1) == NULL) {
|
||||||
|
printdebug("generateFunctionCall failed, NULL tablenode1");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (table_lookup(getAncestor(cur),getName(getTN(op1)))!=undefined) {
|
||||||
|
fprintf(cg_flag, "\tcall %s\n", getName(getTN(op1)));
|
||||||
|
} else {
|
||||||
|
// printf("%s\n", getName(getTN(op1)));
|
||||||
|
if (findCG(getTN(op1)) == NULL) {
|
||||||
|
//printf("generateFunctionCall failed, function not in stack");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fprintf(cg_flag, "\tmovq\t%d(%%rbp), %%rax\t#call %s!\n", getAddress(findCG(getTN(op1))), getName(getTN(op1)));
|
||||||
|
fprintf(cg_flag, "\tcall *%%rax\n");
|
||||||
|
}
|
||||||
|
//if (getTN(op2) == NULL) {
|
||||||
|
//printdebug("generateFunctionCall failed, NULL tablenode2");
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
|
//now for the return
|
||||||
|
CGNode *cg = findCG(getResult(inst));
|
||||||
|
|
||||||
|
if (cg == NULL) {
|
||||||
|
cg = addCG(getResult(inst), offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\t#store return from call\n", getAddress(cg));
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
int generateCopyRight(Instruction *instruction){
|
int generateReturn(Instruction *inst) {
|
||||||
|
TNodeOrConst *op1 = getOperand1(inst);
|
||||||
|
CGNode *cg;
|
||||||
|
|
||||||
|
if (op1 == NULL) {
|
||||||
|
printdebug("generateReturn failed, NULL operand");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cg = findCG(getTN(op1));
|
||||||
|
if (cg == NULL) {
|
||||||
|
printdebug("generateReturn failed, trying to return %s not in CGList", getName(getTN(op1)));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (table_lookup(getAncestor(cur), getName(getTN(op1))) != undefined) {
|
||||||
|
fprintf(cg_flag, "\tmovl\t$%s,%%eax\t#return a function\n", getName(getTN(op1)));
|
||||||
|
} else {
|
||||||
|
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#return %s\n", getAddress(cg), getName(getTN(op1)));
|
||||||
|
}
|
||||||
|
fprintf(cg_flag, "\tleave\n");
|
||||||
|
fprintf(cg_flag, "\tret\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int generateCopyRight(Instruction *inst) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int generateCopyLeft(Instruction *instruction){
|
int generateCopyLeft(Instruction *inst) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int generateAddressOf(Instruction *instruction){
|
int generateAddressOf(Instruction *inst) {
|
||||||
return -1;
|
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
|
int generateParam(Instruction *inst) {
|
||||||
|
TNodeOrConst *op1 = getOperand1(inst);
|
||||||
|
//fprintf(stderr, "generate param reached\n");
|
||||||
|
if (op1 == NULL) {
|
||||||
|
printdebug("generateParam failed, NULL operand");
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGNode *op1CG = findCG(getTN(op1));
|
||||||
|
if (op1CG == NULL) {
|
||||||
|
printdebug("generateParam failed, %s is not in CGlist", getName(getTN(op1)));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
paramCount += 1;
|
||||||
|
switch(paramCount) {
|
||||||
|
case 1:
|
||||||
|
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %s\t#adding param start\n", getAddress(op1CG), REG1);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %s\t#adding param start\n", getAddress(op1CG), REG2);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %s\t#adding param start\n", getAddress(op1CG), REG3);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %s\t#adding param start\n", getAddress(op1CG), REG4);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %s\t#adding param start\n", getAddress(op1CG), REG5);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %s\t#adding param start\n", getAddress(op1CG), REG6);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
align(getTN(op1));
|
||||||
|
offset += getPrimSize(getTypeEntry(getTN(op1)));
|
||||||
|
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#adding param start\n", getAddress(op1CG));
|
||||||
|
fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\t#adding param end\n", offset - getPrimSize(getTypeEntry(getTN(op1))));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int generateFunctionStart(Instruction *inst) {
|
||||||
|
currentsp = offset;
|
||||||
|
TableNode *funDecTN = getResult(inst);
|
||||||
|
|
||||||
|
if (funDecTN == NULL) {
|
||||||
|
printdebug("generateFunctionStart failed, NULL tablenode");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//this is independent of parameters:
|
||||||
|
fprintf(cg_flag, "%s:\n", getName(funDecTN));
|
||||||
|
fprintf(cg_flag, "\tpushq\t%%rbp\n");
|
||||||
|
fprintf(cg_flag, "\tmovq\t%%rsp, %%rbp\n");
|
||||||
|
fprintf(cg_flag, "\tsubq\t$%d, %%rsp\n", getStackSize());
|
||||||
|
|
||||||
|
//now we need to add the CGs of nodes to the CG list by doing assign from the
|
||||||
|
// have function declararation node
|
||||||
|
//declaration ->getType: if record, go through each element and load param from stack and store to correct tn cg
|
||||||
|
// if not, go get one element of type of param
|
||||||
|
//declaration ->getType->getDefinitionScope?: go through first n entries to get table nodes for params
|
||||||
|
|
||||||
|
TableNode *paramTN = getParameter(getTypeEntry(funDecTN));
|
||||||
|
SymbolTable *st = getFunScope(funDecTN);
|
||||||
|
int paramOffset = 16;
|
||||||
|
TableNode *tnToAdd = getFirstEntry(st);
|
||||||
|
if (getAdInfoType(paramTN) != TYPE_RECORD_TYPE) {
|
||||||
|
CGNode *paramCG = addCG(tnToAdd, offset);
|
||||||
|
int size = getPrimSize(getTypeEntry(tnToAdd));
|
||||||
|
paramOffset += getPrimSize(getTypeEntry(tnToAdd));
|
||||||
|
fprintf(cg_flag, "\tmovl\t%%edi, %d(%%rbp)\t#FunctionStart1param end\n", getAddress(paramCG));
|
||||||
|
} else {
|
||||||
|
int numParams = getRecLength(paramTN);
|
||||||
|
for (int i = numParams; i > 0; i--) {
|
||||||
|
CGNode *paramCG = addCG(tnToAdd, offset);
|
||||||
|
switch(i) {
|
||||||
|
case 1:
|
||||||
|
fprintf(cg_flag, "\tmovl\t%s, %d(%%rbp)\t#FunctionStart1param end\n", REG1, getAddress(paramCG));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
fprintf(cg_flag, "\tmovl\t%s, %d(%%rbp)\t#FunctionStart1param end\n", REG2, getAddress(paramCG));
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
fprintf(cg_flag, "\tmovl\t%s, %d(%%rbp)\t#FunctionStart1param end\n", REG3, getAddress(paramCG));
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
fprintf(cg_flag, "\tmovl\t%s, %d(%%rbp)\t#FunctionStart1param end\n", REG4, getAddress(paramCG));
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
fprintf(cg_flag, "\tmovl\t%s, %d(%%rbp)\t#FunctionStart1param end\n", REG5, getAddress(paramCG));
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
fprintf(cg_flag, "\tmovl\t%s, %d(%%rbp)\t#FunctionStart1param end\n", REG6, getAddress(paramCG));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
int size = getPrimSize(getTypeEntry(tnToAdd));
|
||||||
|
paramOffset += size;
|
||||||
|
offset += getPrimSize(getTypeEntry(tnToAdd));
|
||||||
|
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#FunctionStart1Param start\n", paramOffset);
|
||||||
|
fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\t#FunctionStart1param end\n", getAddress(paramCG));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
tnToAdd = getNextEntry(tnToAdd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if (strcmp(getName(funDecTN), "entry") == 0) {
|
||||||
|
if (funList == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
TableNode *funDec;
|
||||||
|
while (funList != NULL) {
|
||||||
|
funDec = funList->tn;
|
||||||
|
CGNode *cg = findCG(getResult(inst));
|
||||||
|
fprintf(cg_flag, "\tmovq\t$%s, %d(%%rbp)\t#storing function declaration\n", getName(funDec), getAddress(cg));
|
||||||
|
funList = funList->next;
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
return 0;
|
||||||
}
|
}
|
@ -13,20 +13,34 @@
|
|||||||
#include "intermediate_code.h"
|
#include "intermediate_code.h"
|
||||||
#include "symbol_table.h"
|
#include "symbol_table.h"
|
||||||
|
|
||||||
|
#define REG1 "%edi"
|
||||||
|
#define REG2 "%esi"
|
||||||
|
#define REG3 "%edx"
|
||||||
|
#define REG4 "%ecx"
|
||||||
|
#define REG5 "%r8d"
|
||||||
|
#define REG6 "%r9d"
|
||||||
|
|
||||||
extern FILE *cg_flag;
|
extern FILE *cg_flag;
|
||||||
|
|
||||||
typedef struct CGNode {
|
typedef struct CGNode {
|
||||||
TableNode *tn;
|
TableNode *tn;
|
||||||
int address;
|
int address;
|
||||||
CGNode *next;
|
struct CGNode *next;
|
||||||
} CGNode;
|
} CGNode;
|
||||||
|
|
||||||
|
typedef struct FunDecList {
|
||||||
|
TableNode *tn;
|
||||||
|
struct FunDecList *next;
|
||||||
|
} FunDecList;
|
||||||
|
|
||||||
|
bool isAnActualFunction(TableNode *tn);
|
||||||
int generate();
|
int generate();
|
||||||
CGNode *getNextCG(CGNode *cg);
|
CGNode *getNextCG(CGNode *cg);
|
||||||
int getAddress(CGNode *cg);
|
int getAddress(CGNode *cg);
|
||||||
TableNode *getTNofCG(CGNode *cg);
|
TableNode *getTNofCG(CGNode *cg);
|
||||||
CGNode *findCG(TableNode *tn);
|
CGNode *findCG(TableNode *tn);
|
||||||
CGNode *addCG(TableNode *tn, int sp);
|
CGNode *addCG(TableNode *tn, int sp);
|
||||||
|
int generateFunctionDec(Instruction *inst);
|
||||||
int generateLabel(Instruction *inst);
|
int generateLabel(Instruction *inst);
|
||||||
int generateAdd(Instruction *inst);
|
int generateAdd(Instruction *inst);
|
||||||
int generateSub(Instruction *instruction);
|
int generateSub(Instruction *instruction);
|
||||||
@ -50,11 +64,14 @@ int generateCopyRight(Instruction *instruction);
|
|||||||
int generateCopyLeft(Instruction *instruction);
|
int generateCopyLeft(Instruction *instruction);
|
||||||
int generateAddressOf(Instruction *instruction);
|
int generateAddressOf(Instruction *instruction);
|
||||||
int generateParam(Instruction *instruction);
|
int generateParam(Instruction *instruction);
|
||||||
|
int generateFunctionStart(Instruction *instruction);
|
||||||
|
|
||||||
extern int label_count;
|
extern int label_count;
|
||||||
extern Instruction *begin;
|
extern Instruction *begin;
|
||||||
extern Instruction *current;
|
extern Instruction *current;
|
||||||
|
extern SymbolTable *top;
|
||||||
|
|
||||||
extern int offset;
|
extern int offset;
|
||||||
extern int currentsp;
|
extern int currentsp;
|
||||||
extern CGNode *cgList;
|
extern CGNode *cgList;
|
||||||
|
extern FunDecList *funList;
|
||||||
|
@ -8,8 +8,11 @@
|
|||||||
#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 bool entry_flag;
|
||||||
|
extern void insert_code_line(char *error_message, int line_number);
|
||||||
|
extern bool contains_errors;
|
||||||
|
extern int context;
|
||||||
|
//extern TableNode* comparator;
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ERROR_RUNTIME = 1,
|
ERROR_RUNTIME = 1,
|
||||||
ERROR_SYNTAX = 2,
|
ERROR_SYNTAX = 2,
|
||||||
@ -30,3 +33,7 @@ Instruction *current;
|
|||||||
int offset;
|
int offset;
|
||||||
int currentsp;
|
int currentsp;
|
||||||
CGNode *cgList;
|
CGNode *cgList;
|
||||||
|
FunDecList *funList;
|
||||||
|
Stack *stack;
|
||||||
|
Stack *TrueList;
|
||||||
|
Stack *FalseList;
|
||||||
|
905
src/grammar.y
905
src/grammar.y
File diff suppressed because it is too large
Load Diff
@ -3,43 +3,145 @@
|
|||||||
|
|
||||||
#include "intermediate_code.h"
|
#include "intermediate_code.h"
|
||||||
|
|
||||||
// TODO: this is here to bring your attention to the comment bellow.
|
Stack *S_Init() {
|
||||||
// check if start is NULL if it is assign it to the start globle variable
|
Stack *s = calloc(1, sizeof(*s));
|
||||||
// otherwise make it next of current and set cur to your instruction.
|
return s;
|
||||||
TNodeOrConst* getOperand1(Instruction* i) {
|
}
|
||||||
|
|
||||||
|
void S_Free(Stack *s) {
|
||||||
|
// since we are not responsible for the values we can just pop until
|
||||||
|
// NULL
|
||||||
|
for (void *p = S_Pop(s); p != NULL; p = S_Pop(s));
|
||||||
|
free(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void S_Push(Stack *s, void *v, int i) {
|
||||||
|
__Node *n = calloc(1, sizeof(*n));
|
||||||
|
n->v = v;
|
||||||
|
n->next = s->n;
|
||||||
|
s->n = n;
|
||||||
|
s->w = i;
|
||||||
|
s->size = s->size + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *S_Pop(Stack *s) {
|
||||||
|
if (s == NULL || S_IsEmpty(s)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
__Node *node = s->n;
|
||||||
|
s->n = node->next;
|
||||||
|
s->size = s->size - 1;
|
||||||
|
void *r = node->v;
|
||||||
|
free(node);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *S_Peek(Stack *s) {
|
||||||
|
if (s == NULL || S_IsEmpty(s)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return s->n->v;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool S_IsEmpty(Stack *s) {
|
||||||
|
if (s == NULL || s->size == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int S_Size(Stack *s) {
|
||||||
|
if (s == NULL || S_IsEmpty(s)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return s->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void S_Merge(Stack *list) {
|
||||||
|
Stack *s1 = S_Pop(list);
|
||||||
|
Stack *s2 = S_Peek(list);
|
||||||
|
if (s1 == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (s2 == NULL) {
|
||||||
|
S_Push(list, s1, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (Instruction *i = S_Pop(s1); i; i = S_Pop(s1)) {
|
||||||
|
S_Push(s2, i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void emit_backpatch(Stack *s, int l) {
|
||||||
|
for (Instruction *i = S_Pop(s); i; i = S_Pop(s)) {
|
||||||
|
i->label = l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//_______________________________________________________________________
|
||||||
|
|
||||||
|
char *temp = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO: this is here to bring your attention to the comment bellow.
|
||||||
|
check if start is NULL if it is assign it to the start globle variable
|
||||||
|
otherwise make it next of current and set cur to your instruction.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void emit_push_all(Stack *s) {
|
||||||
|
for (Instruction *i = S_Pop(s); i; i = S_Pop(s)) {
|
||||||
|
current->next = i;
|
||||||
|
i->prev = current;
|
||||||
|
i->index = current->index + 1;
|
||||||
|
current = i;
|
||||||
|
current->next = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void emit_detach() {
|
||||||
|
current = current->prev;
|
||||||
|
current->next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void backpatch(Stack *s, int l) {
|
||||||
|
while (!S_IsEmpty(s)) {
|
||||||
|
Instruction *i = S_Pop(s);
|
||||||
|
set_label(i, l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
@ -53,20 +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;
|
||||||
@ -77,8 +180,18 @@ static void emit_helper(void) {
|
|||||||
current = inst;
|
current = inst;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void emit_function_dec(TableNode * name){
|
||||||
|
emit_helper();
|
||||||
|
current->opcode = E_FUNC_DEC;
|
||||||
|
current->result = name;
|
||||||
|
}
|
||||||
|
|
||||||
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
|
// TODO: create temp and remove result from param list
|
||||||
@ -87,22 +200,28 @@ void emit_binary_op(Op op, TableNode* result, TNodeOrConst* arg1, TNodeOrConst*
|
|||||||
current->operand2 = arg2;
|
current->operand2 = arg2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_unary_op(Op op, TableNode* result, TNodeOrConst* arg) {
|
void emit_goto(int i) {
|
||||||
|
emit_helper();
|
||||||
|
current->opcode = E_GOTO;
|
||||||
|
current->label = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
@ -126,119 +245,6 @@ char* get_string(TNodeOrConst* tc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
void emit_label(int label) {
|
||||||
emit_helper();
|
emit_helper();
|
||||||
current->opcode = E_LABEL;
|
current->opcode = E_LABEL;
|
||||||
@ -259,18 +265,18 @@ 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_TRUE:
|
||||||
case E_IF_X_FALSE:
|
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_LESS_THAN:
|
||||||
case E_EQUAL_TO:
|
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;
|
||||||
current->operand2 = n2;
|
current->operand2 = n2;
|
||||||
break;
|
break;
|
||||||
@ -278,65 +284,89 @@ void emit_conditional_jump(Op condition, int label, ...) {
|
|||||||
va_end(argptr);
|
va_end(argptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_function_start(TNodeOrConst * name) {
|
void emit_function_start(TableNode *name) {
|
||||||
emit_helper();
|
emit_helper();
|
||||||
current->opcode = E_LABEL; // I think this is right TODO: ask
|
current->opcode = E_FUNC_START;
|
||||||
current->operand1 = name;
|
current->result = name;
|
||||||
// this is probabaly a func declaration
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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(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, ¶m_count);
|
current->operand1 = name;
|
||||||
current->operand2 = name;
|
current->operand2 = tn_or_const(INTEGER, ¶m_count);
|
||||||
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
|
||||||
|
// we need to take a int
|
||||||
|
/*
|
||||||
|
emit_binary_op(E_MUL, result,
|
||||||
|
*/
|
||||||
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() {
|
void emit_deref_right(TableNode *x, TNodeOrConst *y) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void emit_deref_left() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void emit_field_access(char* result, char* record, char* field) {
|
|
||||||
emit_helper();
|
emit_helper();
|
||||||
|
current->opcode = E_DEREF_RIGHT;
|
||||||
|
current->result = x;
|
||||||
|
current->operand1 = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_array_access(Op op, TableNode* result, TNodeOrConst* array, TNodeOrConst* index) {
|
void emit_deref_left(TableNode *x, TNodeOrConst *y) {
|
||||||
emit_helper();
|
emit_helper();
|
||||||
current->opcode;
|
current->opcode = E_DEREF_LEFT;
|
||||||
|
current->result = x;
|
||||||
|
current->operand1 = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emit_address_of(TableNode *x, TNodeOrConst *y) {
|
||||||
|
emit_helper();
|
||||||
|
current->opcode = E_ADDRESS_OF;
|
||||||
|
current->result = x;
|
||||||
|
current->operand1 = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emit_field_access(TableNode *result, TNodeOrConst *record, int offset){
|
||||||
|
emit_helper();
|
||||||
|
current->opcode = E_DEREF_RIGHT;
|
||||||
|
current->result = result;
|
||||||
|
current->operand1 = record;
|
||||||
|
current->operand2 = tn_or_const(INTEGER, &offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void emit_array_access(Op op, TableNode *result, TNodeOrConst *array, TNodeOrConst *index) {
|
||||||
|
emit_helper();
|
||||||
|
current->opcode = op;
|
||||||
current->result = result;
|
current->result = result;
|
||||||
current->operand1 = array;
|
current->operand1 = array;
|
||||||
current->operand2 = index;
|
current->operand2 = index;
|
||||||
// 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]
|
||||||
.
|
.
|
||||||
@ -365,36 +395,243 @@ void emit_bounds_check(TNodeOrConst* index, TNodeOrConst* arr) {
|
|||||||
if t_0 < s._1 GOTO access array
|
if t_0 < s._1 GOTO access array
|
||||||
GOTO ERROR
|
GOTO ERROR
|
||||||
*/
|
*/
|
||||||
//emit_conditional_jump(E_LESS_THAN, );
|
|
||||||
//emit_conditional_jump(E_LESS_THAN, );
|
|
||||||
//emit_jump();
|
|
||||||
/* We need a label ERROR to jump to
|
/* We need a label ERROR to jump to
|
||||||
|
emit_conditional_jump(E_LESS_THAN, );
|
||||||
|
emit_conditional_jump(E_LESS_THAN, );
|
||||||
|
emit_jump();
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/*// * Implement temp variable generator function that produces unique names (t1, t2, etc.)
|
// * Implement temp variable generator function that produces unique names (t1, t2, etc.)
|
||||||
char * temp_var_gen(){
|
|
||||||
char * ret = calloc(9, sizeof(*ret));
|
int label_gen() {
|
||||||
sprintf(ret, "$t%d", temp_count);
|
|
||||||
temp_count++;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
int label_gen(){
|
|
||||||
label_count++;
|
label_count++;
|
||||||
return label_count;
|
return label_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
TableNode* getTN(TNodeOrConst* tnc) {
|
void emit_as_file(FILE *out_file, Instruction *i) {
|
||||||
|
if (out_file == NULL) {
|
||||||
|
fprintf(stderr, "Error: output file is NULL\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (i->opcode) {
|
||||||
|
case E_FUNC_DEC:
|
||||||
|
fprintf(out_file,
|
||||||
|
"%4.d: func_dec : %s\n",
|
||||||
|
i->index,
|
||||||
|
getName(i->result));
|
||||||
|
|
||||||
|
break;
|
||||||
|
case E_FUNC_START:
|
||||||
|
fprintf(out_file,
|
||||||
|
"%4.d: func : %s\n",
|
||||||
|
i->index,
|
||||||
|
getName(i->result));
|
||||||
|
break;
|
||||||
|
case E_LABEL:
|
||||||
|
fprintf(out_file,
|
||||||
|
"%4.d: Label : %d\n",
|
||||||
|
i->index,
|
||||||
|
i->label);
|
||||||
|
break;
|
||||||
|
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:
|
||||||
|
fprintf(out_file,
|
||||||
|
"%4.d: GOTO : %d\n",
|
||||||
|
i->index,
|
||||||
|
i->label);
|
||||||
|
break;
|
||||||
|
case E_IF_X_TRUE:
|
||||||
|
fprintf(out_file,
|
||||||
|
"%4.d: if %s True 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:
|
||||||
|
// this feels wrong I need to TODO: this
|
||||||
|
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_EQUAL_TO:
|
||||||
|
// this feels wrong I need to TODO: this
|
||||||
|
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_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:
|
||||||
|
fprintf(out_file,
|
||||||
|
"%4.d: return : %s\n",
|
||||||
|
i->index,
|
||||||
|
get_string(i->operand1));
|
||||||
|
break;
|
||||||
|
case E_INDEX_COPY_RIGHT:
|
||||||
|
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_INDEX_COPY_LEFT:
|
||||||
|
fprintf(out_file,
|
||||||
|
"%4.d: %s[ %s ] = %s\n",
|
||||||
|
i->index,
|
||||||
|
getName(i->result),
|
||||||
|
get_string(i->operand2),
|
||||||
|
get_string(i->operand1));
|
||||||
|
break;
|
||||||
|
case E_ADDRESS_OF:
|
||||||
|
fprintf(out_file,
|
||||||
|
"%4.d: %s = &%s\n",
|
||||||
|
i->index,
|
||||||
|
getName(i->result),
|
||||||
|
get_string(i->operand1));
|
||||||
|
break;
|
||||||
|
case E_DEREF_RIGHT:
|
||||||
|
fprintf(out_file,
|
||||||
|
"%4.d: %s = *((char * )%s + %s)\n",
|
||||||
|
i->index,
|
||||||
|
getName(i->result),
|
||||||
|
get_string(i->operand1),
|
||||||
|
get_string(i->operand2)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case E_DEREF_LEFT:
|
||||||
|
fprintf(out_file,
|
||||||
|
"%4.d: *%s = %s\n",
|
||||||
|
i->index,
|
||||||
|
getName(i->result),
|
||||||
|
get_string(i->operand1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit_as_file(out_file, i->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
} else if (tnc->d == CHARACTER) {
|
||||||
|
return tnc->tnc_union->character;
|
||||||
|
} else if (tnc->d == BOOLEAN) {
|
||||||
|
return tnc->tnc_union->Boolean;
|
||||||
|
} else if (tnc->d == ADDRESS) {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
@ -12,9 +12,39 @@
|
|||||||
|
|
||||||
#include "symbol_table.h"
|
#include "symbol_table.h"
|
||||||
|
|
||||||
|
typedef struct Stack Stack;
|
||||||
|
typedef struct __Node __Node;
|
||||||
|
|
||||||
|
typedef struct __Node {
|
||||||
|
void *v;
|
||||||
|
__Node *next;
|
||||||
|
} __Node;
|
||||||
|
|
||||||
|
typedef struct Stack {
|
||||||
|
__Node *n;
|
||||||
|
int w;
|
||||||
|
int size;
|
||||||
|
} Stack;
|
||||||
|
Stack *S_Init();
|
||||||
|
void S_Free(Stack *s);
|
||||||
|
void S_Push(Stack *s, void *v, int i);
|
||||||
|
void *S_Pop(Stack *s);
|
||||||
|
void *S_Peek(Stack *s);
|
||||||
|
bool S_IsEmpty(Stack *s);
|
||||||
|
int S_Size(Stack *s);
|
||||||
|
void S_Merge(Stack *list);
|
||||||
|
//______________________________________________________________________________________________
|
||||||
|
|
||||||
|
typedef union TNConstUnion TNConstUnion;
|
||||||
|
typedef struct Instruction Instruction;
|
||||||
|
typedef struct TNodeOrConst TNodeOrConst;
|
||||||
|
|
||||||
// these are from page 364
|
// these are from page 364
|
||||||
typedef enum {
|
|
||||||
|
typedef enum { // these are from page 364
|
||||||
E_LABEL = 10000, // this is not in the book
|
E_LABEL = 10000, // this is not in the book
|
||||||
|
E_FUNC_START,
|
||||||
|
E_FUNC_DEC,
|
||||||
E_ADD, // 1 from the list
|
E_ADD, // 1 from the list
|
||||||
E_SUB, // 1
|
E_SUB, // 1
|
||||||
E_MUL, // 1
|
E_MUL, // 1
|
||||||
@ -50,75 +80,91 @@ typedef enum {
|
|||||||
BOOLEAN // bool
|
BOOLEAN // bool
|
||||||
} Discriminant;
|
} Discriminant;
|
||||||
|
|
||||||
typedef union {
|
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 {
|
typedef struct TNodeOrConst {
|
||||||
Discriminant d;
|
Discriminant d;
|
||||||
TNConstUnion* tnc_union;
|
TNConstUnion *tnc_union;
|
||||||
} TNodeOrConst;
|
} TNodeOrConst;
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
TNodeOrConst* getOperand1(Instruction* i);
|
// TFList * make_list(Instruction * i);
|
||||||
TNodeOrConst* getOperand2(Instruction* i);
|
// - makelist(i) function to create instruction lists
|
||||||
TableNode* getResult(Instruction* i);
|
// void merge(TFList * l1, TFList * l2);
|
||||||
Op getOp(Instruction* i);
|
// - merge(p1,p2) function to concatenate lists
|
||||||
int getLabel(Instruction* i);
|
// void backpatch(TFList * l, int label);
|
||||||
int get_index(Instruction* i);
|
// - backpatch(p,i) function to fill in jump targets
|
||||||
void set_label(Instruction* i, int label);
|
// void bp_temp(int n);
|
||||||
bool isConst(TNodeOrConst* tnc);
|
|
||||||
TNodeOrConst* tn_or_const(Discriminant d, void* tnc);
|
extern Instruction *begin;
|
||||||
static void emit_helper(void);
|
extern Instruction *current;
|
||||||
void emit_binary_op(Op op, TableNode* result, TNodeOrConst* arg1, TNodeOrConst* arg2);
|
extern int label_count;
|
||||||
void emit_unary_op(Op op, TableNode* result, TNodeOrConst* arg);
|
extern bool code_gen;
|
||||||
void emit_assignment(TableNode* target, TNodeOrConst* source);
|
extern FILE *ir_flag;
|
||||||
char* get_string(TNodeOrConst* tc);
|
|
||||||
void emit_as_file(FILE* out_file, Instruction* i);
|
TNodeOrConst *tn_or_const(Discriminant, 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);
|
||||||
|
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(TNodeOrConst * name);
|
|
||||||
void emit_parameter(TNodeOrConst* param);
|
void emit_function_start(TableNode *name);
|
||||||
void emit_function_call(TableNode* result, int param_count, TNodeOrConst* name);
|
void emit_parameter(TNodeOrConst *param);
|
||||||
void emit_return(TNodeOrConst* value);
|
void emit_function_call(TableNode *result, int param_count, TNodeOrConst *name);
|
||||||
void emit_reserve(TableNode* result, TNodeOrConst* size);
|
void emit_function_dec(TableNode * name);
|
||||||
void emit_release(TableNode* pointer);
|
void emit_return(TNodeOrConst *value);
|
||||||
void emit_deref_right();
|
void emit_reserve(TableNode *result, TNodeOrConst *size);
|
||||||
void emit_deref_left();
|
void emit_release(TableNode *pointer);
|
||||||
void emit_field_access(char* result, char* record, char* field);
|
void emit_field_access(TableNode *result, TNodeOrConst *record, int offset);
|
||||||
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_detach();
|
||||||
|
void emit_push_all(Stack *s);
|
||||||
|
|
||||||
|
int getLabel(Instruction *i);
|
||||||
|
TableNode *getTN(TNodeOrConst *tnc);
|
||||||
|
int getConst(TNodeOrConst *tnc);
|
||||||
|
|
||||||
|
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);
|
||||||
int label_gen();
|
int label_gen();
|
||||||
TableNode* getTN(TNodeOrConst* tnc);
|
void backpatch(Stack *s, int l);
|
||||||
int getConst(TNodeOrConst* tnc);
|
void emit_backpatch(Stack *s, int l);
|
||||||
|
|
||||||
extern int label_count;
|
|
||||||
extern Instruction* begin;
|
|
||||||
extern Instruction* current;
|
|
||||||
|
|
||||||
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; \
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ SCHAR \\n|\\t|\\\"|[^\"\n\\]
|
|||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
"#include" { if(tok_flag != NULL) {print_tok(INCLUDE);} incr(line_number,column_number,INCLUDE); return INCLUDE; }
|
||||||
|
|
||||||
"integer" { 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(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(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; }
|
||||||
@ -56,10 +58,27 @@ SCHAR \\n|\\t|\\\"|[^\"\n\\]
|
|||||||
"->" { 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(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(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) print_tok(C_CHARACTER);
|
||||||
|
incr(line_number, column_number, C_CHARACTER);
|
||||||
|
|
||||||
|
int value;
|
||||||
|
if (strcmp(yytext, "'\\n'") == 0) value = 0x0A;
|
||||||
|
else if (strcmp(yytext, "'\\t'") == 0) value = 0x09;
|
||||||
|
else if (strcmp(yytext, "'\\''") == 0) value = 0x27;
|
||||||
|
else if (strcmp(yytext, "'\\\\'") == 0) value = 0x5C;
|
||||||
|
else value = yytext[1];
|
||||||
|
|
||||||
|
yylval.letter = value;
|
||||||
|
return C_CHARACTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
\"{SCHAR}*\" {if(tok_flag != NULL){print_tok(C_STRING);}incr(line_number,column_number,C_STRING);int k = strlen(yytext);yytext[k-1] = '\0';yylval.words = strdup(&yytext[1]);return C_STRING;}
|
\"{SCHAR}*\" {if(tok_flag != NULL){print_tok(C_STRING);}incr(line_number,column_number,C_STRING);int k = strlen(yytext);yytext[k-1] = '\0';yylval.words = strdup(&yytext[1]);return C_STRING;}
|
||||||
{COMMENT} {if(tok_flag != NULL){print_tok(COMMENT);}incr(line_number,column_number,COMMENT);/*return COMMENT;*/}
|
{COMMENT} {if(tok_flag != NULL){print_tok(COMMENT);}incr(line_number,column_number,COMMENT);/*return COMMENT;*/}
|
||||||
|
_{DIGIT}+ {if(tok_flag != NULL){print_tok(ACCESS);}incr(line_number,column_number,ACCESS);yylval.integ = atoi(&yytext[1])/*words = strdup("integer")*/;return ACCESS;}
|
||||||
"(" { 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(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(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; }
|
||||||
|
23
src/runner.c
23
src/runner.c
@ -126,6 +126,9 @@ int run(FILE *alpha) {
|
|||||||
fseek(alpha, 0, SEEK_SET);
|
fseek(alpha, 0, SEEK_SET);
|
||||||
|
|
||||||
yyin = alpha;
|
yyin = alpha;
|
||||||
|
stack = S_Init();
|
||||||
|
TrueList = S_Init();
|
||||||
|
FalseList = S_Init();
|
||||||
yyparse();
|
yyparse();
|
||||||
|
|
||||||
if (tok_flag != NULL) {
|
if (tok_flag != NULL) {
|
||||||
@ -153,13 +156,22 @@ int run(FILE *alpha) {
|
|||||||
|
|
||||||
if (ir_flag != NULL) {
|
if (ir_flag != NULL) {
|
||||||
printdebug("[-ir] Intermediate code is enabled.");
|
printdebug("[-ir] Intermediate code is enabled.");
|
||||||
|
if (!contains_errors) {
|
||||||
emit_as_file(ir_flag, begin);
|
emit_as_file(ir_flag, begin);
|
||||||
|
} else {
|
||||||
|
remove(ir_name);
|
||||||
|
}
|
||||||
fclose(ir_flag);
|
fclose(ir_flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cg_flag != NULL) {
|
if (cg_flag != NULL) {
|
||||||
printdebug("[-cg] Code generation is enabled.");
|
printdebug("[-cg] Code generation is enabled.");
|
||||||
|
|
||||||
|
if (!contains_errors) {
|
||||||
generate();
|
generate();
|
||||||
|
} else {
|
||||||
|
remove(cg_name);
|
||||||
|
}
|
||||||
fclose(cg_flag);
|
fclose(cg_flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +203,7 @@ int new_file(char *arg, char *alpha) {
|
|||||||
|
|
||||||
mkdir("./out", 0777);
|
mkdir("./out", 0777);
|
||||||
|
|
||||||
char *new_basename = calloc(strlen(basename) + 5, sizeof(char));
|
char *new_basename = calloc(strlen(basename) + 7, sizeof(char));
|
||||||
strcpy(new_basename, "./out/");
|
strcpy(new_basename, "./out/");
|
||||||
strcat(new_basename, basename);
|
strcat(new_basename, basename);
|
||||||
basename = new_basename;
|
basename = new_basename;
|
||||||
@ -232,8 +244,12 @@ int new_file(char *arg, char *alpha) {
|
|||||||
} else if (strcmp(arg, "-asc") == 0) {
|
} else if (strcmp(arg, "-asc") == 0) {
|
||||||
asc_flag = fopen(file_name, "w");
|
asc_flag = fopen(file_name, "w");
|
||||||
} else if (strcmp(arg, "-ir") == 0) {
|
} else if (strcmp(arg, "-ir") == 0) {
|
||||||
|
ir_name = malloc(strlen(file_name) + 1);
|
||||||
|
strcpy(ir_name, file_name);
|
||||||
ir_flag = fopen(file_name, "w");
|
ir_flag = fopen(file_name, "w");
|
||||||
} else if (strcmp(arg, "-cg") == 0) {
|
} else if (strcmp(arg, "-cg") == 0) {
|
||||||
|
cg_name = malloc(strlen(file_name) + 1);
|
||||||
|
strcpy(cg_name, file_name);
|
||||||
cg_flag = fopen(file_name, "w");
|
cg_flag = fopen(file_name, "w");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -247,7 +263,7 @@ 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) {
|
void insert_code_line(char *error_message, int line_number) {
|
||||||
CodeLine *error_line = malloc(sizeof(CodeLine));
|
CodeLine *error_line = malloc(sizeof(CodeLine));
|
||||||
error_line->line_number = line_number;
|
error_line->line_number = line_number;
|
||||||
error_line->line = malloc(strlen(error_message) + 1);
|
error_line->line = malloc(strlen(error_message) + 1);
|
||||||
@ -259,12 +275,15 @@ void insert_code_line(char * error_message, int line_number) {
|
|||||||
|
|
||||||
int line = error_line->line_number;
|
int line = error_line->line_number;
|
||||||
CodeLine *current = code_head;
|
CodeLine *current = code_head;
|
||||||
|
|
||||||
while (current != NULL) {
|
while (current != NULL) {
|
||||||
if (current->line_number == line) {
|
if (current->line_number == line) {
|
||||||
|
if (current->is_error == false) {
|
||||||
CodeLine *next_code_line = current->next;
|
CodeLine *next_code_line = current->next;
|
||||||
current->next = error_line;
|
current->next = error_line;
|
||||||
error_line->next = next_code_line;
|
error_line->next = next_code_line;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
current = current->next;
|
current = current->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
11
src/runner.h
11
src/runner.h
@ -56,8 +56,14 @@ FILE *ir_flag = NULL;
|
|||||||
FILE *cg_flag = NULL;
|
FILE *cg_flag = NULL;
|
||||||
bool tc_flag = false;
|
bool tc_flag = false;
|
||||||
bool DEBUG = false;
|
bool DEBUG = false;
|
||||||
|
bool entry_flag = false;
|
||||||
|
//1 is for default, 2 is in array context, 3 is in record context
|
||||||
|
int context = 1;
|
||||||
int no_flag = 0;
|
int no_flag = 0;
|
||||||
int arg;
|
int arg;
|
||||||
|
bool contains_errors = false;
|
||||||
|
char *cg_name;
|
||||||
|
char *ir_name;
|
||||||
|
|
||||||
TableNode *funprime;
|
TableNode *funprime;
|
||||||
TableNode *arrayprim;
|
TableNode *arrayprim;
|
||||||
@ -70,6 +76,9 @@ TableNode *recprime;
|
|||||||
TableNode *funtypeprime;
|
TableNode *funtypeprime;
|
||||||
TableNode *undefined;
|
TableNode *undefined;
|
||||||
extern Instruction *begin;
|
extern Instruction *begin;
|
||||||
|
extern Stack *stack;
|
||||||
|
extern Stack *TrueList;
|
||||||
|
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);
|
||||||
@ -106,6 +115,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();
|
@ -4,7 +4,12 @@
|
|||||||
#include "symbol_table.h"
|
#include "symbol_table.h"
|
||||||
|
|
||||||
Constant_Stack *head = NULL;
|
Constant_Stack *head = NULL;
|
||||||
|
Context_stack *context_head = NULL;
|
||||||
|
//TableNode* comparator = NULL;
|
||||||
|
Function_Stack *function_head = NULL;
|
||||||
|
|
||||||
int temp2_count = 0;
|
int temp2_count = 0;
|
||||||
|
int temp3_count = 0;
|
||||||
|
|
||||||
void printdebug_impl(char *file, int line, const char *format, ...) {
|
void printdebug_impl(char *file, int line, const char *format, ...) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
@ -24,6 +29,12 @@ char *temp_var_gen() {
|
|||||||
temp2_count++;
|
temp2_count++;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
char *arg_var_gen() {
|
||||||
|
char *ret = calloc(9, sizeof(*ret));
|
||||||
|
sprintf(ret, "&%d", temp3_count);
|
||||||
|
temp3_count++;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
Constant_Stack *Push(TableNode *type, void *value, bool isConst) {
|
Constant_Stack *Push(TableNode *type, void *value, bool isConst) {
|
||||||
if (type == NULL || type == undefined) {
|
if (type == NULL || type == undefined) {
|
||||||
@ -46,6 +57,234 @@ Constant_Stack *Push(TableNode *type, void *value, bool isConst) {
|
|||||||
return cs;
|
return cs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Context_stack *PushContext(/*int context, */TableNode *typeToCompare) {
|
||||||
|
/*if (context != 1 && context != 2 && context != 3 && context != 0) {
|
||||||
|
printdebug(
|
||||||
|
"invalid context passed in");
|
||||||
|
return NULL;
|
||||||
|
}*/
|
||||||
|
if(typeToCompare == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"passed a NULL reference to PushContext. Invalid.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Context_stack *cs = (Context_stack *)calloc(1,sizeof(Context_stack));
|
||||||
|
//cs->con = context;
|
||||||
|
cs->typeToCompare = typeToCompare;
|
||||||
|
if (context_head == NULL) {
|
||||||
|
context_head = cs;
|
||||||
|
cs->next = NULL;
|
||||||
|
} else {
|
||||||
|
cs->next = context_head;
|
||||||
|
context_head = cs;
|
||||||
|
}
|
||||||
|
return cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
Function_Stack *PushFunction(int arg, TableNode* FunctionType) {
|
||||||
|
if (FunctionType == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"passed a NULL reference to PushFunction. Invalid.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(FunctionType == undefined) {
|
||||||
|
printdebug(
|
||||||
|
"passed an undefined reference to PushFunction. Invalid.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Function_Stack *fs = (Function_Stack *)calloc(1,sizeof(Function_Stack));
|
||||||
|
fs->arg = arg;
|
||||||
|
fs->FunctionType = FunctionType;
|
||||||
|
if (function_head == NULL) {
|
||||||
|
function_head = fs;
|
||||||
|
fs->next = NULL;
|
||||||
|
} else {
|
||||||
|
fs->next = function_head;
|
||||||
|
function_head = fs;
|
||||||
|
}
|
||||||
|
return fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
Function_Stack *PopFunction() {
|
||||||
|
if (function_head == NULL) {
|
||||||
|
printf("cannot pop from an empty stack from popfunction. Invalid.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Function_Stack *fs = function_head;
|
||||||
|
function_head = function_head->next;
|
||||||
|
return fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getArgumentNumber(Function_Stack *fs) {
|
||||||
|
if (fs == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"passed a NULL reference to getArgumentNumber. Invalid.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return fs->arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getTotalNumberArguments(TableNode* function) {
|
||||||
|
if (function == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"passed a NULL reference to getTotalNumberArguments. Invalid.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (getAdInfoType(function) != TYPE_FUNCTION_DECLARATION) {
|
||||||
|
printdebug(
|
||||||
|
"passed an invalid reference to getTotalNumberArguments. Invalid.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
TableNode* functionType = getParameter(getTypeEntry(function));
|
||||||
|
if(functionType != undefined){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(getAdInfoType(functionType) != TYPE_RECORD_TYPE){
|
||||||
|
return 1;
|
||||||
|
}else{
|
||||||
|
return getRecLength(functionType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function_Stack* setArgumentNumber(Function_Stack *fs, int arg) {
|
||||||
|
if (fs == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"passed a NULL reference to setArgumentNumber. Invalid.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(arg<getTotalNumberArguments(fs->FunctionType)){
|
||||||
|
//case where invalid argument number is being passed
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
fs->arg = arg;
|
||||||
|
return fs;
|
||||||
|
}
|
||||||
|
Function_Stack* setFunctionType(Function_Stack *fs, TableNode* functionType) {
|
||||||
|
if (fs == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"passed a NULL reference to setFunctionType. Invalid.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (functionType == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"passed a NULL reference to setFunctionType. Invalid.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
fs->FunctionType = functionType;
|
||||||
|
return fs;
|
||||||
|
}
|
||||||
|
TableNode* getFunctionType(Function_Stack *fs) {
|
||||||
|
if (fs == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"passed a NULL reference to getFunctionType. Invalid.");
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
TableNode* tn = fs->FunctionType;
|
||||||
|
return tn;
|
||||||
|
}
|
||||||
|
|
||||||
|
Function_Stack* incrementArgumentNumber(Function_Stack *fs) {
|
||||||
|
if (fs == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"passed a NULL reference to incrementArgumentNumber. Invalid.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
int cur=getArgumentNumber(fs);
|
||||||
|
setArgumentNumber(fs, cur+1);
|
||||||
|
//setFunctionType(fs, getFunctionNumberType(getFunctionType(fs), cur+1));
|
||||||
|
return fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
TableNode* getRecordNumberType(TableNode* record, int arg){
|
||||||
|
if(record == NULL){
|
||||||
|
//case where NULL is being passed in
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if(getAdInfoType(record) != TYPE_RECORD_TYPE){
|
||||||
|
//case where invalid argument number is being passed
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if(arg<getRecLength(record)){
|
||||||
|
//case where invalid argument number is being passed
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
int count = 1;
|
||||||
|
TableNode* this = getFirstEntry(getRecList(record));
|
||||||
|
while(this != NULL && count<arg){
|
||||||
|
this = getNextEntry(this);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if(this == NULL){
|
||||||
|
//something went wrong. traversal is off
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return getTypeEntry(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
TableNode* getFunctionNumberType(TableNode* function, int arg){
|
||||||
|
if(function ==NULL){
|
||||||
|
//case where NULL is being passed in
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if(arg<1){
|
||||||
|
//case where invalid argument number is being passed
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if(getAdInfoType(function) == TYPE_FUNCTION_DECLARATION){
|
||||||
|
|
||||||
|
if(getAdInfoType(getParameter(function)) != TYPE_RECORD_TYPE){
|
||||||
|
return getParameter(function);
|
||||||
|
}else{
|
||||||
|
return getRecordNumberType(getParameter(function), arg);
|
||||||
|
}
|
||||||
|
} else if(getAdInfoType(function) == TYPE_ARRAY_TYPE){
|
||||||
|
return getArrType(function);
|
||||||
|
}else{
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TableNode* getFunctionTypeContext(Function_Stack *fs) {
|
||||||
|
if (fs == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"passed a NULL reference to getFunctionTypeContext. Invalid.");
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
TableNode* tn = fs->FunctionType;
|
||||||
|
return tn;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context_stack *PopContext() {
|
||||||
|
if (context_head == NULL) {
|
||||||
|
printf("cannot pop from an empty stack from popcontext. Invalid.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Context_stack *cs = context_head;
|
||||||
|
context_head = context_head->next;
|
||||||
|
//printf("Popped context off stack: number %d\n", cs->con);
|
||||||
|
return cs;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
int getContextType(Context_stack *cs) {
|
||||||
|
if (cs == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"passed a NULL reference to getContextType. Invalid.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return cs->con;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
TableNode *getContextTypeEntry(Context_stack *cs) {
|
||||||
|
if (cs == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"passed a NULL reference to getContextTypeEntry. Invalid.");
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
TableNode* tn = cs->typeToCompare;
|
||||||
|
return tn;
|
||||||
|
}
|
||||||
Constant_Stack *Pop() {
|
Constant_Stack *Pop() {
|
||||||
if (head == NULL) {
|
if (head == NULL) {
|
||||||
printf("cannot pop from an empty stack. Invalid.\n");
|
printf("cannot pop from an empty stack. Invalid.\n");
|
||||||
@ -68,10 +307,10 @@ Constant_Stack *Print_Stack() {
|
|||||||
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: %c\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);
|
||||||
@ -109,6 +348,18 @@ int getPrimSize(TableNode *definition) {
|
|||||||
"Invalid.");
|
"Invalid.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (getAdInfoType(definition) == TYPE_ARRAY_TYPE) {
|
||||||
|
//special case to return size for reference to an array
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
if (getAdInfoType(definition) == TYPE_FUNCTION_TYPE) {
|
||||||
|
//special case to return size for reference to a function
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
if (getAdInfoType(definition) == TYPE_RECORD_TYPE) {
|
||||||
|
//special case to return size for reference to a record
|
||||||
|
return getRecTotal(definition);
|
||||||
|
}
|
||||||
if (definition->additionalinfo == NULL) {
|
if (definition->additionalinfo == NULL) {
|
||||||
printdebug("node has NULL additionalinfo. Invalid.");
|
printdebug("node has NULL additionalinfo. Invalid.");
|
||||||
return -1;
|
return -1;
|
||||||
@ -389,7 +640,7 @@ int getRecLength(TableNode *definition) {
|
|||||||
}
|
}
|
||||||
return definition->additionalinfo->RecAdInfo->numofelements;
|
return definition->additionalinfo->RecAdInfo->numofelements;
|
||||||
}
|
}
|
||||||
// This gets the array. Needs to up be updated to get the scope instead
|
|
||||||
SymbolTable *getRecList(TableNode *definition) {
|
SymbolTable *getRecList(TableNode *definition) {
|
||||||
if (definition == NULL) {
|
if (definition == NULL) {
|
||||||
printdebug(
|
printdebug(
|
||||||
@ -443,18 +694,89 @@ int getRecSize(SymbolTable *tn) {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
int getRecPosition(TableNode *rec, char *id) {
|
||||||
|
if (rec == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"passed a NULL entry to getRecPosition. Invalid.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (rec == undefined) {
|
||||||
|
printdebug(
|
||||||
|
"passed an undefined entry to getRecPosition. Invalid.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (getAdInfoType(rec) != TYPE_RECORD_TYPE) {
|
||||||
|
printdebug(
|
||||||
|
"not checking the position of a record -- invalid op");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
TableNode *cur = getFirstEntry(getRecList(rec));
|
||||||
|
int i = 1;
|
||||||
|
while (cur != NULL) {
|
||||||
|
if (strcmp(getName(cur), id) == 0) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
cur = getNextEntry(cur);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (cur == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"passed an invalid entry to getRecPosition. Invalid.");
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int getElementOffset(TableNode *rec, char *id) {
|
||||||
|
if (rec == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"passed a NULL entry to getElementOffset. Invalid.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (rec == undefined) {
|
||||||
|
printdebug(
|
||||||
|
"passed an undefined entry to getElementOffset. Invalid.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (getAdInfoType(rec) != TYPE_RECORD_TYPE) {
|
||||||
|
printdebug(
|
||||||
|
"not checking the offset of a record -- invalid op");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int *offsets = getRecOffsets(rec);
|
||||||
|
int position = getRecPosition(rec, id);
|
||||||
|
if (position == -1) {
|
||||||
|
printdebug(
|
||||||
|
"passed an invalid entry to getElementOffset. Invalid.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
position = position - 1;
|
||||||
|
int total_offset = 0;
|
||||||
|
int current_position = 1;
|
||||||
|
while (current_position < position + 1) {
|
||||||
|
//adding current element in struct
|
||||||
|
total_offset += offsets[2 * current_position];
|
||||||
|
//adding padding between elements
|
||||||
|
total_offset += offsets[2 * current_position + 1];
|
||||||
|
current_position++;
|
||||||
|
}
|
||||||
|
//returning the offset of the start of the element
|
||||||
|
return total_offset;
|
||||||
|
}
|
||||||
|
|
||||||
// below function takes a bool to see if parameter should be decomposed or not
|
// below function takes a bool to see if parameter should be decomposed or not
|
||||||
; // note that functions only take one input and have one output
|
; // note that functions only take one input and have one output
|
||||||
// using "as" the input record can be decomposed to give the illusion of
|
// using "as" the input record can be decomposed to give the illusion of
|
||||||
// multiple inputs Below function also has the line number where the function is
|
// multiple inputs Below function also has the line number where the function is
|
||||||
// first defined
|
// first defined
|
||||||
AdInfo *CreateFunctionDeclarationInfo(int line, bool asorregular) {
|
AdInfo *CreateFunctionDeclarationInfo(int line, bool asorregular, SymbolTable *scope) {
|
||||||
AdInfo *info = (AdInfo *)malloc(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;
|
||||||
info->FunDecAdInfo->regularoras = asorregular;
|
info->FunDecAdInfo->regularoras = asorregular;
|
||||||
|
info->FunDecAdInfo->scope = scope;
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
// gets the line at which the function was first defined. (Can be used to print
|
// gets the line at which the function was first defined. (Can be used to print
|
||||||
@ -523,6 +845,68 @@ bool getAsKeyword(TableNode *definition) {
|
|||||||
return definition->additionalinfo->FunDecAdInfo->regularoras;
|
return definition->additionalinfo->FunDecAdInfo->regularoras;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SymbolTable *getFunScope(TableNode *definition) {
|
||||||
|
if (definition == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"passed a NULL entry to getScope "
|
||||||
|
"function. Invalid.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (getAdInfoType(definition) != TYPE_FUNCTION_DECLARATION) {
|
||||||
|
printdebug(
|
||||||
|
"passed in invalid entry type to getScope "
|
||||||
|
"function. Invalid.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (definition->additionalinfo == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"node has NULL additionalinfo. Invalid.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (definition->additionalinfo->FunDecAdInfo == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"node has NULL additionalinfo. Invalid.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (definition->additionalinfo->FunDecAdInfo->scope == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"node has no scope initialized.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return definition->additionalinfo->FunDecAdInfo->scope;
|
||||||
|
}
|
||||||
|
TableNode *setFunScope(TableNode *tn, SymbolTable *scope) {
|
||||||
|
if (tn == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"passing in a NULL entry to setFunScope. "
|
||||||
|
"invalid");
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (getAdInfoType(tn) != TYPE_FUNCTION_DECLARATION) {
|
||||||
|
printdebug(
|
||||||
|
"passing in an invalid entry to setFunScope. "
|
||||||
|
"invalid");
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (tn->additionalinfo == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"node has NULL additionalinfo. Invalid.");
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (tn->additionalinfo->FunDecAdInfo == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"node has NULL additionalinfo. Invalid.");
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (scope == NULL) {
|
||||||
|
printdebug(
|
||||||
|
"passed in an empty scope.");
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
tn->additionalinfo->FunDecAdInfo->scope = scope;
|
||||||
|
return tn;
|
||||||
|
}
|
||||||
TableNode *setAsKeyword(TableNode *tn, bool as) {
|
TableNode *setAsKeyword(TableNode *tn, bool as) {
|
||||||
if (tn == NULL) {
|
if (tn == NULL) {
|
||||||
printdebug(
|
printdebug(
|
||||||
@ -623,6 +1007,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));
|
||||||
return definition->additionalinfo->FunTypeAdInfo->returntype;
|
return definition->additionalinfo->FunTypeAdInfo->returntype;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -671,31 +1056,31 @@ SymbolTable *init(SymbolTable *start) {
|
|||||||
chara = (TableNode *)calloc(1, sizeof(TableNode));
|
chara = (TableNode *)calloc(1, sizeof(TableNode));
|
||||||
stri = (TableNode *)calloc(1, sizeof(TableNode));
|
stri = (TableNode *)calloc(1, sizeof(TableNode));
|
||||||
boo = (TableNode *)calloc(1, sizeof(TableNode));
|
boo = (TableNode *)calloc(1, sizeof(TableNode));
|
||||||
TableNode *reservetype = (TableNode *)calloc(1, sizeof(TableNode));
|
//TableNode *reservetype = (TableNode *)calloc(1, sizeof(TableNode));
|
||||||
TableNode *reserve = (TableNode *)calloc(1, sizeof(TableNode));
|
//TableNode *reserve = (TableNode *)calloc(1, sizeof(TableNode));
|
||||||
TableNode *releasetype = (TableNode *)calloc(1, sizeof(TableNode));
|
//TableNode *releasetype = (TableNode *)calloc(1, sizeof(TableNode));
|
||||||
TableNode *release = (TableNode *)calloc(1, sizeof(TableNode));
|
//TableNode *release = (TableNode *)calloc(1, sizeof(TableNode));
|
||||||
// TableNode* arr = (TableNode*)malloc(sizeof(SymbolTable));
|
// TableNode* arr = (TableNode*)malloc(sizeof(SymbolTable));
|
||||||
start->entries = integ;
|
start->entries = integ;
|
||||||
integ->next = addr;
|
integ->next = addr;
|
||||||
addr->next = chara;
|
addr->next = chara;
|
||||||
chara->next = stri;
|
chara->next = stri;
|
||||||
stri->next = boo;
|
stri->next = boo;
|
||||||
boo->next = reservetype;
|
boo->next = NULL;//reservetype;
|
||||||
reservetype->next = reserve;
|
//reservetype->next = reserve;
|
||||||
reserve->next = releasetype;
|
//reserve->next = releasetype;
|
||||||
releasetype->next = release;
|
//releasetype->next = release;
|
||||||
release->next = NULL;
|
//release->next = NULL;
|
||||||
|
|
||||||
integ->theName = "integer";
|
integ->theName = "integer";
|
||||||
addr->theName = "address";
|
addr->theName = "address";
|
||||||
chara->theName = "character";
|
chara->theName = "character";
|
||||||
boo->theName = "Boolean";
|
boo->theName = "Boolean";
|
||||||
stri->theName = "string";
|
stri->theName = "string";
|
||||||
reserve->theName = "reserve";
|
//reserve->theName = "reserve";
|
||||||
reservetype->theName = "reserve type";
|
//reservetype->theName = "reserve type";
|
||||||
releasetype->theName = "release type";
|
//releasetype->theName = "release type";
|
||||||
release->theName = "release";
|
//release->theName = "release";
|
||||||
// arr->theName= "array"
|
// arr->theName= "array"
|
||||||
|
|
||||||
// root TableNode that all are pointing to but not in table
|
// root TableNode that all are pointing to but not in table
|
||||||
@ -762,10 +1147,10 @@ SymbolTable *init(SymbolTable *start) {
|
|||||||
chara->theType = prime;
|
chara->theType = prime;
|
||||||
stri->theType = arrayprim;
|
stri->theType = arrayprim;
|
||||||
boo->theType = prime;
|
boo->theType = prime;
|
||||||
reserve->theType = reservetype;
|
//reserve->theType = reservetype;
|
||||||
reservetype->theType = funtypeprime;
|
//reservetype->theType = funtypeprime;
|
||||||
releasetype->theType = funtypeprime;
|
//releasetype->theType = funtypeprime;
|
||||||
release->theType = releasetype;
|
//release->theType = releasetype;
|
||||||
|
|
||||||
// arr->theType=arrayprim;
|
// arr->theType=arrayprim;
|
||||||
|
|
||||||
@ -779,20 +1164,20 @@ 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);
|
//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);
|
//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
|
||||||
chara->tag = TYPE_PRIMITIVE_TYPE; // explicitly set the type for chara
|
chara->tag = TYPE_PRIMITIVE_TYPE; // explicitly set the type for chara
|
||||||
stri->tag = TYPE_ARRAY_TYPE; // explicitly set the type for stri
|
stri->tag = TYPE_ARRAY_TYPE; // explicitly set the type for stri
|
||||||
boo->tag = TYPE_PRIMITIVE_TYPE; // explicitly set the type for boo
|
boo->tag = TYPE_PRIMITIVE_TYPE; // explicitly set the type for boo
|
||||||
reserve->tag = TYPE_FUNCTION_DECLARATION;
|
//reserve->tag = TYPE_FUNCTION_DECLARATION;
|
||||||
reservetype->tag = TYPE_FUNCTION_TYPE;
|
//reservetype->tag = TYPE_FUNCTION_TYPE;
|
||||||
releasetype->tag = TYPE_FUNCTION_TYPE;
|
//releasetype->tag = TYPE_FUNCTION_TYPE;
|
||||||
release->tag = TYPE_FUNCTION_DECLARATION;
|
//release->tag = TYPE_FUNCTION_DECLARATION;
|
||||||
// addr->additionalinfo = CreatePrimitiveInfo(8);
|
// addr->additionalinfo = CreatePrimitiveInfo(8);
|
||||||
|
|
||||||
start->Line_Number = 1;
|
start->Line_Number = 1;
|
||||||
@ -948,6 +1333,11 @@ TableNode *CreateEntry(SymbolTable *table, int tag, TableNode *typeOf, char *id,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
if ((id != NULL) && table_lookup(cur, id) != undefined) {
|
||||||
|
printdebug("This name is already defined in the current scope");
|
||||||
|
//throw_error(ERROR_TYPE, "Already defined.");
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
if (typeOf == NULL) {
|
if (typeOf == NULL) {
|
||||||
printdebug("Passing an NULL Type Node to Create Entry");
|
printdebug("Passing an NULL Type Node to Create Entry");
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -975,8 +1365,13 @@ TableNode *CreateEntry(SymbolTable *table, int tag, TableNode *typeOf, char *id,
|
|||||||
return newEntry;
|
return newEntry;
|
||||||
} else {
|
} else {
|
||||||
TableNode *oldEntry = table->entries;
|
TableNode *oldEntry = table->entries;
|
||||||
table->entries = newEntry;
|
while (oldEntry->next != NULL) {
|
||||||
newEntry->next = oldEntry;
|
oldEntry = oldEntry->next;
|
||||||
|
}
|
||||||
|
oldEntry->next = newEntry;
|
||||||
|
newEntry->next = NULL;
|
||||||
|
//table->entries = newEntry;
|
||||||
|
//newEntry->next = oldEntry;
|
||||||
printdebug("[CreateEntry] Adding %s to the symbol table", id);
|
printdebug("[CreateEntry] Adding %s to the symbol table", id);
|
||||||
return newEntry;
|
return newEntry;
|
||||||
}
|
}
|
||||||
@ -1119,6 +1514,14 @@ TableNode *table_lookup(SymbolTable *table, char *x) {
|
|||||||
}
|
}
|
||||||
TableNode *entrie = table->entries;
|
TableNode *entrie = table->entries;
|
||||||
for (; entrie != NULL; entrie = entrie->next) {
|
for (; entrie != NULL; entrie = entrie->next) {
|
||||||
|
if (entrie->theName == NULL) {
|
||||||
|
printdebug("name of entry is currently NULL, undefined");
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (entrie->theName == undefined->theName) {
|
||||||
|
printdebug("name of entry is currently undefined");
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
if (!strcmp(entrie->theName, x)) {
|
if (!strcmp(entrie->theName, x)) {
|
||||||
return entrie;
|
return entrie;
|
||||||
}
|
}
|
||||||
@ -1208,6 +1611,9 @@ 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) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (getAdInfoType(entry) == TYPE_ARRAY_TYPE) {
|
if (getAdInfoType(entry) == TYPE_ARRAY_TYPE) {
|
||||||
char *arrayType = (char *)malloc(100);
|
char *arrayType = (char *)malloc(100);
|
||||||
sprintf(arrayType, " %d -> %s", getNumArrDim(entry),
|
sprintf(arrayType, " %d -> %s", getNumArrDim(entry),
|
||||||
@ -1286,11 +1692,17 @@ 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(getReturn(entry)));
|
sprintf(functiontype, " %s", getName(getTypeEntry(entry)));
|
||||||
if (parentScopeNum == 0) {
|
char *functionScope = (char *)malloc(100);
|
||||||
st_fprint(file_ptr, getName(entry), currentScopeNum, -100, functiontype, " Function Definition");
|
if (getLine(getFunScope(entry)) < 1) {
|
||||||
|
sprintf(functionScope, " Function not defined before runtime");
|
||||||
} else {
|
} else {
|
||||||
st_fprint(file_ptr, getName(entry), currentScopeNum, parentScopeNum, functiontype, " Function Definition");
|
sprintf(functionScope, " Function Definition that starts at line %d", getLine(getFunScope(entry)));
|
||||||
|
}
|
||||||
|
if (parentScopeNum == 0) {
|
||||||
|
st_fprint(file_ptr, getName(entry), currentScopeNum, -100, functiontype, functionScope);
|
||||||
|
} else {
|
||||||
|
st_fprint(file_ptr, getName(entry), currentScopeNum, parentScopeNum, functiontype, functionScope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1309,7 +1721,7 @@ void print_symbol_table(SymbolTable *table, FILE *file_ptr) {
|
|||||||
if ((getFirstChild(node)) == NULL) {
|
if ((getFirstChild(node)) == NULL) {
|
||||||
print_symbol_table(getFirstChild(node), file_ptr);
|
print_symbol_table(getFirstChild(node), file_ptr);
|
||||||
} else {
|
} else {
|
||||||
if (getLine(getFirstChild(node)) == -1) {
|
if (getLine(getFirstChild(node)) < -3) {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
print_symbol_table(getFirstChild(node), file_ptr);
|
print_symbol_table(getFirstChild(node), file_ptr);
|
||||||
@ -1435,7 +1847,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) {
|
||||||
@ -1553,3 +1971,28 @@ TableNode *printTableNode(TableNode *tn) {
|
|||||||
|
|
||||||
return tn;
|
return tn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getStackSize() {
|
||||||
|
int i = 0;
|
||||||
|
TableNode *tn = getFirstEntry(top);
|
||||||
|
while (tn != NULL) {
|
||||||
|
i++;
|
||||||
|
tn = getNextEntry(tn);
|
||||||
|
}
|
||||||
|
|
||||||
|
ListOfTable *lt = getChildren(top);
|
||||||
|
while (lt != NULL) {
|
||||||
|
TableNode *first = lt->table->entries;
|
||||||
|
while (first != NULL) {
|
||||||
|
i++;
|
||||||
|
first = getNextEntry(first);
|
||||||
|
}
|
||||||
|
|
||||||
|
lt = lt->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
i= i * 8;
|
||||||
|
if (i % 16 != 0) i += 8;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
@ -15,9 +15,14 @@
|
|||||||
#define SIZE_CHAR 1
|
#define SIZE_CHAR 1
|
||||||
#define SIZE_BOOL 1
|
#define SIZE_BOOL 1
|
||||||
|
|
||||||
struct TableNode;
|
extern FILE *ir_flag;
|
||||||
|
|
||||||
|
typedef struct TableNode TableNode;
|
||||||
typedef struct TFList TFList;
|
typedef struct TFList TFList;
|
||||||
typedef struct CGNode CGNode;
|
typedef struct CGNode CGNode;
|
||||||
|
typedef struct SymbolTable SymbolTable;
|
||||||
|
typedef struct Function_Stack Function_Stack;
|
||||||
|
typedef struct Context_stack Context_stack;
|
||||||
|
|
||||||
typedef struct Constant_Stack {
|
typedef struct Constant_Stack {
|
||||||
struct TableNode *theType;
|
struct TableNode *theType;
|
||||||
@ -25,6 +30,32 @@ typedef struct Constant_Stack {
|
|||||||
struct Constant_Stack *next;
|
struct Constant_Stack *next;
|
||||||
bool isConst;
|
bool isConst;
|
||||||
} Constant_Stack;
|
} Constant_Stack;
|
||||||
|
//explanation about context stack
|
||||||
|
//If we have an array context, it means that we are expecting an array, either on the left side of assignable or as the (one of the) arguments that needs to be passed in for a function
|
||||||
|
//with the array context, either we are initializing the array OR we are reserving space for an element of the array. Can only reserve a record or an array so that element must be a record or an array.
|
||||||
|
//if we have a record context, that means we are expecting a record on the left side of the assignable assignment or we are expecting a record passed as an argument for a function call.
|
||||||
|
//we push and pop these contexts as needed.
|
||||||
|
//we can also push the table node of the thing that we are trying to look at. If it is supposed to be an array, for example, we can push that array onto the stack
|
||||||
|
//if it is a record, we can push that record onto the stack so that we can approperiately type check
|
||||||
|
//0 - no expecting array or record
|
||||||
|
//1 - expecting an array
|
||||||
|
//2 - expecting a record
|
||||||
|
//we also have a function call stack to look at what function call we are inside (what parameters it is expecting)
|
||||||
|
//This is distinct from the context stack. We don't necessarily add to the function call stack. After every valid argument, we simply add one to what argument we are seeing
|
||||||
|
//This lets us update the context stack as needed with the next tablenode type that we are comparing against
|
||||||
|
//we can also simply add to the function call stack if we have functions inside functions and then update as needed
|
||||||
|
|
||||||
|
typedef struct Context_stack {
|
||||||
|
//int con;
|
||||||
|
TableNode *typeToCompare;
|
||||||
|
struct Context_stack *next;
|
||||||
|
} Context_stack;
|
||||||
|
|
||||||
|
typedef struct Function_Stack{
|
||||||
|
int arg;
|
||||||
|
TableNode *FunctionType;
|
||||||
|
struct Function_Stack *next;
|
||||||
|
} Function_Stack;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int size;
|
int size;
|
||||||
@ -45,6 +76,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
int startlinenumber;
|
int startlinenumber;
|
||||||
bool regularoras;
|
bool regularoras;
|
||||||
|
SymbolTable *scope;
|
||||||
} function_declaration_info;
|
} function_declaration_info;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -101,14 +133,29 @@ void printdebug_impl(char *file, int line, const char *format, ...);
|
|||||||
printdebug_impl(__FILE__, __LINE__, format, ##__VA_ARGS__)
|
printdebug_impl(__FILE__, __LINE__, format, ##__VA_ARGS__)
|
||||||
|
|
||||||
char *temp_var_gen();
|
char *temp_var_gen();
|
||||||
|
char *arg_var_gen();
|
||||||
|
int getTotalNumberArguments(TableNode* function);
|
||||||
|
Function_Stack* incrementArgumentNumber(Function_Stack *fs);
|
||||||
|
Function_Stack* setArgumentNumber(Function_Stack *fs, int arg);
|
||||||
Constant_Stack *Push(TableNode *type, void *value, bool isConst);
|
Constant_Stack *Push(TableNode *type, void *value, bool isConst);
|
||||||
|
Context_stack *PushContext(/*int context,*/TableNode *typeToCompare);
|
||||||
|
Function_Stack *PushFunction(int arg, TableNode* FunctionType);
|
||||||
Constant_Stack *Pop();
|
Constant_Stack *Pop();
|
||||||
|
Context_stack *PopContext();
|
||||||
|
Function_Stack* setFunctionType(Function_Stack *fs, TableNode* functionType);
|
||||||
|
Function_Stack *PopFunction();
|
||||||
|
TableNode* getFunctionTypeContext(Function_Stack *fs);
|
||||||
|
TableNode* getFunctionType(Function_Stack *fs);
|
||||||
|
//int getContextType(Context_stack *cs);
|
||||||
Constant_Stack *Print_Stack();
|
Constant_Stack *Print_Stack();
|
||||||
|
int getArgumentNumber(Function_Stack *fs);
|
||||||
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);
|
||||||
|
TableNode* getRecordNumberType(TableNode* record, int arg);
|
||||||
|
TableNode* getFunctionNumberType(TableNode* function, int arg);
|
||||||
AdInfo *CreateRecordInfo(int length, SymbolTable *recordScope);
|
AdInfo *CreateRecordInfo(int length, SymbolTable *recordScope);
|
||||||
int getRecTotal(TableNode *node);
|
int getRecTotal(TableNode *node);
|
||||||
TableNode *setRecOffsetInfo(SymbolTable *scope, TableNode *node);
|
TableNode *setRecOffsetInfo(SymbolTable *scope, TableNode *node);
|
||||||
@ -117,7 +164,9 @@ 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);
|
AdInfo *CreateFunctionDeclarationInfo(int line, bool asorregular, SymbolTable *scope);
|
||||||
|
TableNode *setFunScope(TableNode *tn, SymbolTable *scope);
|
||||||
|
SymbolTable *getFunScope(TableNode *definition);
|
||||||
int getStartLine(TableNode *definition);
|
int getStartLine(TableNode *definition);
|
||||||
TableNode *setStartLine(TableNode *tn, int start);
|
TableNode *setStartLine(TableNode *tn, int start);
|
||||||
bool getAsKeyword(TableNode *definition);
|
bool getAsKeyword(TableNode *definition);
|
||||||
@ -155,16 +204,25 @@ TableNode *getFirstEntry(SymbolTable *st);
|
|||||||
TableNode *getNextEntry(TableNode *tn);
|
TableNode *getNextEntry(TableNode *tn);
|
||||||
TableNode *printTableNode(TableNode *tn);
|
TableNode *printTableNode(TableNode *tn);
|
||||||
|
|
||||||
|
TableNode *getContextTypeEntry(Context_stack *cs);
|
||||||
|
|
||||||
|
int getElementOffset(TableNode *rec, char* id);
|
||||||
|
int getRecPosition(TableNode* rec, char* id);
|
||||||
|
int getStackSize();
|
||||||
|
|
||||||
|
|
||||||
extern int yylex(void);
|
extern int yylex(void);
|
||||||
extern char *yytext;
|
extern char *yytext;
|
||||||
extern int yyleng;
|
extern int yyleng;
|
||||||
extern int yychar;
|
extern int yychar;
|
||||||
extern SymbolTable *cur;
|
extern SymbolTable *cur;
|
||||||
|
extern SymbolTable *top;
|
||||||
extern int line_number;
|
extern int line_number;
|
||||||
extern int column_number;
|
extern int column_number;
|
||||||
extern FILE *yyin;
|
extern FILE *yyin;
|
||||||
extern bool DEBUG;
|
extern bool DEBUG;
|
||||||
extern int temp2_count;
|
extern int temp2_count;
|
||||||
|
extern int temp3_count;
|
||||||
extern TableNode *funprime;
|
extern TableNode *funprime;
|
||||||
extern TableNode *arrayprim;
|
extern TableNode *arrayprim;
|
||||||
extern TableNode *integ;
|
extern TableNode *integ;
|
||||||
@ -176,6 +234,8 @@ extern TableNode *recprime;
|
|||||||
extern TableNode *funtypeprime;
|
extern TableNode *funtypeprime;
|
||||||
extern TableNode *undefined;
|
extern TableNode *undefined;
|
||||||
extern Constant_Stack *head;
|
extern Constant_Stack *head;
|
||||||
|
extern Context_stack *context_head;
|
||||||
|
extern Function_Stack *function_head;
|
||||||
|
|
||||||
extern char *COLOR_RED;
|
extern char *COLOR_RED;
|
||||||
extern char *COLOR_GREEN;
|
extern char *COLOR_GREEN;
|
||||||
|
@ -55,3 +55,6 @@
|
|||||||
#define RELEASE 614
|
#define RELEASE 614
|
||||||
// comments
|
// comments
|
||||||
#define COMMENT 700
|
#define COMMENT 700
|
||||||
|
//Additional tokens
|
||||||
|
#define ACCESS 801
|
||||||
|
#define INCLUDE 901
|
243
test.sh
243
test.sh
@ -20,147 +20,140 @@ LIGHTCYAN='\033[1;36m'
|
|||||||
WHITE='\033[1;37m'
|
WHITE='\033[1;37m'
|
||||||
|
|
||||||
if [ ! -f "./alpha" ]; then
|
if [ ! -f "./alpha" ]; then
|
||||||
echo -e "${RED}[ERROR] ${YELLOW}File ./alpha not found!${WHITE}"
|
echo -e "${RED}[ALERT] ${YELLOW}File ./alpha not found! Generating with 'make'.${WHITE}"
|
||||||
exit 1
|
make
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -d "./out" ]; then
|
if [ ! -d "./out" ]; then
|
||||||
mkdir -p out
|
mkdir -p out
|
||||||
fi
|
fi
|
||||||
|
|
||||||
SWITCH=${YELLOW}
|
if [ $# -eq 0 ]; then
|
||||||
count=0
|
help
|
||||||
|
fi
|
||||||
|
|
||||||
switchfunc() {
|
help() {
|
||||||
if [ $count -eq 0 ]; then
|
echo -e "${WHITE}-----{ ${BLUE}Test.sh Help ${WHITE}}-----\n"
|
||||||
count=1
|
echo -e "${YELLOW} Arguments: ${WHITE}"
|
||||||
SWITCH=${YELLOW}
|
echo -e "${GREEN} -exp ${WHITE} Generate expected output files"
|
||||||
|
echo -e "${GREEN} -diff ${WHITE} Compare output files with expected output files"
|
||||||
|
echo -e "${GREEN} -help ${WHITE} Show this help message\n"
|
||||||
|
echo -e "${YELLOW} Usage: ${WHITE}"
|
||||||
|
echo -e "${GREEN} ./test.sh <file.alpha> [flags] ${WHITE} Run the test on a single file"
|
||||||
|
echo -e "${GREEN} ./test.sh <directory> [flags] ${WHITE} Run the test on all files in a directory\n"
|
||||||
|
echo -e "${YELLOW} Examples: ${WHITE}"
|
||||||
|
echo -e "${GREEN} ./test.sh test.alpha ${WHITE} Runs test flags in header on test.alpha"
|
||||||
|
echo -e "${GREEN} ./test.sh test/ ${WHITE} Runs test flags in header on all .alpha files in test/"
|
||||||
|
echo -e "${GREEN} ./test.sh test/ -exp ${WHITE} Runs test flags in header on all .alpha files in test/ and generates expected output files"
|
||||||
|
echo -e "${GREEN} ./test.sh test/ -diff ${WHITE} Runs test flags in header on all .alpha files in test/ and compares output files with expected output files"
|
||||||
|
echo -e "${GREEN} ./test.sh test/ -exp -diff ${WHITE} Runs test flags in header on all .alpha files in test/ and generates expected output files and compares output files with expected output files\n"
|
||||||
|
echo -e "${YELLOW} Notes: ${WHITE}"
|
||||||
|
echo -e "${ORANGE} To create a test file, on the first line of the .alpha file, add:"
|
||||||
|
echo -e "${LIGHTBLUE} (* TEST: [ <test_flags> ] *)"
|
||||||
|
echo -e "${ORANGE} where <test_flags> are the alpha flags to be used. Ex:"
|
||||||
|
echo -e "${LIGHTBLUE} (* TEST: [ -debug -asc -tc ] *)\n"
|
||||||
|
echo -e "${WHITE}-----------------------------------------\n"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
run() {
|
||||||
|
filename=$(basename -- "$1")
|
||||||
|
first_line=$(head -n 1 "$1")
|
||||||
|
if [[ "$first_line" == "(* TEST: ["*"] *)"* ]]; then
|
||||||
|
bracket_content=$(echo "$first_line" | sed -n 's/.*\[\(.*\)\].*/\1/p')
|
||||||
|
sed -i '1d' "$1"
|
||||||
|
./alpha ${bracket_content} "$1"
|
||||||
|
sed -i "1s/^/$first_line\n/" "$1"
|
||||||
|
|
||||||
|
if [ $# -ge 2 ]; then
|
||||||
|
path=$(dirname "$1")
|
||||||
|
filename_noext=${filename:0:${#filename}-6}
|
||||||
|
if [[ "$2" == "-exp" || "$3" == "-exp" ]]; then
|
||||||
|
for file in out/${filename_noext}.*; do
|
||||||
|
if [[ "$file" == *".asc" || "$file" == *".s" || "$file" == *".st" || "$file" == *".tok" || "$file" == *".ir" ]]; then
|
||||||
|
for_filename=$(basename -- "$file")
|
||||||
|
for_filename="${for_filename}.exp"
|
||||||
|
if [ -f "${path}/../expected/${for_filename}" ]; then
|
||||||
|
echo -e "${RED}[ALERT] ${YELLOW}File ${path}/../expected/${for_filename} already exists! Overwriting...${WHITE}"
|
||||||
|
fi
|
||||||
|
cp "$file" "${path}/../expected/${for_filename}"
|
||||||
else
|
else
|
||||||
count=0
|
echo -e "${RED}[ALERT] ${YELLOW}Unexpected file found: $file ${WHITE}"
|
||||||
SWITCH='\033[0;35m'
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$2" == "-diff" || "$3" == "-diff" ]]; then
|
||||||
|
for file in out/${filename_noext}.*; do
|
||||||
|
if [[ "$file" == *".asc" || "$file" == *".s" || "$file" == *".st" || "$file" == *".tok" || "$file" == *".ir" ]]; then
|
||||||
|
for_filename=$(basename -- "$file")
|
||||||
|
for_filename="${for_filename}.exp"
|
||||||
|
if [ -f "${path}/../expected/${for_filename}" ]; then
|
||||||
|
exp_basename=$(basename -- "$for_filename")
|
||||||
|
diff -q "${path}/../expected/${for_filename}" "$file"
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}[SUCCESS] ${YELLOW}Test ${WHITE}$file ${YELLOW}passed ${WHITE}$exp_basename${WHITE}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}[ERROR] ${YELLOW}Test ${WHITE}$file ${YELLOW}failed ${WHITE}$exp_basename${WHITE}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "${RED}[ALERT] ${YELLOW}File ${path}/../expected/${for_filename} not found!${WHITE}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "${RED}[ALERT] ${YELLOW}Unexpected file found: $file ${WHITE}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "${RED}[ERROR] ${YELLOW}File $1 is not a valid .alpha test file!${WHITE}"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ $# -eq 0 ]; then
|
|
||||||
echo -e "${YELLOW}[INFO] ${WHITE}Running all tests...${WHITE}"
|
|
||||||
echo -e "${YELLOW}[INFO] ${ORANGE}Testing SPRINT-1 ---------------------------\n${WHITE}"
|
if [[ "$1" == *"/" ]]; then
|
||||||
for file in ./tests/sprint1/test/*; do
|
if [ $# -ge 2 ]; then
|
||||||
if [ -f "$file" ]; then
|
for file in "$1"*; do
|
||||||
filename=$(basename -- "$file")
|
if [[ "$file" == *.alpha ]]; then
|
||||||
echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}"
|
if [[ "$2" == "-exp" || "$3" == "-exp" || "$2" == "-diff" || "$3" == "-diff" ]]; then
|
||||||
./alpha -st -debug "$file"
|
run "$file" "$2" "$3"
|
||||||
echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n"
|
else
|
||||||
switchfunc
|
echo -e "${RED}[ERROR] ${YELLOW}Invalid argument $2!${WHITE}"
|
||||||
|
help
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
echo -e ""
|
else
|
||||||
|
for file in "$1"*; do
|
||||||
echo -e "${YELLOW}[INFO] ${ORANGE}Testing SPRINT-2 ---------------------------\n${WHITE}"
|
if [[ "$file" == *.alpha ]]; then
|
||||||
for file in ./tests/sprint2/test/*; do
|
run "$file"
|
||||||
if [ -f "$file" ]; then
|
else
|
||||||
filename=$(basename -- "$file")
|
echo -e "${RED}[ERROR] ${YELLOW}File $file is not a .alpha file!${WHITE}"
|
||||||
echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}"
|
|
||||||
./alpha -st -debug "$file"
|
|
||||||
echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n"
|
|
||||||
switchfunc
|
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
echo -e ""
|
|
||||||
|
|
||||||
echo -e "${YELLOW}[INFO] ${ORANGE}Testing SPRINT-3 ---------------------------\n${WHITE}"
|
|
||||||
for file in ./tests/sprint3/test/*; do
|
|
||||||
if [ -f "$file" ]; then
|
|
||||||
filename=$(basename -- "$file")
|
|
||||||
echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}"
|
|
||||||
./alpha -st -debug "$file"
|
|
||||||
echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n"
|
|
||||||
switchfunc
|
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
echo -e ""
|
|
||||||
|
|
||||||
echo -e "${YELLOW}[INFO] ${ORANGE}Testing SPRINT-4 ---------------------------\n${WHITE}"
|
|
||||||
for file in ./tests/sprint4/test/*; do
|
|
||||||
if [ -f "$file" ]; then
|
|
||||||
filename=$(basename -- "$file")
|
|
||||||
echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}"
|
|
||||||
./alpha -cg "$file"
|
|
||||||
echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n${WHITE}"
|
|
||||||
switchfunc
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
else
|
|
||||||
if [ "$1" == "--help" ]; then
|
|
||||||
echo -e "${YELLOW}[INFO] ${WHITE}Usage: ./test.sh [prefix]"
|
|
||||||
echo -e "${YELLOW}[INFO] ${WHITE}--help: show this help message"
|
|
||||||
echo -e "${YELLOW}[INFO] ${WHITE}--file <file>: run test with file"
|
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
if [[ "$1" == "--file" ]]; then
|
|
||||||
shift
|
if [ -f "$1" ]; then
|
||||||
if [ $# -eq 0 ]; then
|
if [[ "$1" == *.alpha ]]; then
|
||||||
echo -e "${RED}[ERROR] ${YELLOW}No file specified!${WHITE}"
|
if [ $# -ge 2 ]; then
|
||||||
exit 1
|
if [[ "$2" == "-exp" || "$3" == "-exp" || "$2" == "-diff" || "$3" == "-diff" ]]; then
|
||||||
fi
|
run "$1" "$2" "$3"
|
||||||
if [ -f "$1" ]; then
|
else
|
||||||
filename=$(basename -- "$1")
|
echo -e "${RED}[ERROR] ${YELLOW}Invalid argument $2!${WHITE}"
|
||||||
echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}"
|
help
|
||||||
./alpha -st -debug "$1"
|
fi
|
||||||
echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}"
|
else
|
||||||
exit 1
|
run "$1"
|
||||||
else
|
|
||||||
echo -e "${RED}[ERROR] ${YELLOW}File $1 not found!${WHITE}"
|
fi
|
||||||
exit 1
|
else
|
||||||
fi
|
echo -e "${RED}[ERROR] ${YELLOW}File $1 is not a .alpha file!${WHITE}"
|
||||||
fi
|
help
|
||||||
|
fi
|
||||||
if [[ "$1" == "sp1" ]]; then
|
else
|
||||||
echo -e "${YELLOW}[INFO] ${WHITE}Running tests with prefix $1..."
|
help
|
||||||
for file in ./tests/sprint1/test/*; do
|
|
||||||
if [[ "$file" == *"$1"* ]]; then
|
|
||||||
filename=$(basename -- "$file")
|
|
||||||
echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}"
|
|
||||||
./alpha -st -debug "$file"
|
|
||||||
echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n"
|
|
||||||
switchfunc
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
elif [[ "$1" == "sp2" ]]; then
|
|
||||||
echo -e "${YELLOW}[INFO] ${WHITE}Running tests with prefix $1..."
|
|
||||||
for file in ./tests/sprint2/test/*; do
|
|
||||||
if [[ "$file" == *"$1"* ]]; then
|
|
||||||
filename=$(basename -- "$file")
|
|
||||||
echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}"
|
|
||||||
./alpha -st -debug "$file"
|
|
||||||
echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n"
|
|
||||||
switchfunc
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
elif [[ "$1" == "sp3" ]]; then
|
|
||||||
echo -e "${YELLOW}[INFO] ${WHITE}Running tests with prefix $1..."
|
|
||||||
for file in ./tests/sprint3/test/*; do
|
|
||||||
if [[ "$file" == *"$1"* ]]; then
|
|
||||||
filename=$(basename -- "$file")
|
|
||||||
echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}"
|
|
||||||
./alpha -st -debug "$file"
|
|
||||||
echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n"
|
|
||||||
switchfunc
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
elif [[ "$1" == "sp4" ]]; then
|
|
||||||
echo -e "${YELLOW}[INFO] ${WHITE}Running tests with prefix $1..."
|
|
||||||
for file in ./tests/sprint4/test/*; do
|
|
||||||
if [[ "$file" == *"$1"* ]]; then
|
|
||||||
filename=$(basename -- "$file")
|
|
||||||
echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}"
|
|
||||||
./alpha -cg -debug "$file"
|
|
||||||
echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n"
|
|
||||||
switchfunc
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
else
|
|
||||||
echo -e "${RED}[ERROR] ${YELLOW}Invalid prefix $1!${WHITE}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
@ -1 +0,0 @@
|
|||||||
type A : 1 -> integer
|
|
1
tests/given/README.MD
Normal file
1
tests/given/README.MD
Normal file
@ -0,0 +1 @@
|
|||||||
|
NOTE: slightly modified from originals, please execute with care. :)
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-asc -tc] *)
|
||||||
(* type string : 1 -> character *)
|
(* type string : 1 -> character *)
|
||||||
type M : string -> integer
|
type M : string -> integer
|
||||||
|
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-asc -tc] *)
|
||||||
type M : string -> integer
|
type M : string -> integer
|
||||||
|
|
||||||
function entry : M
|
function entry : M
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-asc -tc] *)
|
||||||
type M : string -> integer
|
type M : string -> integer
|
||||||
function entry : M
|
function entry : M
|
||||||
|
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-asc -tc] *)
|
||||||
type M : string -> integer
|
type M : string -> integer
|
||||||
|
|
||||||
function entry : M
|
function entry : M
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-asc -tc] *)
|
||||||
type M : string -> integer
|
type M : string -> integer
|
||||||
|
|
||||||
function foo : M
|
function foo : M
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-asc -tc] *)
|
||||||
type M : string -> integer
|
type M : string -> integer
|
||||||
|
|
||||||
function entry : M
|
function entry : M
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-asc -tc] *)
|
||||||
type string2int: string -> integer
|
type string2int: string -> integer
|
||||||
|
|
||||||
function entry : string2int
|
function entry : string2int
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-asc -tc] *)
|
||||||
type string2int: string -> integer
|
type string2int: string -> integer
|
||||||
|
|
||||||
function entry : string2int
|
function entry : string2int
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-asc -tc] *)
|
||||||
type M : integer -> integer
|
type M : integer -> integer
|
||||||
|
|
||||||
function f : M
|
function f : M
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-asc -tc] *)
|
||||||
type M : integer -> integer
|
type M : integer -> integer
|
||||||
|
|
||||||
function f : M
|
function f : M
|
@ -1,5 +1,6 @@
|
|||||||
|
(* TEST: [-asc -tc] *)
|
||||||
(* Type definitions *)
|
(* Type definitions *)
|
||||||
|
#include "std.alpha"
|
||||||
(* mapping type *)
|
(* mapping type *)
|
||||||
type string2int: string -> integer
|
type string2int: string -> integer
|
||||||
|
|
||||||
@ -8,9 +9,9 @@ type funArray: 1 -> string2int
|
|||||||
|
|
||||||
(* record of functions *)
|
(* record of functions *)
|
||||||
type funRec: [ string2int: f; string2int: g ]
|
type funRec: [ string2int: f; string2int: g ]
|
||||||
|
type int2int: integer -> integer
|
||||||
(* function returning function *)
|
(* function returning function *)
|
||||||
type integer_2_string2int: integer -> string2int
|
type integer_2_int2int: integer -> int2int
|
||||||
|
|
||||||
(* function returning function *)
|
(* function returning function *)
|
||||||
type string2int_2_integer: string2int -> integer
|
type string2int_2_integer: string2int -> integer
|
||||||
@ -21,21 +22,23 @@ type iXiXc: [integer: a; integer: b; character: c]
|
|||||||
type iic2b: iXiXc -> Boolean
|
type iic2b: iXiXc -> Boolean
|
||||||
|
|
||||||
(* Function declarations using the above type definitions *)
|
(* Function declarations using the above type definitions *)
|
||||||
function a: string2int
|
function a: int2int
|
||||||
function b: integer_2_string2int
|
function b: integer_2_int2int
|
||||||
function c: string2int_2_integer
|
function c: string2int_2_integer
|
||||||
|
|
||||||
function d: iic2b
|
function d: iic2b
|
||||||
|
|
||||||
d(x,y,z) := {
|
d(x,y,z) := {
|
||||||
return (x < y & z < 'm');
|
[string: s]
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function entry: string2int
|
function entry: string2int
|
||||||
|
|
||||||
a(x) := {
|
a(x) := {
|
||||||
[string : s]
|
[string : s]
|
||||||
s := x;
|
x:= printInteger(x);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +51,7 @@ b(x) := {
|
|||||||
c(x) := {
|
c(x) := {
|
||||||
[string: s]
|
[string: s]
|
||||||
s := "Hi!";
|
s := "Hi!";
|
||||||
return x(s);
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -56,10 +59,11 @@ c(x) := {
|
|||||||
entry is the first function called
|
entry is the first function called
|
||||||
*)
|
*)
|
||||||
entry(arg) := {
|
entry(arg) := {
|
||||||
[integer: result; string2int: f; integer: temp]
|
[integer: result; int2int: f; integer: temp]
|
||||||
temp := a("Hello");
|
temp := 7;
|
||||||
f := b(temp);
|
f := b(temp);
|
||||||
result := c(f);
|
result := f(temp);
|
||||||
|
(*result := c(f);*)
|
||||||
if (d(1,2,'c'))
|
if (d(1,2,'c'))
|
||||||
then {
|
then {
|
||||||
result := 0;
|
result := 0;
|
||||||
@ -68,6 +72,6 @@ entry(arg) := {
|
|||||||
[ Boolean : b]
|
[ Boolean : b]
|
||||||
result := entry("hello");
|
result := entry("hello");
|
||||||
}
|
}
|
||||||
result := c(f);
|
(*result := c(f);*)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-asc -tc] *)
|
||||||
|
|
||||||
(* Type definitions *)
|
(* Type definitions *)
|
||||||
type int2int: integer -> integer
|
type int2int: integer -> integer
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-asc -tc] *)
|
||||||
(* Type definitions *)
|
(* Type definitions *)
|
||||||
|
|
||||||
type string2int: string -> integer
|
type string2int: string -> integer
|
2
tests/given/test/type.array.alpha
Normal file
2
tests/given/test/type.array.alpha
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
(* TEST: [-asc -tc] *)
|
||||||
|
type A : 1 -> integer
|
@ -1,2 +1,3 @@
|
|||||||
|
(* TEST: [-asc -tc] *)
|
||||||
type M : integer -> character
|
type M : integer -> character
|
||||||
|
|
@ -1 +1,2 @@
|
|||||||
|
(* TEST: [-asc -tc] *)
|
||||||
type R : [ integer : i ; character : c ]
|
type R : [ integer : i ; character : c ]
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-asc -tc] *)
|
||||||
(*
|
(*
|
||||||
|
|
||||||
At compiler start-up your program should
|
At compiler start-up your program should
|
19
tests/programs/array.alpha
Normal file
19
tests/programs/array.alpha
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#include "../../library/std.alpha"
|
||||||
|
type main: string -> integer
|
||||||
|
function entry: main
|
||||||
|
|
||||||
|
(* maybe some other type definitions *)
|
||||||
|
|
||||||
|
entry(arg) := {
|
||||||
|
[ string: one_name; string: another_name ]
|
||||||
|
|
||||||
|
one_name := "a string literal";
|
||||||
|
|
||||||
|
another_name := reserve another_name(4);
|
||||||
|
another_name(0) := 'C';
|
||||||
|
another_name(1) := 'a';
|
||||||
|
another_name(2) := 'r';
|
||||||
|
another_name(3) := 'l';
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
42
tests/programs/factorial.alpha
Normal file
42
tests/programs/factorial.alpha
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include "std.alpha"
|
||||||
|
|
||||||
|
function entry: string2integer
|
||||||
|
function calc: integerXinteger2integer
|
||||||
|
|
||||||
|
calc(counter, result) := {
|
||||||
|
|
||||||
|
if ( counter = 0 ) then {
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
result := result * counter;
|
||||||
|
counter := counter - 1;
|
||||||
|
return calc(counter, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
entry (arg) := {
|
||||||
|
[integer: result; integer: userInput]
|
||||||
|
|
||||||
|
result := printC('E');
|
||||||
|
result := printC('n');
|
||||||
|
result := printC('t');
|
||||||
|
result := printC('e');
|
||||||
|
result := printC('r');
|
||||||
|
result := printC(' ');
|
||||||
|
result := printC('N');
|
||||||
|
result := printC('u');
|
||||||
|
result := printC('m');
|
||||||
|
result := printC('b');
|
||||||
|
result := printC('e');
|
||||||
|
result := printC('r');
|
||||||
|
result := printC(':');
|
||||||
|
result := printC(' ');
|
||||||
|
|
||||||
|
userInput := inI(1);
|
||||||
|
userInput := calc(userInput, 1);
|
||||||
|
result := printI(userInput);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
47
tests/programs/fib.alpha
Normal file
47
tests/programs/fib.alpha
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#include "std.alpha"
|
||||||
|
|
||||||
|
function entry : string2integer
|
||||||
|
function fib : integer2integer
|
||||||
|
|
||||||
|
fib(i) := {
|
||||||
|
|
||||||
|
if (i < 1) then {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
i := i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < 2) then {
|
||||||
|
return i;
|
||||||
|
} else {
|
||||||
|
i := i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fib(i-1) + fib(i-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry (arg) := {
|
||||||
|
[ integer: result; integer: input; integer: fibValue]
|
||||||
|
|
||||||
|
result := printC('E');
|
||||||
|
result := printC('n');
|
||||||
|
result := printC('t');
|
||||||
|
result := printC('e');
|
||||||
|
result := printC('r');
|
||||||
|
result := printC(' ');
|
||||||
|
result := printC('N');
|
||||||
|
result := printC('u');
|
||||||
|
result := printC('m');
|
||||||
|
result := printC('b');
|
||||||
|
result := printC('e');
|
||||||
|
result := printC('r');
|
||||||
|
result := printC(':');
|
||||||
|
result := printC(' ');
|
||||||
|
|
||||||
|
input := inI(1);
|
||||||
|
fibValue := fib(input);
|
||||||
|
|
||||||
|
result := printI(fibValue);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
23
tests/programs/helloworld.alpha
Normal file
23
tests/programs/helloworld.alpha
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include "std.alpha"
|
||||||
|
|
||||||
|
function entry: string2integer
|
||||||
|
|
||||||
|
entry (arg) := {
|
||||||
|
[integer: result]
|
||||||
|
|
||||||
|
result := printCharacter('H');
|
||||||
|
result := printCharacter('e');
|
||||||
|
result := printCharacter('l');
|
||||||
|
result := printCharacter('l');
|
||||||
|
result := printCharacter('o');
|
||||||
|
result := printCharacter(' ');
|
||||||
|
result := printCharacter('W');
|
||||||
|
result := printCharacter('o');
|
||||||
|
result := printCharacter('r');
|
||||||
|
result := printCharacter('l');
|
||||||
|
result := printCharacter('d');
|
||||||
|
result := printCharacter('!');
|
||||||
|
result := printCharacter('\n');
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
36
tests/programs/sp3_if_else_sse.alpha
Normal file
36
tests/programs/sp3_if_else_sse.alpha
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include "std.alpha"
|
||||||
|
type rec: [character: x; integer: y]
|
||||||
|
|
||||||
|
type T2: rec -> integer
|
||||||
|
|
||||||
|
type main: string -> integer
|
||||||
|
function entry: main
|
||||||
|
(*
|
||||||
|
function bar: T2
|
||||||
|
|
||||||
|
bar (r,s) := {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*)
|
||||||
|
entry (arg) := {
|
||||||
|
[ Boolean:x ; Boolean:y ; Boolean:z ; Boolean:t; integer: c]
|
||||||
|
x := false;
|
||||||
|
y := false;
|
||||||
|
if ( (x | y) | !( y = x ) ) then {
|
||||||
|
|
||||||
|
(*
|
||||||
|
if ( x<y & !(x=y) ) then {
|
||||||
|
t := 8;
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
*)
|
||||||
|
|
||||||
|
z := 1 < 2;
|
||||||
|
c := printBoolean(z);
|
||||||
|
} else {
|
||||||
|
y := false; (* bar('c', 7); *)
|
||||||
|
c := printBoolean(y);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
3
tests/sprint1/expected/sp1_include.asc.exp
Normal file
3
tests/sprint1/expected/sp1_include.asc.exp
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
001: #include "alpha.h"
|
||||||
|
002: #include "alpha.h"
|
||||||
|
003: #include "alpha.h"
|
6
tests/sprint1/expected/sp1_include.tok.exp
Normal file
6
tests/sprint1/expected/sp1_include.tok.exp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
1 1 901 "#include"
|
||||||
|
1 10 304 ""alpha.h""
|
||||||
|
2 1 901 "#include"
|
||||||
|
2 10 304 ""alpha.h""
|
||||||
|
3 1 901 "#include"
|
||||||
|
3 10 304 ""alpha.h""
|
20
tests/sprint1/expected/sp1_simple_alpha.tok.exp
Normal file
20
tests/sprint1/expected/sp1_simple_alpha.tok.exp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
1 1 405 "type"
|
||||||
|
1 6 101 "main"
|
||||||
|
1 10 508 ":"
|
||||||
|
1 12 101 "string"
|
||||||
|
1 19 510 "->"
|
||||||
|
1 22 201 "integer"
|
||||||
|
2 1 406 "function"
|
||||||
|
2 10 101 "entry"
|
||||||
|
2 15 508 ":"
|
||||||
|
2 17 101 "main"
|
||||||
|
4 1 101 "entry"
|
||||||
|
4 6 501 "("
|
||||||
|
4 7 101 "arg"
|
||||||
|
4 10 502 ")"
|
||||||
|
4 12 608 ":="
|
||||||
|
4 15 505 "{"
|
||||||
|
5 5 407 "return"
|
||||||
|
5 12 301 "0"
|
||||||
|
5 13 507 ";"
|
||||||
|
6 1 506 "}"
|
@ -1 +1,2 @@
|
|||||||
|
(* TEST: [-tok] *)
|
||||||
(***)
|
(***)
|
@ -1 +1,2 @@
|
|||||||
|
(* TEST: [-tok] *)
|
||||||
(*(**)*)
|
(*(**)*)
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-tok] *)
|
||||||
(*(**)*)
|
(*(**)*)
|
||||||
(***)
|
(***)
|
||||||
(******)(*\kpp*********)
|
(******)(*\kpp*********)
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-tok] *)
|
||||||
(* hello *)
|
(* hello *)
|
||||||
(* hello *)
|
(* hello *)
|
||||||
(* I'd think this is a legal "string" that contains several \n \t
|
(* I'd think this is a legal "string" that contains several \n \t
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-tok] *)
|
||||||
This is a test
|
This is a test
|
||||||
9combined 7okens
|
9combined 7okens
|
||||||
12345
|
12345
|
||||||
|
4
tests/sprint1/test/sp1_include.alpha
Normal file
4
tests/sprint1/test/sp1_include.alpha
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
(* TEST: [-tok -asc -tc] *)
|
||||||
|
#include "alpha.h"
|
||||||
|
#include "alpha.h"
|
||||||
|
#include "alpha.h"
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-tok] *)
|
||||||
while
|
while
|
||||||
While
|
While
|
||||||
whiLe
|
whiLe
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-tok] *)
|
||||||
+
|
+
|
||||||
-
|
-
|
||||||
*
|
*
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-tok] *)
|
||||||
;
|
;
|
||||||
:
|
:
|
||||||
,
|
,
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-tok] *)
|
||||||
)
|
)
|
||||||
a)
|
a)
|
||||||
)a
|
)a
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-tok] *)
|
||||||
type rec: [integer: x; integer: y]
|
type rec: [integer: x; integer: y]
|
||||||
type T1: integer -> integer
|
type T1: integer -> integer
|
||||||
type T2: rec -> integer
|
type T2: rec -> integer
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-tok] *)
|
||||||
(* Type definitions *)
|
(* Type definitions *)
|
||||||
type string: 1 -> character
|
type string: 1 -> character
|
||||||
type int2int: integer -> integer
|
type int2int: integer -> integer
|
||||||
|
7
tests/sprint1/test/sp1_simple_alpha.alpha
Normal file
7
tests/sprint1/test/sp1_simple_alpha.alpha
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
(* TEST: [-tok] *)
|
||||||
|
type main: string -> integer
|
||||||
|
function entry: main
|
||||||
|
|
||||||
|
entry(arg) := {
|
||||||
|
return 0;
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-tok] *)
|
||||||
45
|
45
|
||||||
123
|
123
|
||||||
8392
|
8392
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-tok] *)
|
||||||
"this is a string" 721398 'g' '/n' (* should print 3 tokens before this *)
|
"this is a string" 721398 'g' '/n' (* should print 3 tokens before this *)
|
||||||
'
|
'
|
||||||
'
|
'
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
(* TEST: [-tok] *)
|
||||||
valid1
|
valid1
|
||||||
Valid2
|
Valid2
|
||||||
_valid3
|
_valid3
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user