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