diff --git a/Compiler/.idea/.idea.Compiler/.idea/workspace.xml b/Compiler/.idea/.idea.Compiler/.idea/workspace.xml
index 4371fd7..a539953 100644
--- a/Compiler/.idea/.idea.Compiler/.idea/workspace.xml
+++ b/Compiler/.idea/.idea.Compiler/.idea/workspace.xml
@@ -20,14 +20,33 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
@@ -164,7 +183,7 @@
-
+
@@ -202,22 +221,22 @@
-
+
-
-
+
+
-
-
+
+
-
-
+
+
-
+
@@ -282,10 +301,10 @@
-
-
+
+
-
+
diff --git a/Compiler/Compiler.cs b/Compiler/Compiler.cs
index d24c561..2dbe8b3 100644
--- a/Compiler/Compiler.cs
+++ b/Compiler/Compiler.cs
@@ -13,19 +13,35 @@ namespace Compiler
{
public static void Main(string[] args)
{
- if (args.Length != 1)
+ if (args.Length < 1)
{
- Console.WriteLine("Usage: Compiler ");
+ Console.WriteLine("Usage: Compiler [optional: -v]");
}
else
{
+ bool debug = false;
+ string inputFileName = args[0].Split("/").Last();
string outputPath = args[0].Substring(0, args[0].LastIndexOf("/"));
- Compile(args[0], $"{outputPath}/assembly.s");
- Console.WriteLine($"Compiled to {outputPath}/assembly.s");
+ if (args.Length == 2)
+ {
+ if (args[2] == "-v")
+ {
+ debug = true;
+ }
+ }
+
+ Compile(args[0], $"{outputPath}/assembly.s", debug);
+ if (debug)
+ {
+ Console.WriteLine($"Compiled to {outputPath}/assembly.s");
+ }
ProcessStartInfo startInfo = new ProcessStartInfo()
- {FileName = "gcc", Arguments = $"{outputPath}/assembly.s -o {outputPath}/program"};
+ {
+ FileName = "gcc",
+ Arguments = $"{outputPath}/assembly.s -o {outputPath}/{inputFileName.Replace(".c", "")}"
+ };
Process proc = new Process() {StartInfo = startInfo,};
proc.Start();
@@ -33,14 +49,19 @@ namespace Compiler
{
Thread.Sleep(1);
}
- Console.WriteLine($"Assembled to {outputPath}/program");
+
File.Delete($"{outputPath}/assembly.s");
- Console.WriteLine("Deleted assembly.s file. Done!");
+
+ if (debug)
+ {
+ Console.WriteLine($"Assembled to {outputPath}/program");
+ Console.WriteLine("Deleted assembly.s file. Done!");
+ }
}
}
- static void Compile(string inputPath, string outputPath)
+ static void Compile(string inputPath, string outputPath, bool debug)
{
//Lexing
Lexer.Lexer lexer = new Lexer.Lexer();
@@ -50,7 +71,10 @@ namespace Compiler
string contents = file.ReadToEnd();
List tokens = lexer.Lex(contents);
- Console.WriteLine($"Lexed {inputPath.Split("/").Last()}.");
+ if (debug)
+ {
+ Console.WriteLine($"Lexed {inputPath.Split("/").Last()}.");
+ }
//Parsing
Parser.Parser p = new Parser.Parser(tokens);
@@ -58,7 +82,10 @@ namespace Compiler
try
{
Node programNode = p.Parse(NodeType.ProgramNode);
- Console.WriteLine($"Parsed \"{inputPath.Split("/").Last()}\"");
+ if (debug)
+ {
+ Console.WriteLine($"Parsed \"{inputPath.Split("/").Last()}\"");
+ }
//Generating
Generator.Generator generator = new Generator.Generator();
diff --git a/tests/week_1/invalid/missing_paren.c b/stage_1/invalid/missing_paren.c
similarity index 100%
rename from tests/week_1/invalid/missing_paren.c
rename to stage_1/invalid/missing_paren.c
diff --git a/tests/week_1/invalid/missing_retval.c b/stage_1/invalid/missing_retval.c
similarity index 100%
rename from tests/week_1/invalid/missing_retval.c
rename to stage_1/invalid/missing_retval.c
diff --git a/tests/week_1/invalid/no_brace.c b/stage_1/invalid/no_brace.c
similarity index 100%
rename from tests/week_1/invalid/no_brace.c
rename to stage_1/invalid/no_brace.c
diff --git a/tests/week_1/invalid/no_semicolon.c b/stage_1/invalid/no_semicolon.c
similarity index 100%
rename from tests/week_1/invalid/no_semicolon.c
rename to stage_1/invalid/no_semicolon.c
diff --git a/tests/week_1/invalid/no_space.c b/stage_1/invalid/no_space.c
similarity index 100%
rename from tests/week_1/invalid/no_space.c
rename to stage_1/invalid/no_space.c
diff --git a/tests/week_1/invalid/wrong_case.c b/stage_1/invalid/wrong_case.c
similarity index 100%
rename from tests/week_1/invalid/wrong_case.c
rename to stage_1/invalid/wrong_case.c
diff --git a/tests/week_1/valid/multi_digit.c b/stage_1/valid/multi_digit.c
similarity index 100%
rename from tests/week_1/valid/multi_digit.c
rename to stage_1/valid/multi_digit.c
diff --git a/tests/week_1/valid/newlines.c b/stage_1/valid/newlines.c
similarity index 100%
rename from tests/week_1/valid/newlines.c
rename to stage_1/valid/newlines.c
diff --git a/tests/week_1/valid/no_newlines.c b/stage_1/valid/no_newlines.c
similarity index 100%
rename from tests/week_1/valid/no_newlines.c
rename to stage_1/valid/no_newlines.c
diff --git a/tests/week_1/valid/return_0.c b/stage_1/valid/return_0.c
similarity index 100%
rename from tests/week_1/valid/return_0.c
rename to stage_1/valid/return_0.c
diff --git a/tests/week_1/valid/return_2.c b/stage_1/valid/return_2.c
similarity index 100%
rename from tests/week_1/valid/return_2.c
rename to stage_1/valid/return_2.c
diff --git a/tests/week_1/valid/spaces.c b/stage_1/valid/spaces.c
similarity index 100%
rename from tests/week_1/valid/spaces.c
rename to stage_1/valid/spaces.c
diff --git a/test_compiler.sh b/test_compiler.sh
new file mode 100755
index 0000000..ccc485a
--- /dev/null
+++ b/test_compiler.sh
@@ -0,0 +1,158 @@
+#!/bin/bash
+
+padding_dots=$(printf '%0.1s' "."{1..60})
+padlength=50
+cmp=$1
+success_total=0
+failure_total=0
+
+print_test_name () {
+ test_name=$1
+ printf '%s' "$test_name"
+ printf '%*.*s' 0 $((padlength - ${#test_name})) "$padding_dots"
+}
+
+test_success () {
+ echo "OK"
+ ((success++))
+}
+
+test_failure () {
+ echo "FAIL"
+ ((fail++))
+}
+
+test_not_implemented () {
+ echo "NOT IMPLEMENTED"
+}
+
+run_our_program () {
+ actual_out=`./$1 2>/dev/null`
+ actual_exit_code=$?
+ rm $1 2>/dev/null
+}
+
+run_correct_program () {
+ expected_out=`./a.out`
+ expected_exit_code=$?
+ rm a.out
+}
+
+compare_program_results () {
+ # make sure exit code is correct
+ if [ "$expected_exit_code" -ne "$actual_exit_code" ] || [ "$expected_out" != "$actual_out" ]
+ then
+ test_failure
+ else
+ test_success
+ fi
+}
+
+test_stage () {
+ success=0
+ fail=0
+ echo "===================================================="
+ echo "STAGE $1"
+ echo "===================Valid Programs==================="
+ for prog in `find . -type f -name "*.c" -path "./stage_$1/valid/*" -not -path "*/valid_multifile/*" 2>/dev/null`; do
+
+ gcc -w $prog
+ run_correct_program
+
+ base="${prog%.*}" #name of executable (filename w/out extension)
+ test_name="${base##*valid/}"
+
+ print_test_name $test_name
+ $cmp $prog 2>/dev/null
+ status=$?
+
+ if [[ $test_name == "skip_on_failure"* ]]; then
+ # this may depend on features we haven't implemented yet
+ # if compilation succeeds, make sure it gives the right result
+ # otherwise don't count it as success or failure
+ if [[ -f $base ]] && [[ $status -eq 0 ]]; then
+ # it succeeded, so run it and make sure it gives the right result
+ run_our_program $base
+ compare_program_results
+ else
+ test_not_implemented
+ fi
+ else
+ run_our_program $base
+ compare_program_results
+ fi
+ done
+ # programs with multiple source files
+ for dir in `ls -d stage_$1/valid_multifile/* 2>/dev/null` ; do
+ gcc -w $dir/*
+
+ run_correct_program
+
+ base="${dir%.*}" #name of executable (directory w/out extension)
+ test_name="${base##*valid_multifile/}"
+
+ # need to explicitly specify output name
+ $cmp -o "$test_name" $dir/* >/dev/null
+
+ print_test_name $test_name
+
+ # check output/exit codes
+ run_our_program $test_name
+ compare_program_results
+
+ done
+ echo "===================Invalid Programs================="
+ for prog in `ls stage_$1/invalid/{,**/}*.c 2>/dev/null`; do
+
+ base="${prog%.*}" #name of executable (filename w/out extension)
+ test_name="${base##*invalid/}"
+
+ $cmp $prog >/dev/null 2>&1
+ status=$? #failed, as we expect, if exit code != 0
+ print_test_name $test_name
+
+ # make sure neither executable nor assembly was produced
+ # and exit code is non-zero
+ if [[ -f $base || -f $base".s" ]]
+ then
+ test_failure
+ rm $base 2>/dev/null
+ rm $base".s" 2>/dev/null
+ else
+ test_success
+ fi
+ done
+ echo "===================Stage $1 Summary================="
+ printf "%d successes, %d failures\n" $success $fail
+ ((success_total=success_total+success))
+ ((failure_total=failure_total + fail))
+}
+
+total_summary () {
+ echo "===================TOTAL SUMMARY===================="
+ printf "%d successes, %d failures\n" $success_total $failure_total
+}
+
+if [ "$1" == "" ]; then
+ echo "USAGE: ./test_compiler.sh /path/to/compiler [stages(optional)]"
+ echo "EXAMPLE(test specific stages): ./test_compiler.sh ./mycompiler 1 2 4"
+ echo "EXAMPLE(test all): ./test_compiler.sh ./mycompiler"
+ exit 1
+fi
+
+if test 1 -lt $#; then
+ testcases=("$@") # [1..-1] is testcases
+ for i in `seq 2 $#`; do
+ test_stage ${testcases[$i-1]}
+ done
+ total_summary
+ exit 0
+fi
+
+num_stages=10
+
+for i in `seq 1 $num_stages`; do
+ test_stage $i
+done
+
+total_summary