Skip to content
Snippets Groups Projects
Commit 3fb133b8 authored by Xun Yang's avatar Xun Yang
Browse files

Environment

parent 74954d14
No related branches found
No related tags found
No related merge requests found
...@@ -16,13 +16,15 @@ class ASTNode(): ...@@ -16,13 +16,15 @@ class ASTNode():
# call the same method in each class and its children recursively # call the same method in each class and its children recursively
# the methods that represent an action would return arguments to be used in # the methods that represent an action would return arguments to be used in
# the child nodes' method if neccessary # the child nodes' method if neccessary
def recurseAction(self, actionName, args): def recurseAction(self, actionName, args=None):
func = self.getattr(actionName) func = getattr(self, actionName)
result = None result = None
if func: if func and args:
result = func(args) result = func(args)
elif func:
result = func()
for c in self.children: for c in self.children:
c.recurseAction(result) c.recurseAction(actionName, result)
# use the parse tree to populate current AST node and construct child AST nodes # use the parse tree to populate current AST node and construct child AST nodes
def buildASTNodeRecursive(self): def buildASTNodeRecursive(self):
...@@ -35,8 +37,10 @@ class ASTNode(): ...@@ -35,8 +37,10 @@ class ASTNode():
pp.pprint(vars(self)) pp.pprint(vars(self))
pp.pprint("-----children-----") pp.pprint("-----children-----")
prefix += 1 prefix += 1
for c in self.children: return prefix
c.printNodePretty(prefix)
def printTree(self):
self.recurseAction('printNodePretty')
# Utils ###################################################### # Utils ######################################################
......
from CompNode import CompNode from CompNode import CompNode
from pprpint import pprint
from Env import GlobalEnv
# tree: (filename, parseTree) # tree: (filename, parseTree)
def astBuild(trees): def astBuild(trees):
...@@ -7,6 +9,27 @@ def astBuild(trees): ...@@ -7,6 +9,27 @@ def astBuild(trees):
ASTs.append((n, CompNode(t))) ASTs.append((n, CompNode(t)))
return ASTs return ASTs
def buildEnvAndLink(ASTs):
# build env
globalEnv = GlobalEnv()
for t in ASTs:
globalEnv.addtoEnv(t)
# build Env inside each class / interface
t.typeDcl.recurseAction("buildEnv")
# type Linking
for t in ASTs:
t.buildEnvFromImports(globalEnv)
# t.typeDcl.recurseAction("linkType")
print ("\n\n###################### global Env ####################")
pprint(GlobalEnv)
for t in ASTs:
printt ("\n\n###################### Comp Unit Env ####################")
t.recurseAction("printEnv")
#######################################################
# # ast: Node # # ast: Node
# def weed(ast): # def weed(ast):
# res = ast.weed() # res = ast.weed()
......
from ASTNode import ScopeNode, Environment class Env:
nodeToNamespace = dict({
'FieldNode': 'field',
'InterNode': 'interface',
'ClassNode': 'class',
'MethodNode': 'method'
})
################################################################## def __init__(self, parentEnv):
self.parentEnv = parentEnv
self.map = {} # {(name, namespace) -> node}
# give a list of parseTrees, returns the global Environemnt object and def addtoEnv(node):
# a list of classNodes with globalEnv attached to them # use node.__class__.__name__ to get namespace
def buildGlobalEnv(parseTrees): nodeType = node.__class__.__name__
gEnv = Environment(None) if not self.nodeToNamespace.contains(nodeType):
ASTs = [] namespace = 'local'
namespace = self.nodeToNamespace.get(nodeType)
# Add to Env
key = (node.name, namespace)
if self.map.contains(key):
raise Exception('ERROR: Declaration of {} is already in current Environment'.format(node.name))
self.map[key] = node
for t in parseTrees: def getNode(name, namespace):
# add imports key = (name, namespace)
imports = getParseTreeNodes(['importDcl'], t)
for i in imports:
importNames = getParseTreeNodes(['ID', 'COMPID', 'IMPORTALL'], i)
for n in importNames:
gEnv.addName(n.lex, 'package', None)
# TODO: figure out package name if self.map.contains(key):
packages = getParseTreeNodes('packageDcl', t) return self.map.get(key)
pNames = [] elif namespace == 'local':
for p in packages: key2 = (name, 'field')
pNames.extend(getParseTreeNodes(['ID', 'COMPID'], p)) if self.map.contains(key2):
if pNames: return self.map.get(key2)
pNames = pNames[0] elif parentEnv:
else: return parentEnv.getNode(name, namespace)
pNames = 'no packageName' raise Exception("ERROR: Can't find definition of {} in the Environment".format(name))
# add class to global Env ###################################
classDcl = getParseTreeNodes('classDcl', t)
interfaceDcl = getParseTreeNodes('interfaceDcl', t)
if not classDcl: class GlobalEnv(Env):
intNode = ScopeNode(interfaceDcl[0], gEnv) def __init__(self):
ASTs.append(intNode) super().__init__(None)
gEnv.addName(pNames+ " " + intNode.name, 'interface', intNode) #self.map = {} # {(Canonical name, namespace) -> node}
else: self.pacakgeMap = {} # {packageName -> {(simpleName, namespace) -> node}}
classNode = ScopeNode(classDcl[0], gEnv) # A map of maps
ASTs.append(classNode) # contains duplicate info as self.map for easy searching
gEnv.addName(pNames+ " " + classNode.name, 'class', classNode)
#prints # input: Compiliation Unit Node (CompNode)
def addtoEnv(node):
pName = node.packageName
typeDcl = node.typeDcl
typeDclType = typeDcl.__class__.__name__
# at global level there are only class and interface
namespace = self.nodeToNamespace.get(typeDclType)
print('----------- global env ------------') # Add to map
for g in gEnv.map: mapKey = (pName + '.' + typeDclType.name, namespace)
print(g) if self.map.contains(mapKey):
for gg in gEnv.map[g]: raise Exception('ERROR: Declaration of {} is already in current Environment'.format(pName + '.' + typeDclType.name))
print(gg) self.map[mapKey] = typeDcl
print('----------- ASTs -----------------')
for a in ASTs:
print(a.name)
return gEnv, ASTs
# Utils: given a parseTree and a list of names, traverse the tree # Add to packageMap
# to return a list of tree nodes(on the same level) that pMapKey = (typeDclType.name, namespace)
# has one of those names if not self.pacakgeMap.contains(pName):
def getParseTreeNodes(names, tree): self.pacakgeMap[pName] = {}
result = []
if tree.name in names: if not self.pacakgeMap[pName].contains(pMapKey):
return result.append(tree) raise Exception('ERROR: Declaration of {} is already in current Environment'.format(pName + '.' + typeDclType.name))
if not tree.children: self.pacakgeMap[pName][pMapKey] = typeDcl
return []
for n in tree.children: # Use getNode() from base class to get node using Canonical Name (full name)
if n.name in names:
result.append(n) # method for getting all the nodes under a package (import All)
else: # returns a dict of types under that package name
result.extend(getParseTreeNodes(names, n)) def getNodesByPackage(pName):
return result if not self.pacakgeMap.contains(pName):
raise Exception("ERROR: Can't find definition of package {} in the Environment".format(pName))
return self.pacakgeMap.get(pName)
...@@ -103,7 +103,7 @@ def run(testFiles): ...@@ -103,7 +103,7 @@ def run(testFiles):
for (n, t) in ASTs: for (n, t) in ASTs:
print(n) print(n)
print("--------------------") print("--------------------")
t.printNodePretty() t.printTree()
print("\n \n\n \n") print("\n \n\n \n")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment