From 07b85de1888701e644af90fdb5ef423f028d7efb Mon Sep 17 00:00:00 2001 From: Xun Yang <x299yang@uwaterloo.ca> Date: Sun, 5 Apr 2020 18:37:14 -0400 Subject: [PATCH] local var codeGen --- CodeGenUtils.py | 2 +- ExprPrimaryNodes.py | 23 +++++++++++++++-------- LineNodes.py | 10 ++++++++++ NameNode.py | 9 +++++++-- Tests/A5/J1_00_Step0_localVar.java | 10 ++++++++++ 5 files changed, 43 insertions(+), 11 deletions(-) create mode 100644 Tests/A5/J1_00_Step0_localVar.java diff --git a/CodeGenUtils.py b/CodeGenUtils.py index 07f7b73..c7b483f 100644 --- a/CodeGenUtils.py +++ b/CodeGenUtils.py @@ -30,7 +30,7 @@ def pLabel(name, type, comment=""): used_labels.add(l) result = "" - if type in ["class", "method", "constant"]: # make global + if type in ["class", "method"]: # make global result += "global " + l + "\n" if comment: result += l + ": ;" + comment + "\n" diff --git a/ExprPrimaryNodes.py b/ExprPrimaryNodes.py index 5be74d5..23cb989 100644 --- a/ExprPrimaryNodes.py +++ b/ExprPrimaryNodes.py @@ -118,7 +118,7 @@ class ArgsNode(ASTNode): if arg and hasattr(arg, "codeGen"): # children hasn't generated code yet # Note: this check is redundant if we're certain that every override of this method has the initial check - if not hasattr(arg, "code"): + if not hasattr(arg, "code"): arg.codeGen() self.code += arg.code self.code += p(instruction="push", arg1="eax", comment="pushing result of evaluation of argument") @@ -244,6 +244,13 @@ class AssignNode(ASTNode): raise Exception("ERROR: not reaching a assignment statement") self.outMaybe = inMaybe + def codeGen(self): + self.right.codeGen() + self.code = self.right.code + if self.left.prefixLink.__class__.__name__ == "VarDclNode": + # move init result to var location + self.code += p("mov", "[ebp + " + str(self.left.prefixLink.offset) + "]", "eax") + ################################################################################## # cast: castExpr LPAREN castType RPAREN unaryNotPlusMinus @@ -634,18 +641,18 @@ class MethodInvNode(ASTNode): else: raise Exception("ERROR: Class {} doesn't have a method {} with given argument types.".format(self.typeName, self.ID.name)) - + def reachCheck(self, inMaybe): if not inMaybe: raise Exception("ERROR: not reaching a variable declaration statement for var {}".format(self.name)) self.outMaybe = inMaybe - - + + def codeGen(self): if hasattr(self, "code"): return self.code = "" - # Only invoking static methods + # Only invoking static methods if "static" in self.method.mods: mLabel = "M_" + self.typeName + "_" + self.method.name + "_" + self.method.paramTypes (pro, epi) = genMethodInvoke(mLabel) @@ -674,15 +681,15 @@ class MethodInvNode(ASTNode): if c and hasattr(c, "codeGen"): # children hasn't generated code yet # Note: this check is redundant if we're certain that every override of this method has the initial check - if not hasattr(c, "code"): + if not hasattr(c, "code"): c.codeGen() self.code += c.code - - + + ################# Helper ####################### diff --git a/LineNodes.py b/LineNodes.py index d447447..422c307 100644 --- a/LineNodes.py +++ b/LineNodes.py @@ -2,6 +2,7 @@ from AST import ASTNode, getParseTreeNodes, getASTNode from Environment import Env from ExprPrimaryNodes import makeNodeFromExpr, makeNodeFromAllPrimary, MethodInvNode, ClassCreateNode from TheTypeNode import TypeNode, TypeStruct +from CodeGenUtils import p # Contains: # block @@ -163,6 +164,15 @@ class VarDclNode(ASTNode): raise Exception("ERROR: not reaching a variable declaration statement for var {} in class {}".format(self.name, self.typeName)) self.outMaybe = inMaybe + def codeGen(self): + self.code = "" + if self.variableInit: + self.variableInit.codeGen() + self.code += self.variableInit.code + # move init result to var location + self.code += p("mov", "[ebp + " + str(self.offset) + "]", "eax") + + # ifStatement, ifElseStatement, ifElseStatementNoShortIf # Rules: # 1. ifStatement IF LPAREN expr RPAREN statement diff --git a/NameNode.py b/NameNode.py index 65d2967..62acb8e 100644 --- a/NameNode.py +++ b/NameNode.py @@ -3,6 +3,7 @@ from TheTypeNode import TypeStruct, getSupers import MemberNodes import TypeNodes from Environment import Env +from CodeGenUtils import p # name nodes: contains compID and IDs @@ -66,7 +67,7 @@ class NameNode(ASTNode): self.addToPrefix(typeNode) return True return False - + def checkLength(self): if not self.IDs: return True @@ -166,7 +167,7 @@ class NameNode(ASTNode): if self.checkThis(): self.pointToThis = True return - + # Checking if a1 is length if self.checkLength(): return @@ -252,6 +253,10 @@ class NameNode(ASTNode): # pprint(vars(self)) raise Exception("ERROR: Cannot check type of name {}".format(self.name)) + def codeGen(self): + self.code = "" + if self.prefixLink.__class__.__name__ == "VarDclNode": + self.code = p("mov", "eax", "[ebp + " + str(self.prefixLink.offset) + "]", "access local var" + self.name) # helper def checkProtected(dcl, usage): # get curType's class it was declared in diff --git a/Tests/A5/J1_00_Step0_localVar.java b/Tests/A5/J1_00_Step0_localVar.java new file mode 100644 index 0000000..a9752c0 --- /dev/null +++ b/Tests/A5/J1_00_Step0_localVar.java @@ -0,0 +1,10 @@ +// most basic test case for step 0 +public class J1_00_Step0_localVar { + public static int test() { + int i = 0; + i = 2; + int b = 3; + b = 4; + return i + b; + } +} -- GitLab