Skip to content
Snippets Groups Projects
Commit 0bcb8572 authored by braught2's avatar braught2
Browse files

update main method to show easy usage

parent 422ebd69
No related branches found
No related tags found
No related merge requests found
...@@ -244,16 +244,45 @@ def createTransition(path, vertices, modes): ...@@ -244,16 +244,45 @@ def createTransition(path, vertices, modes):
return edges return edges
class controller_ast(): class controller_ast():
'''
Initalizing function for a controller_ast object.
Reads in the code and parses it to a python ast and statement tree.
Statement tree is a tree of nodes that contain a list in their data. The list contains a single guard or a list of resets.
Variables (inputs to the controller) are collected.
Modes are collected from all enums that have the word "mode" in them.
Vertices are generated by taking the products of mode types.
'''
def __init__(self, code): def __init__(self, code):
self.code = code self.code = code
self.tree = ast.parse(code) self.tree = ast.parse(code)
#statement tree is a tree of nodes that contain a list in their data. The list contains a single guard or a list of resets self.statementtree, self.variables, self.modes = self.initalwalktree(code, self.tree)
self.statementtree, self.variables, self.modes = self.initalwalktree(code, tree)
self.vertices = [] self.vertices = []
self.vertexStrings = []
for vertex in itertools.product(*self.modes.values()):
self.vertices.append(vertex)
vertexstring = vertex[0]
for index in range(1,len(vertex)):
vertexstring += ";" + vertex[index]
self.vertexStrings.append(vertexstring)
self.paths = None
'''
Function to populate paths variable with all paths of the controller.
'''
def getAllPaths(self):
currentModes = []
for modeTypes in self.modes.values():
currentModes.extend(modeTypes)
self.paths = self.getNextModes(currentModes)
return self.paths
#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 getNextModes takes in a list of current modes. It should include all modes.
getNextModes returns a list of paths that can be followed when in the given mode.
A path is a list of statements, all guards and resets along the path. They are in the order they are encountered in the code.
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): def getNextModes(self, currentModes):
#walk the tree and capture all paths that have modes that are listed. Path is a list of statements #walk the tree and capture all paths that have modes that are listed. Path is a list of statements
paths = [] paths = []
...@@ -263,6 +292,10 @@ class controller_ast(): ...@@ -263,6 +292,10 @@ class controller_ast():
return paths return paths
'''
Helper function to walk the statement tree from parentnode and find paths that are allowed in the currentMode.
Returns a list of paths.
'''
def walkstatements(self, parentnode, currentModes): def walkstatements(self, parentnode, currentModes):
nextsPaths = [] nextsPaths = []
...@@ -292,7 +325,15 @@ class controller_ast(): ...@@ -292,7 +325,15 @@ class controller_ast():
return nextsPaths return nextsPaths
def create_json(input_file_name, output_file_name): '''
Function to create a json of the full graph.
Requires that paths class variables has been set.
'''
def create_json(self, input_file_name, output_file_name):
if not self.paths:
print("Cannot call create_json without calling getAllPaths")
return
with open(input_file_name) as in_json_file: with open(input_file_name) as in_json_file:
input_json = json.load(in_json_file) input_json = json.load(in_json_file)
...@@ -305,16 +346,16 @@ class controller_ast(): ...@@ -305,16 +346,16 @@ class controller_ast():
guards = [] guards = []
resets = [] resets = []
for path in paths: for path in self.paths:
transitions = createTransition(path, vertices, modes) transitions = createTransition(path, self.vertices, self.modes)
for edge in transitions: for edge in transitions:
edges.append([edge.source, edge.dest]) edges.append([edge.source, edge.dest])
guards.append(guardString(edge.guards)) guards.append(guardString(edge.guards))
resets.append(resetString(edge.resets)) resets.append(resetString(edge.resets))
output_dict['vertex'] = vertexStrings output_dict['vertex'] = self.vertexStrings
#print(vertices) #print(vertices)
output_dict['variables'] = variables output_dict['variables'] = self.variables
# #add edge, transition(guards) and resets # #add edge, transition(guards) and resets
output_dict['edge'] = edges output_dict['edge'] = edges
#print(len(edges)) #print(len(edges))
...@@ -331,6 +372,10 @@ class controller_ast(): ...@@ -331,6 +372,10 @@ class controller_ast():
print("wrote json to " + output_file_name) print("wrote json to " + output_file_name)
#inital tree walk, parse into a tree of resets/modes #inital tree walk, parse into a tree of resets/modes
'''
Function called by init function. Walks python ast and parses to a statement tree.
Returns a statement tree (nodes contain a list of either a single guard or muliple resets), the variables, and a mode dictionary
'''
def initalwalktree(self, code, tree): def initalwalktree(self, code, tree):
vars = [] vars = []
out = [] out = []
...@@ -346,17 +391,19 @@ class controller_ast(): ...@@ -346,17 +391,19 @@ class controller_ast():
if isinstance(node, ast.FunctionDef): if isinstance(node, ast.FunctionDef):
if node.name == 'controller': if node.name == 'controller':
#print(node.body) #print(node.body)
out = self.parsenodelist(code, node.body, False, Tree(), None) statementtree = self.parsenodelist(code, node.body, False, Tree(), None)
#print(type(node.args)) #print(type(node.args))
args = node.args.args args = node.args.args
for arg in args: for arg in args:
if "mode" not in arg.arg: if "mode" not in arg.arg:
vars.append(arg.arg) vars.append(arg.arg)
#todo: what to add for return values #todo: what to add for return values
return [out, vars, mode_dict] return [statementtree, vars, mode_dict]
'''
Helper function for initalwalktree which parses the statements in the controller function into a statement tree
'''
def parsenodelist(self, code, nodes, addResets, tree, parent): def parsenodelist(self, code, nodes, addResets, tree, parent):
childrens_guards=[] childrens_guards=[]
childrens_resets=[] childrens_resets=[]
...@@ -407,80 +454,37 @@ if __name__ == "__main__": ...@@ -407,80 +454,37 @@ if __name__ == "__main__":
input_file_name = 'billiard_input.json' #sys.argv[2] input_file_name = 'billiard_input.json' #sys.argv[2]
output_file_name = 'out.json' #sys.argv[3] output_file_name = 'out.json' #sys.argv[3]
with open(input_file_name) as in_json_file: with open(input_file_name) as in_json_file:
input_json = json.load(in_json_file) input_json = json.load(in_json_file)
output_dict = { output_dict = {
} }
#read in the controler code
f = open(input_code_name,'r') f = open(input_code_name,'r')
code = f.read() code = f.read()
tree = ast.parse(code)
#tree = ast.parse()
#paths, variables, modes = walktree(code, tree)
test = controller_ast(code) #parse the controller code into our controller ast objct
paths = test.getNextModes("NormalA;Normal3") controller_obj = controller_ast(code)
variables = test.variables
modes = test.modes
#demonstrate you can check getNextModes after only initalizing
paths = controller_obj.getNextModes("NormalA;Normal3")
print("Results") print("Results")
for path in paths: for path in paths:
for item in path: for item in path:
print(item.code) print(item.code)
print() print()
print("Done") print("Done")
#print("Paths found:")
#for result in paths:
# for item in result:
#item.print()
#print(item.mode)
#print(item.modeType)
# print()
#print("Modes found: ")
#print(modes)
output_dict.update(input_json)
vertices = []
vertexStrings = []
for vertex in itertools.product(*modes.values()):
vertices.append(vertex)
vertexstring = vertex[0]
for index in range(1,len(vertex)):
vertexstring += ";" + vertex[index]
vertexStrings.append(vertexstring)
edges = [] #attempt to write to json, fail because we haven't populated paths yet
guards = [] controller_obj.create_json(input_file_name, output_file_name)
resets = []
for path in paths: controller_obj.getAllPaths()
transitions = createTransition(path, vertices, modes)
for edge in transitions: controller_obj.create_json(input_file_name, output_file_name)
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)
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