diff --git a/ExprPrimaryNodes.py b/ExprPrimaryNodes.py index da0eca1b286a4bcec3ace7274b5e971996a23bb9..07860ef5d8f1cf5b26f5465995fdaf14f86ee03e 100644 --- a/ExprPrimaryNodes.py +++ b/ExprPrimaryNodes.py @@ -93,16 +93,22 @@ def helperDisambigName(node): # args exprs, exprs expr COMMA exprs class ArgsNode(ASTNode): # always list all fields in the init method to show the class structure - def __init__(self, parseTree, typeName): + def __init__(self, parseTree, typeName, exprs = []): self.parseTree = parseTree self.exprs = [] # a list of expressions self.env = None self.children = [] self.typeName = typeName # the type (class/interface) this node belongs under - exprs = getParseTreeNodes(['expr'], parseTree) - for e in exprs: - self.exprs.append(makeNodeFromExpr(e, typeName)) + if exprs == []: + exprs = getParseTreeNodes(['expr'], parseTree) + for e in exprs: + self.exprs.append(makeNodeFromExpr(e, typeName)) + else: + # manually induce exprs + # for converting string concatenation to a method call + # see ExprPrimaryNodes:ExprNode on string concat + self.exprs = exprs self.children.extend(self.exprs) @@ -562,6 +568,48 @@ class ExprNode(ASTNode): or (self.right.myType.name =='java.lang.String' and self.left.myType.name not in ['void'])) and self.op == '+': self.myType = TypeStruct('java.lang.String', self.env.getNode('java.lang.String', 'type')) self.myType.link(self.env) + + # var1 + var2 === String.valueOf(var1).concat( String.valueOf(var2) ) + + # methodInvoc name LPAREN args RPAREN (because it's static) + # MethodInvNode + # ID = NameNode + # - name = "String.valueOf" + # args = ArgsNode + # - exprs = [self.left] + + # create MethodInvNode to call String.valueOf(left) and String.valueOf(right) + # 1. Make NameNode for String.valueOf + valueOfNameNode = NameNode(self.parseTree, True, self.typeName, "String.valueOf") + valueOfNameNode.env = self.env + # 2. Make ArgsNode for left and right + leftArg = ArgsNode(self.parseTree, self.typeName, [self.left]) + rightArg = ArgsNode(self.parseTree, self.typeName, [self.right]) + # 3. Put it all together + self.valueOfMethodInvLeft = MethodInvNode(self.parseTree, self.typeName, valueOfNameNode, leftArg) + self.valueOfMethodInvRight = MethodInvNode(self.parseTree, self.typeName, valueOfNameNode, rightArg) + # 4. Check type to be safe + self.valueOfMethodInvLeft.checkType() + self.valueOfMethodInvRight.checkType() + + + # methodInvoc primary PERIOD ID LPAREN args RPAREN + # MethodInvNode + # primary = self.left + # ID = NameNode + # - name = "concat" + # args = ArgsNode + # - exprs = [self.right] + + # create MethodInvNode to call left.concat(right) + # 1. Make NameNode for String.concat (name = "concat") + concatNameNode = NameNode(self.parseTree, True, self.typeName, "concat") + # 2. Make ArgsNode for right (already have from above!) + # 3. Put it all together + self.concatMethodInv = MethodInvNode(self.parseTree, self.typeName, concatNameNode, rightArg, self.left) + # 4. Check type to be safe + self.concatMethodInv.checkType() + return raise Exception("ERROR: Incompatible types. Left of {} type can't be used with right of {} type on operation {}".format(self.left.myType.name, self.right.myType.name, self.op)) @@ -905,7 +953,7 @@ class FieldAccessNode(ASTNode): # methodInvoc class MethodInvNode(ASTNode): # always list all fields in the init method to show the class structure - def __init__(self, parseTree, typeName): + def __init__(self, parseTree, typeName, ID = '', args = None, primary = None): self.parseTree = parseTree self.primary = None # can be empty self.ID = '' # can be either ID or compID @@ -915,12 +963,23 @@ class MethodInvNode(ASTNode): self.method = None self.typeName = typeName # the type (class/interface) this node belongs under - # input parse tree is either: methodInvoc primary PERIOD ID LPAREN args RPAREN - # methodInvoc name LPAREN args RPAREN - self.ID = NameNode(parseTree.children[-4], True, typeName) - self.args = ArgsNode(parseTree.children[-2], typeName) - if parseTree.children[0].name == 'primary': - self.primary = makeNodeFromAllPrimary(parseTree.children[0], typeName) + if ID == '' or args is None: + # input parse tree is either: methodInvoc primary PERIOD ID LPAREN args RPAREN + # methodInvoc name LPAREN args RPAREN + self.ID = NameNode(parseTree.children[-4], True, typeName) + self.args = ArgsNode(parseTree.children[-2], typeName) + if parseTree.children[0].name == 'primary': + self.primary = makeNodeFromAllPrimary(parseTree.children[0], typeName) + self.override = False + else: + # manually induce ID and args + # for converting string concatenation to a method call + # see ExprPrimaryNodes:ExprNode on string concat + self.ID = ID + self.args = args + if primary is not None: + self.primary = primary + self.override = True self.children.append(self.primary) self.children.append(self.args) @@ -963,7 +1022,7 @@ class MethodInvNode(ASTNode): if m: # check static - if (not self.ID.shouldBeStatic) and 'static' in m.mods: + if (not self.ID.shouldBeStatic and not self.override) and 'static' in m.mods: raise Exception("ERROR: Non-static access of static method {}.".format(m.name)) # check protected diff --git a/NameNode.py b/NameNode.py index 859f25fdeb799941053e0a70b25754de7ab09056..70ce82cf4de5bb8c57ac120ea9f530274ac48b5b 100644 --- a/NameNode.py +++ b/NameNode.py @@ -19,7 +19,7 @@ from codeGenNodes import genNameNode class NameNode(ASTNode): - def __init__(self, parseTree, methodInvoke, typeName): + def __init__(self, parseTree, methodInvoke, typeName, name = ""): self.parseTree = parseTree self.name = "" # str: stores original lex of the name (ID/COMPID) @@ -40,7 +40,14 @@ class NameNode(ASTNode): self.staticField = None self.prefixNodes = [] # stores the past prefix links so we can evaluate them one by one - self.name = getParseTreeNodes(["ID", "COMPID"], parseTree)[0].lex + if name == "": + self.name = getParseTreeNodes(["ID", "COMPID"], parseTree)[0].lex + else: + # manually induce name + # for converting string concatenation to a method call + # see ExprPrimaryNodes:ExprNode on string concat + self.name = name + self.IDs = self.name.split(".") # Updates the resolved/identified prefix diff --git a/UnitNodes.py b/UnitNodes.py index 606114766223e0f486d3e7238a877ad841611c2f..9490a010792631522fe581dac850809ecb1cd354 100644 --- a/UnitNodes.py +++ b/UnitNodes.py @@ -55,7 +55,7 @@ class LiteralNode(ASTNode): self.code += p("mov", "eax", "0", " set to literal false") return - # char TODO + # char if self.name == 'char': self.code += p("mov", "eax", str(self.getConstant()), " set to literal char") return