This project is a J-- (subset of Java) compiler written in C, that compiles J-- into WebAssembly Text Format (WAT).
See the full J-- specification here: https://pages.cpsc.ucalgary.ca/~aycock/411/spec.html
- Scanner (Flex)
- Parser (Bison)
- Semantic Checker
- Code Generation
When the compiler is run, it generates WAT files from J-- files. WASM files are then generated from the WAT files, and then the WASM files are run.
All the provided J-- test cases can found here: J-- Files
All the generated WAT files can be found here: WAT Files
gen.t1
This test case makes use of the prints
run-time function, and outputs a string.
Provided J-- File: gen.t1
Generated WAT File: gen_t1.wat
Hello, world!
gen.t5
This test case assigns a value of 42 to 3 variables using i = j = k = 42
. It then uses the printi
and printc
run-time functions to print these variables and a new line character (ASCII new line is 10 Dec).
Provided J-- File: gen.t5
Generated WAT File: gen_t5.wat
42
42
42
gen.t10
This test case uses the prints
and printi
run-time functions to output formatted versions of the first 46 Fibonacci numbers. The Fibonacci numbers are calculated recursively.
The test case was stopped before it could fully complete because it takes a very long time to calculate the larger numbers.
Provided J-- File: gen.t10
Generated WAT File: gen_t10.wat
fib(0) = 0
fib(1) = 1
fib(2) = 1
fib(3) = 2
fib(4) = 3
fib(5) = 5
fib(6) = 8
fib(7) = 13
fib(8) = 21
fib(9) = 34
fib(10) = 55
fib(11) = 89
fib(12) = 144
fib(13) = 233
fib(14) = 377
fib(15) = 610
fib(16) = 987
fib(17) = 1597
fib(18) = 2584
fib(19) = 4181
fib(20) = 6765
fib(21) = 10946
fib(22) = 17711
fib(23) = 28657
fib(24) = 46368
fib(25) = 75025
fib(26) = 121393
fib(27) = 196418
fib(28) = 317811
fib(29) = 514229
fib(30) = 832040
fib(31) = 1346269
fib(32) = 2178309
fib(33) = 3524578
fib(34) = 5702887
^C
gen.t11
This test case outputs an both a local and a global uninitialized integer and boolean using the printi
and printb
run-time functions.
Provided J-- File: gen.t11
Generated WAT File: gen_t11.wat
global int default value: 0
global boolean default value: false
(it's ok if the following aren't 0/false)
local int default value: 0
local boolean default value: false
(it's ok if the following aren't 0/false)
local int default value: 0
local boolean default value: false
gen.t12
This test case uses the prints
and printi
run-time functions to output formatted versions of the first 46 Fibonacci numbers. The Fibonacci numbers are calculated in a loop.
Provided J-- File: gen.t12
Generated WAT File: gen_t12.wat
fib(0) = 0
fib(1) = 1
fib(2) = 1
fib(3) = 2
fib(4) = 3
fib(5) = 5
fib(6) = 8
fib(7) = 13
fib(8) = 21
fib(9) = 34
fib(10) = 55
fib(11) = 89
fib(12) = 144
fib(13) = 233
fib(14) = 377
fib(15) = 610
fib(16) = 987
fib(17) = 1597
fib(18) = 2584
fib(19) = 4181
fib(20) = 6765
fib(21) = 10946
fib(22) = 17711
fib(23) = 28657
fib(24) = 46368
fib(25) = 75025
fib(26) = 121393
fib(27) = 196418
fib(28) = 317811
fib(29) = 514229
fib(30) = 832040
fib(31) = 1346269
fib(32) = 2178309
fib(33) = 3524578
fib(34) = 5702887
fib(35) = 9227465
fib(36) = 14930352
fib(37) = 24157817
fib(38) = 39088169
fib(39) = 63245986
fib(40) = 102334155
fib(41) = 165580141
fib(42) = 267914296
fib(43) = 433494437
fib(44) = 701408733
fib(45) = 1134903170
fib(46) = 1836311903
gen.t13
This test case uses the getchar
run-time function to read in a character entered by the user. The function that makes the call to read a character is called recursively, and characters will continue to be read until a new line character is read. After that, the characters are printed using the printc
run-time function, and will be printed in reverse order from how they were entered due.
Provided J-- File: gen.t13
Generated WAT File: gen_t13.wat
123456789ABC
CBA987654321
gen.t14
This test case uses the printi
run-time function to output the minimum value of a 32-bit signed integer.
Provided J-- File: gen.t14
Generated WAT File: gen_t14.wat
minint is -2147483648
gen.t15
This test case uses the printi
run-time function to print the value of four negative numbers. Some of the numbers have multiple negative signs in front of them, which is just interpreted as a negative number in J--.
Provided J-- File: gen.t15
Generated WAT File: gen_t15.wat
-123
-2147483648
-2147483648
-2147483648
gen.t18
This test case implements a recursive-descent calculator that includes a simple scanner and parser. When the code is running, the scanner detects the type of character that was entered and the parser matches various simple expressions, evaluates them and prints their result.
The gen.t18 J-- file is missing a return statement on line 92. I assumed that all the test cases were supposed to work, so I added a return -1 to the end of the function and generated the code this way. This test case may have a mistake in it, or maybe an exception was supposed to be raised and code generation was not even supposed to happen because the code is incorrect. Another possibility is that this case would have been allowed because the code halts and exits if it gets to line 92.
Provided J-- File: gen.t18
Generated WAT File: gen_t18.wat
1+2
= 3
12345*-98
= -1209810
1111/4
= 277
-3--5
= 2
Error: expected factor.
gen.t22
This test case uses the prints
run-time function to output strings that includes escape characters and a NUL character.
Provided J-- File: gen.t22
Generated WAT File: gen_t22.wat
asdf�
"'\�� asdf
gen.t26
This test case uses the prints
run-time function to output three base 10 numbers in base 2, base 8 and base 10.
Provided J-- File: gen.t26
Generated WAT File: gen_t26.wat
0 =
0 (base 2)
0 (base 8)
0 (base 10)
17 =
010001 (base 2)
021 (base 8)
017 (base 10)
42 =
0101010 (base 2)
052 (base 8)
042 (base 10)
gen.t29
This test case evaluates boolean expressions and prints out which portion of the expression was evaluated. For example, if the boolean expression is (A() && B()) || C()
and A()
is false, then B()
does not need to be evaluated because that portion of the expression is already known to be false. In this case, only A()
and C()
will need to be evaluated.
Provided J-- File: gen.t29
Generated WAT File: gen_t29.wat
if ((A && B) || C) {...} else {...}, with A=false B=false C=false
evaluated A
evaluated C
else-part executed
if ((A && B) || C) {...} else {...}, with A=false B=false C=true
evaluated A
evaluated C
if-part executed
if ((A && B) || C) {...} else {...}, with A=false B=true C=false
evaluated A
evaluated C
else-part executed
if ((A && B) || C) {...} else {...}, with A=false B=true C=true
evaluated A
evaluated C
if-part executed
if ((A && B) || C) {...} else {...}, with A=true B=false C=false
evaluated A
evaluated B
evaluated C
else-part executed
if ((A && B) || C) {...} else {...}, with A=true B=false C=true
evaluated A
evaluated B
evaluated C
if-part executed
if ((A && B) || C) {...} else {...}, with A=true B=true C=false
evaluated A
evaluated B
if-part executed
if ((A && B) || C) {...} else {...}, with A=true B=true C=true
evaluated A
evaluated B
if-part executed
x = (A && !B) || C, with A=false B=false C=false
evaluated A
evaluated C
x=false
x = (A && !B) || C, with A=false B=false C=true
evaluated A
evaluated C
x=true
x = (A && !B) || C, with A=false B=true C=false
evaluated A
evaluated C
x=false
x = (A && !B) || C, with A=false B=true C=true
evaluated A
evaluated C
x=true
x = (A && !B) || C, with A=true B=false C=false
evaluated A
evaluated B
x=true
x = (A && !B) || C, with A=true B=false C=true
evaluated A
evaluated B
x=true
x = (A && !B) || C, with A=true B=true C=false
evaluated A
evaluated B
evaluated C
x=false
x = (A && !B) || C, with A=true B=true C=true
evaluated A
evaluated B
evaluated C
x=true
gen.t30
This test case does not output anything, and it has no return statement outside the if statement even though the function is supposed to return an integer.
I assumed that all the test cases were supposed to work, so I added a return -1 to the end of the function and generated the code this way. This test case may have a mistake in it (missing return statement), or maybe an exception was supposed to be raised and code generation was not even supposed to happen because the code is incorrect.
Provided J-- File: gen.t30
Generated WAT File: gen_t30.wat
gen.t31
This test case tries to use the printi
run-time function to output the result of division by zero. The error is detected and output.
Provided J-- File: gen.t31
Generated WAT File: gen_t31.wat
error initialiazing module: integer divide by zero
gen.t32
This test case uses two nested loops to output numbers between 0 to 5 in the outer loop and 100 to 105 in the inner loop.
Provided J-- File: gen.t32
Generated WAT File: gen_t32.wat
0
100
101
102
103
104
105
1
100
101
102
103
104
105
2
100
101
102
103
104
105
3
100
101
102
103
104
105
4
100
101
102
103
104
105
5
100
101
102
103
104
105
gen.t33
This test case uses the getchar
run-time function to read in characters and the printc
run-time function to output the entered characters until a character that is not recognized is entered.
Provided J-- File: gen.t33
Generated WAT File: gen_t33.wat
Test String
Test String
12345
12345
A
A
()_OP:
()_OP:
gen.t34
This test case uses the printi
run-time function to output a number generated through a series of function calls. Some of the function calls are made in the arguments of other function calls.
Provided J-- File: gen.t34
Generated WAT File: gen_t34.wat
2903040
art-life.j--
This test case generates a 10x10 pseudorandom binary matrix for the first generation. The other nine generations are determined based on the rules for Conway's Game of Life: https://www.geeksforgeeks.org/program-for-conways-game-of-life/
Provided J-- File: art-life.j--
Generated WAT File: art-life_j.wat
Generation 1:
0 1 1 1 0 1 0 0 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 1 1 0 1 0 0 0
0 1 0 1 0 0 1 0 0 0
0 1 1 0 0 0 0 1 0 0
0 0 0 0 1 0 0 1 0 0
0 1 1 0 0 0 0 0 1 0
0 1 0 0 1 0 0 0 0 0
0 1 1 0 0 0 0 1 0 0
0 1 1 0 1 0 0 0 1 0
Generation 2:
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0
0 0 1 1 1 0 1 1 0 0
0 1 0 1 1 1 1 1 0 0
0 1 1 1 0 0 1 1 0 0
0 0 0 1 0 0 0 1 1 0
0 1 1 1 0 0 0 0 0 0
1 0 0 1 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
0 1 1 1 0 0 0 0 0 0
Generation 3:
0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 1 1 1 0 0
0 0 1 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0 0 0
0 0 0 0 1 0 1 1 1 0
0 1 0 1 1 0 0 0 0 0
1 0 0 1 0 0 0 0 0 0
1 0 0 1 0 0 0 0 0 0
0 1 1 0 0 0 0 0 0 0
Generation 4:
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0 0
0 1 1 0 0 0 1 1 0 0
0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0
0 0 1 1 1 1 0 1 0 0
0 0 1 1 1 1 0 1 0 0
1 1 0 1 0 0 0 0 0 0
1 0 0 1 0 0 0 0 0 0
0 1 1 0 0 0 0 0 0 0
Generation 5:
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 0 0 0
0 1 1 0 0 0 1 1 0 0
0 1 1 0 0 0 0 1 0 0
0 1 0 0 1 0 0 0 0 0
0 0 1 0 0 1 0 1 1 0
0 0 0 0 0 1 0 0 0 0
1 1 0 0 0 0 0 0 0 0
1 0 0 1 0 0 0 0 0 0
0 1 1 0 0 0 0 0 0 0
Generation 6:
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 1 0 0
0 1 1 0 0 1 0 1 0 0
1 0 0 1 0 0 1 1 0 0
0 1 0 1 0 0 1 1 1 0
0 0 0 0 1 1 1 0 0 0
0 1 0 0 0 0 1 0 0 0
1 1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
0 1 1 0 0 0 0 0 0 0
Generation 7:
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 1 0 1 0 0
0 1 1 0 1 1 0 0 1 0
1 0 0 1 1 1 0 0 0 0
0 0 1 1 0 0 0 0 1 0
0 0 1 0 1 0 0 0 0 0
1 1 0 0 0 0 1 0 0 0
1 1 0 0 0 0 0 0 0 0
1 0 1 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
Generation 8:
0 0 0 0 0 0 1 0 0 0
0 0 0 0 1 1 0 1 0 0
0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0
0 1 1 0 0 1 0 0 0 0
0 0 1 0 0 0 0 0 0 0
1 0 1 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
1 0 1 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
Generation 9:
0 0 0 0 0 1 1 0 0 0
0 0 0 0 0 1 1 0 0 0
0 0 0 0 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0
0 1 1 0 0 0 0 0 0 0
0 0 1 1 0 0 0 0 0 0
0 0 1 1 0 0 0 0 0 0
0 0 1 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
Generation 10:
0 0 0 0 0 1 1 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 1 0 1 0 0 0
0 0 0 0 0 1 0 0 0 0
0 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 1 0 0 1 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
0 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
art-select.j--
This test case generates 15 pseudorandom numbers and then sorts the numbers from smallest to largest using a selection sort algorithm. The steps to sort the numbers are printed out.
Provided J-- File: art-select.j--
Generated WAT File: art-select_j.wat
30 23 4 9 86 63 48 61 98 39 8 73 18 35 0
0 23 4 9 86 63 48 61 98 39 8 73 18 35 30
0 4 23 9 86 63 48 61 98 39 8 73 18 35 30
0 4 8 9 86 63 48 61 98 39 23 73 18 35 30
0 4 8 9 86 63 48 61 98 39 23 73 18 35 30
0 4 8 9 18 63 48 61 98 39 23 73 86 35 30
0 4 8 9 18 23 48 61 98 39 63 73 86 35 30
0 4 8 9 18 23 30 61 98 39 63 73 86 35 48
0 4 8 9 18 23 30 35 98 39 63 73 86 61 48
0 4 8 9 18 23 30 35 39 98 63 73 86 61 48
0 4 8 9 18 23 30 35 39 48 63 73 86 61 98
0 4 8 9 18 23 30 35 39 48 61 73 86 63 98
0 4 8 9 18 23 30 35 39 48 61 63 86 73 98
0 4 8 9 18 23 30 35 39 48 61 63 73 86 98
0 4 8 9 18 23 30 35 39 48 61 63 73 86 98
art-sieve.j--
This test case calculates and outputs the all the prime numbers less than or equal to 100, as well as the number of prime numbers less than or equal to 100.
Provided J-- File: art-sieve.j--
Generated WAT File: art-sieve_j.wat
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97
25 prime numbers <= 100
- Allocated memory is never deallocated