From 4d714afd8111fd43ac6b7acaf526e9aec80fc9d0 Mon Sep 17 00:00:00 2001 From: Katherine Braught <braught2@illinois.edu> Date: Mon, 11 Apr 2022 12:33:21 -0500 Subject: [PATCH] save earlier progress --- pythonparser.py | 168 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 166 insertions(+), 2 deletions(-) diff --git a/pythonparser.py b/pythonparser.py index a6a86790..2ee152f5 100644 --- a/pythonparser.py +++ b/pythonparser.py @@ -14,6 +14,8 @@ import ast #from cfg import CFG #import clang.cfg +from treelib import Node, Tree + class Edge: def __init__(self, source, dest, guards, resets): self.source = source @@ -241,6 +243,159 @@ def createTransition(path, vertices, modes): edges.append(Edge(sourceindex, destindex, guards, resets)) return edges +class controller_ast(): + def __init__(self, code): + self.code = code + self.tree = ast.parse(code) + self.nodect= 1 + self.statementtree, self.variables, self.modes = self.initalwalktree(code, tree) + self.vertices = [] + + + #assume that currentModes is a list of all node types! + #TODO: should we not force all modes be listed? Or rerun for each unknown/don't care node? Or add them all to the list + def getNextModes(self, currentModes): + #walk the tree and capture all paths that have modes that are listed. Path is a list of statements + paths = [] + rootid = self.statementtree.root + currnode = self.statementtree.get_node(rootid) + paths = self.walkstatements(currnode, currentModes) + + return paths + + def walkstatements(self, parentnode, currentModes): + nextsPaths = [] + for node in self.statementtree.children(parentnode.identifier): + statement = node.tag + print(statement) + print(node) + if isinstance(statement, Guard) and statement.isModeCheck(): + if statement.mode in currentModes: + newPaths = self.walkstatements(node, currentModes) + for path in newPaths: + nextsPaths.append(statement.extend(path)) + if len(nextsPaths) == 0: + nextsPaths.append(statement) + + else: + newPaths =self.walkstatements(node, currentModes) + for path in newPaths: + nextsPaths.append(statement.extend(path)) + if len(nextsPaths) == 0: + nextsPaths.append(statement) + + return nextsPaths + + + def create_json(input_file_name, output_file_name): + with open(input_file_name) as in_json_file: + input_json = json.load(in_json_file) + + output_dict = { + } + + output_dict.update(input_json) + + edges = [] + guards = [] + resets = [] + + for path in paths: + transitions = createTransition(path, vertices, modes) + for edge in transitions: + edges.append([edge.source, edge.dest]) + guards.append(guardString(edge.guards)) + resets.append(resetString(edge.resets)) + + output_dict['vertex'] = vertexStrings + #print(vertices) + output_dict['variables'] = variables + # #add edge, transition(guards) and resets + output_dict['edge'] = edges + #print(len(edges)) + output_dict['guards'] = guards + #print(len(guards)) + output_dict['resets'] = resets + #print(len(resets)) + + output_json = json.dumps(output_dict, indent=4) + outfile = open(output_file_name, "w") + outfile.write(output_json) + outfile.close() + + print("wrote json to " + output_file_name) + + #inital tree walk, parse into a tree of resets/modes + def initalwalktree(self, code, tree): + vars = [] + out = [] + mode_dict = {} + for node in ast.walk(tree): #don't think we want to walk the whole thing because lose ordering/depth + if isinstance(node, ast.ClassDef): + if "Mode" in node.name: + modeType = str(node.name) + modes = [] + for modeValue in node.body: + modes.append(str(modeValue.targets[0].id)) + mode_dict[modeType] = modes + if isinstance(node, ast.FunctionDef): + if node.name == 'controller': + #print(node.body) + out = self.parsenodelist(code, node.body, False, Tree(), None) + #print(type(node.args)) + args = node.args.args + for arg in args: + if "mode" not in arg.arg: + vars.append(arg.arg) + #todo: what to add for return values + return [out, vars, mode_dict] + + + + def parsenodelist(self, code, nodes, addResets, tree, parent): + childrens_guards=[] + childrens_resets=[] + recoutput = [] + #tree.show() + if parent == None: + s = Statement("root", None, None) + tree.create_node(s, self.nodect) + parent = self.nodect + self.nodect += 1 + + for childnode in nodes: + if isinstance(childnode, ast.Assign) and addResets: + reset = Reset.parseReset(childnode, code) + #print("found reset: " + reset.code) + childrens_resets.append(reset) + if isinstance(childnode, ast.If): + guard = Guard.parseGuard(childnode, code) + childrens_guards.append(guard) + #print("found if statement: " + guard.code) + newTree = Tree() + temp_node_num = self.nodect + self.nodect += 1 + newTree.create_node([guard], temp_node_num) + #print(self.nodect) + tempresults = self.parsenodelist(code, childnode.body, True, newTree, temp_node_num) + #for result in tempresults: + recoutput.append(tempresults) + + + #pathsafterme = [] + if len(childrens_resets) > 0: + #print("adding node:" + str(self.nodect) + "with parent:" + str(parent)) + tree.create_node(childrens_resets, self.nodect, parent= parent) + parent = self.nodect + self.nodect += 1 + for subtree in recoutput: + #print("adding subtree:" + " to parent:" + str(parent)) + tree.paste(parent, subtree) + + + return tree + + ##main code### #print(sys.argv) if __name__ == "__main__": @@ -264,7 +419,17 @@ if __name__ == "__main__": code = f.read() tree = ast.parse(code) #tree = ast.parse() - paths, variables, modes = walktree(code, tree) + #paths, variables, modes = walktree(code, tree) + + test = controller_ast(code) + paths = test.getNextModes("NormalA;Normal3") + variables = test.variables + modes = test.modes + + for path in paths: + for item in path: + print(item.code) + print() #print("Paths found:") #for result in paths: @@ -279,7 +444,6 @@ if __name__ == "__main__": output_dict.update(input_json) - #TODO: create graph! vertices = [] vertexStrings = [] for vertex in itertools.product(*modes.values()): -- GitLab