Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
C
cs444
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Xun Yang
cs444
Commits
046889e2
Commit
046889e2
authored
5 years ago
by
Xun Yang
Browse files
Options
Downloads
Patches
Plain Diff
methodNode ReturnNode codeGen
parent
21fdaf4e
No related branches found
No related tags found
No related merge requests found
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
AstBuilding.py
+1
-0
1 addition, 0 deletions
AstBuilding.py
CodeGenUtils.py
+2
-2
2 additions, 2 deletions
CodeGenUtils.py
LineNodes.py
+17
-9
17 additions, 9 deletions
LineNodes.py
MemberNodes.py
+43
-1
43 additions, 1 deletion
MemberNodes.py
with
63 additions
and
12 deletions
AstBuilding.py
+
1
−
0
View file @
046889e2
...
@@ -58,6 +58,7 @@ def reachabilityChecking(ASTs):
...
@@ -58,6 +58,7 @@ def reachabilityChecking(ASTs):
####################################################
####################################################
def
codeGen
(
ASTs
,
output
=
"
output
"
):
def
codeGen
(
ASTs
,
output
=
"
output
"
):
ASTs
=
ASTs
[:
1
]
# TOREMOVE: don't compile stdlib for now
for
t
in
ASTs
:
for
t
in
ASTs
:
t
[
1
].
codeGen
()
t
[
1
].
codeGen
()
# Outputting the generated code into className.s
# Outputting the generated code into className.s
...
...
This diff is collapsed.
Click to expand it.
CodeGenUtils.py
+
2
−
2
View file @
046889e2
...
@@ -3,8 +3,8 @@
...
@@ -3,8 +3,8 @@
# String, String, String/None, String/None
# String, String, String/None, String/None
def
p
(
instruction
,
arg1
,
arg2
=
""
,
comment
=
""
):
def
p
(
instruction
,
arg1
,
arg2
=
""
,
comment
=
""
):
result
=
"
"
+
instruction
+
"
"
+
str
(
arg1
)
result
=
"
"
+
instruction
+
"
"
+
str
(
arg1
)
if
arg2
!=
""
:
if
arg2
:
result
+=
"
,
"
+
str
(
arg2
)
result
+=
"
,
"
+
arg2
if
comment
:
if
comment
:
result
+=
"
;
"
+
comment
result
+=
"
;
"
+
comment
return
result
+
"
\n
"
return
result
+
"
\n
"
...
...
This diff is collapsed.
Click to expand it.
LineNodes.py
+
17
−
9
View file @
046889e2
...
@@ -92,7 +92,7 @@ class BlockNode(ASTNode):
...
@@ -92,7 +92,7 @@ class BlockNode(ASTNode):
if
not
inMaybe
:
if
not
inMaybe
:
raise
Exception
(
"
ERROR: cannot reach block node in class {}
"
.
format
(
self
.
typeName
))
raise
Exception
(
"
ERROR: cannot reach block node in class {}
"
.
format
(
self
.
typeName
))
# Checking reachability of each statement
# Checking reachability of each statement
prevOut
=
inMaybe
# Note: in[S1] = in[L]
prevOut
=
inMaybe
# Note: in[S1] = in[L]
for
statement
in
self
.
statements
:
for
statement
in
self
.
statements
:
...
@@ -122,6 +122,8 @@ class VarDclNode(ASTNode):
...
@@ -122,6 +122,8 @@ class VarDclNode(ASTNode):
self
.
dclType
=
TypeNode
(
parseTree
.
children
[
0
],
typeName
)
self
.
dclType
=
TypeNode
(
parseTree
.
children
[
0
],
typeName
)
self
.
name
=
parseTree
.
children
[
1
].
lex
self
.
name
=
parseTree
.
children
[
1
].
lex
self
.
offset
=
0
# offset on the stack
if
len
(
parseTree
.
children
)
>
2
:
if
len
(
parseTree
.
children
)
>
2
:
# Handling rule: variableInit expr
# Handling rule: variableInit expr
self
.
variableInit
=
makeNodeFromExpr
(
parseTree
.
children
[
3
].
children
[
0
],
typeName
)
self
.
variableInit
=
makeNodeFromExpr
(
parseTree
.
children
[
3
].
children
[
0
],
typeName
)
...
@@ -201,7 +203,7 @@ class IfNode(ASTNode):
...
@@ -201,7 +203,7 @@ class IfNode(ASTNode):
# No need to check for empty statement, since in[ifBody] = inMaybe
# No need to check for empty statement, since in[ifBody] = inMaybe
if
self
.
ifBody
:
if
self
.
ifBody
:
self
.
ifBody
.
reachCheck
(
inMaybe
)
self
.
ifBody
.
reachCheck
(
inMaybe
)
if
not
self
.
elseBody
:
if
not
self
.
elseBody
:
# L : if (E) S
# L : if (E) S
# in[S] = in[L]
# in[S] = in[L]
...
@@ -250,7 +252,7 @@ class WhileNode(ASTNode):
...
@@ -250,7 +252,7 @@ class WhileNode(ASTNode):
def
reachCheck
(
self
,
inMaybe
):
def
reachCheck
(
self
,
inMaybe
):
if
not
inMaybe
:
if
not
inMaybe
:
raise
Exception
(
"
in[s] = no for WhileNode in class {}
"
.
format
(
self
.
typeName
))
raise
Exception
(
"
in[s] = no for WhileNode in class {}
"
.
format
(
self
.
typeName
))
# Checking constant expression in whileBound
# Checking constant expression in whileBound
con
=
None
# default to None: i.e. not a constant expression
con
=
None
# default to None: i.e. not a constant expression
if
hasattr
(
self
.
whileBound
,
"
getConstant
"
):
if
hasattr
(
self
.
whileBound
,
"
getConstant
"
):
...
@@ -261,7 +263,7 @@ class WhileNode(ASTNode):
...
@@ -261,7 +263,7 @@ class WhileNode(ASTNode):
# General case: while(E) S
# General case: while(E) S
if
con
==
None
:
if
con
==
None
:
self
.
outMaybe
=
inMaybe
self
.
outMaybe
=
inMaybe
# while(false) S
# while(false) S
elif
con
==
False
or
con
==
0
:
elif
con
==
False
or
con
==
0
:
self
.
outMaybe
=
inMaybe
self
.
outMaybe
=
inMaybe
inMaybeWhileBody
=
False
inMaybeWhileBody
=
False
...
@@ -270,12 +272,12 @@ class WhileNode(ASTNode):
...
@@ -270,12 +272,12 @@ class WhileNode(ASTNode):
# Checking reachability on whileBody
# Checking reachability on whileBody
if
self
.
whileBody
:
if
self
.
whileBody
:
self
.
whileBody
.
reachCheck
(
inMaybeWhileBody
)
self
.
whileBody
.
reachCheck
(
inMaybeWhileBody
)
elif
not
inMaybeWhileBody
:
# empty block/empty statement that's unreachable
elif
not
inMaybeWhileBody
:
# empty block/empty statement that's unreachable
raise
Exception
(
"
ERROR: unreachable empty statment/block at while node for class {}
"
.
format
(
self
.
typeName
))
raise
Exception
(
"
ERROR: unreachable empty statment/block at while node for class {}
"
.
format
(
self
.
typeName
))
return
return
# returnStatement
# returnStatement
# Rules:
# Rules:
...
@@ -310,6 +312,12 @@ class ReturnNode(ASTNode):
...
@@ -310,6 +312,12 @@ class ReturnNode(ASTNode):
raise
Exception
(
"
ERROR: return statement unreachable at class {}
"
.
format
(
self
.
typeName
))
raise
Exception
(
"
ERROR: return statement unreachable at class {}
"
.
format
(
self
.
typeName
))
self
.
outMaybe
=
False
# out[L] = no
self
.
outMaybe
=
False
# out[L] = no
def
codeGen
(
self
):
self
.
code
=
""
if
self
.
expr
:
self
.
expr
.
codeGen
()
self
.
code
+=
self
.
expr
.
code
# forStatement and forStatementNoShortIf
# forStatement and forStatementNoShortIf
# Rules:
# Rules:
# 1. forStatement FOR LPAREN forInit SEMICO forExpr SEMICO forInit RPAREN statement
# 1. forStatement FOR LPAREN forInit SEMICO forExpr SEMICO forInit RPAREN statement
...
@@ -376,7 +384,7 @@ class ForNode(ASTNode):
...
@@ -376,7 +384,7 @@ class ForNode(ASTNode):
def
reachCheck
(
self
,
inMaybe
):
def
reachCheck
(
self
,
inMaybe
):
if
not
inMaybe
:
if
not
inMaybe
:
raise
Exception
(
"
in[s] = no for ForNode in class {}
"
.
format
(
self
.
typeName
))
raise
Exception
(
"
in[s] = no for ForNode in class {}
"
.
format
(
self
.
typeName
))
# Checking constant expression in whileBound
# Checking constant expression in whileBound
con
=
None
# default to None: i.e. not a constant expression
con
=
None
# default to None: i.e. not a constant expression
if
hasattr
(
self
.
forBound
,
"
getConstant
"
):
if
hasattr
(
self
.
forBound
,
"
getConstant
"
):
...
@@ -396,7 +404,7 @@ class ForNode(ASTNode):
...
@@ -396,7 +404,7 @@ class ForNode(ASTNode):
# Checking reachability on whileBody
# Checking reachability on whileBody
if
self
.
bodyStatement
:
if
self
.
bodyStatement
:
self
.
bodyStatement
.
reachCheck
(
inMaybeForBody
)
self
.
bodyStatement
.
reachCheck
(
inMaybeForBody
)
elif
inMaybeForBody
:
# checking if the empty forBody can be reached
elif
inMaybeForBody
:
# checking if the empty forBody can be reached
raise
Exception
(
"
ERROR: unreachable empty statement/block at for node at class {}
"
.
format
(
self
.
typeName
))
raise
Exception
(
"
ERROR: unreachable empty statement/block at for node at class {}
"
.
format
(
self
.
typeName
))
return
return
This diff is collapsed.
Click to expand it.
MemberNodes.py
+
43
−
1
View file @
046889e2
...
@@ -5,6 +5,7 @@ from UnitNodes import ParamNode
...
@@ -5,6 +5,7 @@ from UnitNodes import ParamNode
from
TheTypeNode
import
TypeNode
from
TheTypeNode
import
TypeNode
from
Environment
import
Env
from
Environment
import
Env
from
collections
import
OrderedDict
from
collections
import
OrderedDict
from
CodeGenUtils
import
p
,
pLabel
,
genProcedure
# field
# field
class
FieldNode
(
ASTNode
):
class
FieldNode
(
ASTNode
):
...
@@ -171,13 +172,41 @@ class MethodNode(ASTNode):
...
@@ -171,13 +172,41 @@ class MethodNode(ASTNode):
self
.
body
.
reachCheck
(
True
)
# For method bodies, in[L] = maybe by default
self
.
body
.
reachCheck
(
True
)
# For method bodies, in[L] = maybe by default
self
.
outMaybe
=
self
.
body
.
outMaybe
self
.
outMaybe
=
self
.
body
.
outMaybe
# Check if out[method body] is a maybe for non-void methods
# Check if out[method body] is a maybe for non-void methods
if
not
self
.
methodType
or
self
.
myType
.
name
==
"
void
"
:
# Omitting the check for constructors and void functions
if
not
self
.
methodType
or
self
.
myType
.
name
==
"
void
"
:
# Omitting the check for constructors and void functions
return
return
if
self
.
outMaybe
:
if
self
.
outMaybe
:
raise
Exception
(
"
Non-void method
'
{}
'
in class
'
{}
'
does not return
"
.
format
(
self
.
name
,
self
.
typeName
))
raise
Exception
(
"
Non-void method
'
{}
'
in class
'
{}
'
does not return
"
.
format
(
self
.
name
,
self
.
typeName
))
return
return
def
codeGen
(
self
):
if
hasattr
(
self
,
"
code
"
)
and
self
.
code
!=
""
:
return
self
.
code
=
pLabel
(
self
.
typeName
+
"
_
"
+
self
.
name
+
"
_
"
+
self
.
paramTypes
,
"
method
"
)
if
self
.
body
:
bodyCode
=
""
# push all local var to stack
vars
=
getVarDclNodes
(
self
.
body
)
for
i
in
range
(
len
(
vars
)):
vars
[
i
].
offset
=
i
*
4
+
16
bodyCode
+=
p
(
"
push
"
,
0
)
self
.
body
.
codeGen
()
bodyCode
+=
self
.
body
.
code
# pop off all the local var
for
i
in
range
(
len
(
vars
)):
bodyCode
+=
p
(
"
pop
"
,
"
edx
"
)
self
.
code
+=
genProcedure
(
bodyCode
,
"
method definition for
"
+
self
.
name
)
else
:
self
.
code
+=
p
(
"
ret
"
,
""
)
############# helper for forward ref checking ########
############# helper for forward ref checking ########
# Input: AST Node
# Input: AST Node
# Output: A list of names to be check
# Output: A list of names to be check
...
@@ -208,3 +237,16 @@ def getNameNodes(node):
...
@@ -208,3 +237,16 @@ def getNameNodes(node):
result
.
extend
(
getNameNodes
(
c
))
result
.
extend
(
getNameNodes
(
c
))
return
result
return
result
# Input: Block Node
# Output: A list of local var dcl to be pushed onto the stack
def
getVarDclNodes
(
node
):
result
=
[]
for
s
in
node
.
statements
:
if
s
.
__class__
.
__name__
==
'
VarDclNode
'
:
result
+=
[
s
]
if
s
.
__class__
.
__name__
==
'
BlockNode
'
:
result
+=
getVarDclNodes
(
node
)
return
result
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment