-
Notifications
You must be signed in to change notification settings - Fork 3
/
README
47 lines (36 loc) · 2.52 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
CS143 (Compilers), Summer 2012
Assignment handout: http://www.stanford.edu/class/archive/cs/cs143/cs143.1128/handouts/250%20Assignment%204.pdf
This is a working compiler for Decaf (https://parasol.tamu.edu/courses/decaf/students/decafOverview.pdf),
an object oriented programming language similar to Java but smaller in scope.
Usage: ./run <decaf file name>
Notes on the TAC generator:
My naming scheme is that my main function is labeled "main", global
function are labeled "_globalfunctionname", and methods are labeled
"_Classname.Methodname".
Otherwise, this extends onto the functionality that I built for the semantic analyzer. I
store the scoping information, the current class, and all of the other
information that I used and/or collected during the semantic analysis for
each node in that same node during semantic analysis. That way, on the
next tree traversal for code generation, this information is all set up
and ready for the code generator to use.
The code generation revolves around the virtual Emit function, but I also
use a lot of helper functions such as MakeLocation, ReadValue, etc.
Notes on the semantic analyzer:
My semantic analyzer passes down scopes via arguments as it traverses the parse tree.
It makes 2 passes. The first pass is merely to "fill up" the scopes for each class
and interface so that on the second pass, we actually have something to compare to.
The second pass is when all o the rest of the scope checking and type checking takes
place. Because the class and interface scope information is in the process of being
collected in the first pass, my program only ever prints error messages on the second
pass.
My semantic analyzer initially checks for any declaration conflicts with global variable
names, adds all the acceptable ones to the global scope, and then scope checks and type
checks the variables themselves (i.e. the body of a function/class/interface, the type
of a VarDecl, etc) which then recursively check their various components.
As for error cascading, I used Type::errorType a lot to try and prevent this. In a lot of
cases, I set the type of a semantically incorrect node to Type::errorType and set rules
that allowed Type::errorType to make it through successfully in most situations. In other
situations, such as if the condition in a while loop has an undeclared variable in an
equality statement, I just set the type to be boolType anyways after reporting the error
so that the rest of the analysis goes through correctly (because equality statements always
have type boolType).