diff --git a/AstBuilding.py b/AstBuilding.py index 734eee03494ca491ba8f68f60721718a08346a30..3c872478b01a49e1c4019c3878daab46139d6c44 100644 --- a/AstBuilding.py +++ b/AstBuilding.py @@ -182,11 +182,11 @@ def codeGen(ASTs, output="output"): f.write(classInterNode.data) f.write("section .text\n") if not flagGlobalHelper: - f.write(globalImport(True)) + f.write(globalImport(True, classInterNode.name)) f.write(genericHelperFunctions()) flagGlobalHelper = True else: - f.write(globalImport()) + f.write(globalImport(False, classInterNode.name)) f.write(classInterNode.code) f.close() @@ -204,13 +204,16 @@ def startGen(ASTs, output, arrayClassMemory): className = ast.typeDcl.name method_label = "M_" + className + "_test_" - callInit = "; Start of calling each class's classAndStaticFieldInit \n" + callInit = "; Start of calling each class's classAndStaticFieldInit and globalImport\n" for t in ASTs: classInterNode = t[1].typeDcl if classInterNode and classInterNode.__class__.__name__ == "ClassNode": - label = "H_" + classInterNode.name + "_" + "classAndStaticFieldInit" - callInit += p(instruction="extern", arg1=label) + \ - p(instruction="call", arg1=label) + label1 = "H_" + classInterNode.name + "_" + "classAndStaticFieldInit" + label2 = "H_" + classInterNode.name + "_" + "globalImport" + callInit += p(instruction="extern", arg1=label1) + \ + p(instruction="call", arg1=label1) + \ + p(instruction="extern", arg1=label2) + \ + p(instruction="call", arg1=label2) callInit += "; End of calling each class's classAndStaticFieldInit \n" callArrayInit = "; Start of calling each array type's arrayMemoryInitialize\n" diff --git a/CodeGenUtils.py b/CodeGenUtils.py index a56fb5e96db6f84ec9a9984a315e76569ee333e5..c953da3cd38254b328dbf339a5ac04b05e86f372 100644 --- a/CodeGenUtils.py +++ b/CodeGenUtils.py @@ -152,8 +152,9 @@ def genericHelperFunctions(): return code # Generates code to import helper generic functions and global constants -def globalImport(genGlobalFunction=False): - code = "; Importing helper functions and constants\n" + \ +def globalImport(genGlobalFunction, typeName): + code = "; Function to import helper functions and constants\n" + \ + pLabel(name=typeName + "_globalImport", type="helper") + \ p(instruction="extern", arg1="__malloc") + \ p(instruction="extern", arg1="__exception") @@ -163,6 +164,7 @@ def globalImport(genGlobalFunction=False): p(instruction="extern", arg1="H__Null_Check") + \ p(instruction="extern", arg1="H__Bounds_Check") + code += p(instruction="ret", arg1="") code += "; End of importing helper functions and constants\n" return code diff --git a/ExprPrimaryNodes.py b/ExprPrimaryNodes.py index f20a562b0aaa3d87d21c03a1e561a4f583c274f3..1731b69bcc9d1f87e6b61b4a17ff01cafc1a3b56 100644 --- a/ExprPrimaryNodes.py +++ b/ExprPrimaryNodes.py @@ -676,12 +676,21 @@ class ExprNode(ASTNode): # eax = right result # so, basically do "eax = ebx op eax" - # Comparisons: - if self.op == '&': - self.code += p("and", "eax", "ebx", " right:eax " + self.op + " left:ebx") - return - if self.op == '|': - self.code += p("por", "eax", "ebx", " right:eax " + self.op + " left:ebx") + # Comparisons that don't short-circuit: + if self.op in ['|', '&']: + n = getCFlowLabel() + endLabel = "_end" + n + + if self.op == '|': + # if right = False, then we output left's result + self.code += p("cmp", "eax", "1") + elif self.op == '&': + # if right = True, then we output left's result + self.code += p("cmp", "eax", "0") + + self.code += p("je", endLabel) + self.code += p("mov", "eax", "ebx") + self.code += p(endLabel + ":", "") return # Binary operations: diff --git a/LineNodes.py b/LineNodes.py index 3793813f7b58df45bbfb8d10a4c6a06a88d07ecc..20338426a2c6dfafa0f6e43120f470d14fc4f8ed 100644 --- a/LineNodes.py +++ b/LineNodes.py @@ -450,11 +450,14 @@ class ForNode(ASTNode): self.children.append(self.bodyStatement) def checkType(self): - self.forInit.checkType() - self.forBound.checkType() # need resolving var declared in forInit to use it in forBound - if self.forBound.myType.name != 'boolean': - raise Exception("ERROR: Cannot use non-boolean type for forBound.") - self.forUpdate.checkType() + if self.forInit: + self.forInit.checkType() + if self.forBound: + self.forBound.checkType() # need resolving var declared in forInit to use it in forBound + if self.forBound.myType.name != 'boolean': + raise Exception("ERROR: Cannot use non-boolean type for forBound.") + if self.forUpdate: + self.forUpdate.checkType() self.bodyStatement.checkType() def reachCheck(self, inMaybe): diff --git a/Tests/A5/J1_01_fieldAcc_ObjCreate.java b/Tests/A5/J1_01_fieldAcc_ObjCreate.java index 2c476eee03493ac5d761d0175dffd6d55fb44bd1..df98faa836fd7888d99e3728b765f8cdf69d58fb 100644 --- a/Tests/A5/J1_01_fieldAcc_ObjCreate.java +++ b/Tests/A5/J1_01_fieldAcc_ObjCreate.java @@ -12,7 +12,7 @@ public class J1_01_fieldAcc_ObjCreate { } public static int test() { - J1_01_ObjCreate k = new J1_01_fieldAcc_ObjCreate(); + J1_01_fieldAcc_ObjCreate k = new J1_01_fieldAcc_ObjCreate(); return k.i + k.m() + J1_01_fieldAcc_ObjCreate.n; } }