Skip to content
Snippets Groups Projects

String concat

Merged Xun Yang requested to merge string_concat into new-string
3 files
+ 174
25
Compare changes
  • Side-by-side
  • Inline
Files
3
+ 86
12
@@ -93,16 +93,22 @@ def helperDisambigName(node):
@@ -93,16 +93,22 @@ def helperDisambigName(node):
# args exprs, exprs expr COMMA exprs
# args exprs, exprs expr COMMA exprs
class ArgsNode(ASTNode):
class ArgsNode(ASTNode):
# always list all fields in the init method to show the class structure
# 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.parseTree = parseTree
self.exprs = [] # a list of expressions
self.exprs = [] # a list of expressions
self.env = None
self.env = None
self.children = []
self.children = []
self.typeName = typeName # the type (class/interface) this node belongs under
self.typeName = typeName # the type (class/interface) this node belongs under
exprs = getParseTreeNodes(['expr'], parseTree)
if exprs == []:
for e in exprs:
exprs = getParseTreeNodes(['expr'], parseTree)
self.exprs.append(makeNodeFromExpr(e, typeName))
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)
self.children.extend(self.exprs)
@@ -562,6 +568,49 @@ class ExprNode(ASTNode):
@@ -562,6 +568,49 @@ class ExprNode(ASTNode):
or (self.right.myType.name =='java.lang.String' and self.left.myType.name not in ['void'])) and self.op == '+':
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 = TypeStruct('java.lang.String', self.env.getNode('java.lang.String', 'type'))
self.myType.link(self.env)
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
 
valueOfMethodInvLeft = MethodInvNode(self.parseTree, self.typeName, valueOfNameNode, leftArg)
 
valueOfMethodInvRight = MethodInvNode(self.parseTree, self.typeName, valueOfNameNode, rightArg)
 
# 4. Check type to be safe
 
# valueOfMethodInvLeft.checkType()
 
# 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
 
rightArgMethodInv = ArgsNode(self.parseTree, self.typeName, [valueOfMethodInvRight])
 
# 3. Put it all together
 
self.concatMethodInv = MethodInvNode(self.parseTree, self.typeName, concatNameNode, rightArgMethodInv, valueOfMethodInvLeft)
 
# 4. Check type to be safe
 
self.concatMethodInv.checkType()
 
return
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))
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))
@@ -681,6 +730,20 @@ class ExprNode(ASTNode):
@@ -681,6 +730,20 @@ class ExprNode(ASTNode):
# String Add TODO
# String Add TODO
if (self.left.myType.name =='java.lang.String' or self.right.myType.name =='java.lang.String') \
if (self.left.myType.name =='java.lang.String' or self.right.myType.name =='java.lang.String') \
and self.op == '+':
and self.op == '+':
 
# String.valueOf(left)
 
# if not hasattr(self.valueOfMethodInvLeft, "code"):
 
# self.valueOfMethodInvLeft.codeGen()
 
# self.code += self.valueOfMethodInvLeft.code
 
 
# String.valueOf(right)
 
# if not hasattr(self.valueOfMethodInvLeft, "code"):
 
# self.valueOfMethodInvLeft.codeGen()
 
# self.code += self.valueOfMethodInvLeft.code
 
 
# ( String.valueOf(right) ).concat( left )
 
if not hasattr(self.concatMethodInv, "code"):
 
self.concatMethodInv.codeGen()
 
self.code += self.concatMethodInv.code
return
return
# Number Add, Subtract, Multiply
# Number Add, Subtract, Multiply
if self.op in ['+', '-', '*']:
if self.op in ['+', '-', '*']:
@@ -905,7 +968,7 @@ class FieldAccessNode(ASTNode):
@@ -905,7 +968,7 @@ class FieldAccessNode(ASTNode):
# methodInvoc
# methodInvoc
class MethodInvNode(ASTNode):
class MethodInvNode(ASTNode):
# always list all fields in the init method to show the class structure
# 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.parseTree = parseTree
self.primary = None # can be empty
self.primary = None # can be empty
self.ID = '' # can be either ID or compID
self.ID = '' # can be either ID or compID
@@ -915,12 +978,23 @@ class MethodInvNode(ASTNode):
@@ -915,12 +978,23 @@ class MethodInvNode(ASTNode):
self.method = None
self.method = None
self.typeName = typeName # the type (class/interface) this node belongs under
self.typeName = typeName # the type (class/interface) this node belongs under
# input parse tree is either: methodInvoc primary PERIOD ID LPAREN args RPAREN
if ID == '' or args is None:
# methodInvoc name LPAREN args RPAREN
# input parse tree is either: methodInvoc primary PERIOD ID LPAREN args RPAREN
self.ID = NameNode(parseTree.children[-4], True, typeName)
# methodInvoc name LPAREN args RPAREN
self.args = ArgsNode(parseTree.children[-2], typeName)
self.ID = NameNode(parseTree.children[-4], True, typeName)
if parseTree.children[0].name == 'primary':
self.args = ArgsNode(parseTree.children[-2], typeName)
self.primary = makeNodeFromAllPrimary(parseTree.children[0], 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.primary)
self.children.append(self.args)
self.children.append(self.args)
@@ -963,7 +1037,7 @@ class MethodInvNode(ASTNode):
@@ -963,7 +1037,7 @@ class MethodInvNode(ASTNode):
if m:
if m:
# check static
# 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))
raise Exception("ERROR: Non-static access of static method {}.".format(m.name))
# check protected
# check protected
Loading