TheTypeNode.py 3.15 KiB
from AST import ASTNode, getParseTreeNodes
##################################################################################
# TypeNode: an AST node represents a type
# TypeStruct: a struct holding type information for type checking
# TypeNode represents a parse tree unit that contains a type,
# TypeStruct is not a unit on parseTree, it is just a struct living in different AST nodes to keep track of their type
class TypeNode(ASTNode):
# always list all fields in the init method to show the class structure
def __init__(self, parseTree, typeName):
self.parseTree = parseTree
self.name = ''
self.env = None
self.children = []
self.myType = "" # empty string or typeStruct
if parseTree == 'VOID':
self.myType = TypeStruct('void', None)
else:
nameNodes = getParseTreeNodes(['BOOLEAN', 'BYTE', 'CHAR', 'INT', 'SHORT'], parseTree)
if nameNodes:
self.myType = TypeStruct(nameNodes[0].lex, None)
else:
self.myType = TypeStruct(getParseTreeNodes(['ID', 'COMPID'], parseTree)[0].lex, None)
nameNodes = getParseTreeNodes(['LSQRBRACK'], parseTree)
if nameNodes:
self.myType.isArray = True
def __eq__(self, other):
return self.myType == other.myType
def linkType(self):
self.myType.link(self.env)
class TypeStruct():
def __init__(self, name, typePointer):
self.isArray = False
self.isPrimitive = False
self.typePointer = typePointer
self.name = name
if name in ['boolean', 'byte', 'char', 'int', 'short', 'void']:
self.isPrimitive = True
def link(self, env):
if not self.isPrimitive:
self.typePointer = env.getNode(self.name, 'type')
self.name = self.typePointer.canonName # Use canonName instead of simple name for comparison
def __eq__(self, other):
return self.name == other.name
def isNum(self):
return self.name in ['int', 'short', 'char', 'byte']
# if self is assignable to input typeNode: self := right
# right is either a TypeNode or a LiteralNode
def assignable(self, right):
if self.isArray == right.isArray:
if self == right \
or (right.name in ['short', 'char', 'byte'] and self.name == 'int') \
or (right.name == 'byte' and self.name == 'short') \
or (not self.isPrimitive and right.name == 'null'):
return True
# check if self is super of right
elif ((not self.isPrimitive) and (not right.isPrimitive)) \
and (self.name in getSupers(right.typePointer)):
return True
return False
if right.isArray and self.name in ['java.lang.Object', 'java.lang.Cloneable', 'java.io.Serializable']:
return True
return False
# helper: get list of all super class/interface of a ClassInterNode
def getSupers(classType):
result = ["java.lang.Object"]
if not classType.super:
return result
for s in classType.super:
result.append(s.canonName)
result.extend(getSupers(s))
return result