Skip to content
Snippets Groups Projects

New new string

Merged Xun Yang requested to merge new-new-string into master
3 files
+ 174
25
Compare changes
  • Side-by-side
  • Inline
Files
3
+ 86
12
@@ -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)
@@ -582,6 +588,49 @@ 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
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
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))
@@ -701,6 +750,20 @@ class ExprNode(ASTNode):
# String Add TODO
if (self.left.myType.name =='java.lang.String' or self.right.myType.name =='java.lang.String') \
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
# Number Add, Subtract, Multiply
if self.op in ['+', '-', '*']:
@@ -928,7 +991,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
@@ -938,12 +1001,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)
@@ -986,7 +1060,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
Loading