def for_of_statement_to_gast(node): gast = {} gast["type"] = "forOfStatement" gast["init"] = pr.node_to_gast(node.target) gast["iter"] = pr.node_to_gast(node.iter) gast["body"] = pr.node_to_gast(node.body) return gast
def dictionary_to_gast(node): """ takes a dictionary converts it for the generic AST """ gast = {"type": "dict", "elements": []} for i in range(len(node.keys)): prop = {"type": "property"} prop["key"] = pr.node_to_gast(node.keys[i]) prop["value"] = pr.node_to_gast(node.values[i]) gast["elements"].append(prop) return gast
def aug_assign_to_gast(node): """ takes python ast and converts augmented assignment into generic AST example: exampleIn: AugAssign(target=Name(id='x', ctx=Store()), op=Add(), value=Num(n=1)) exampleOut: {'type': 'augAssign', 'left': {'type': 'name', 'value': 'x'}, 'op': '+=', 'right': {'type': 'num', 'value': 1}} """ gast = {"type": "augAssign"} gast["left"] = pr.node_to_gast(node.target) gast["op"] = augop_to_str(node.op) gast["right"] = pr.node_to_gast(node.value) return gast
def call_to_gast(node): """ takes python ast call node and converts to generic ast format example print('hello'): exampleIn Call(func=Name(id='print'), args=[Str(s='hello')], keywords=[]) exampleOut {'type': 'funcCall', 'value': {'type': 'logStatement'}, 'args': [{'type': 'str', 'value': 'hello'}]} """ gast = {} gast["type"] = "funcCall" gast["value"] = pr.node_to_gast(node.func) gast["args"] = pr.node_to_gast(node.args) return gast
def bin_op_to_gast(node): """ converts a python ast BinOp and to a readable string recursively example 3+4: exampleIn BinOp(left=Num(n=3), op=Add, right=Num(n=4)) exampleOut {'type': 'binOp', 'op': '+', 'left': {'type': 'num', 'value': 3}, 'right': {'type': 'num', 'value': 4}} """ if pyop_to_str(node.op) == None: return {"type": "error", "value": "unsupported"} gast = {"type": "binOp", "op": pyop_to_str(node.op)} gast["left"] = pr.node_to_gast(node.left) gast["right"] = pr.node_to_gast(node.right) return gast
def arg_helper(arg_list, default_list, param_list): # if arg_list empty return if not arg_list: return param_list # if default list empty arg not assigned if not default_list: param_list.insert(0, pr.node_to_gast(arg_list.pop())) return arg_helper(arg_list, default_list, param_list) else: gast = {"type": "assignPattern"} gast["left"] = pr.node_to_gast(arg_list.pop()) gast["right"] = pr.node_to_gast(default_list.pop()) param_list.insert(0, gast) return arg_helper(arg_list, default_list, param_list)
def compare_helper(node_list, op_list): if pyop_to_str(op_list[0]) == None: return {"type": "error", "value": "unsupported"} gast = {} gast["type"] = "binOp" gast["left"] = pr.node_to_gast(node_list[0]) gast["op"] = pyop_to_str(op_list[0]) if len(node_list[1:]) > 1: gast["right"] = compare_helper(node_list[1:], op_list[1:]) else: gast["right"] = pr.node_to_gast(node_list[1]) return gast
def for_range_statement_to_gast(node): """ Converts for statement of the structure for i in range() to gast Notes about functionality - only works with 2-3 range args - only works if arg nodes are of type ast.Num (in case of positives) or ast.UnaryOp (in case of negatives). Does not work with vars. """ gast = {} try: gast["type"] = "forRangeStatement" ast.dump(node) args = node.iter.args start_num = get_start_num(args) end_num = get_end_num(args) step_num = get_step_num(args) gast["init"] = for_range_statement_init_helper(node.target, start_num) gast["test"] = for_range_statement_test_helper(node.target, start_num, end_num) gast["update"] = for_range_statement_update_helper( node.target, step_num) gast["body"] = pr.node_to_gast(node.body) except: gast = {"type": "error", "value": "unsupported"} return gast
def bool_op_helper(node_list, op_str): """ Recursively handles case where Python creates a list of literals """ if op_str == None: return {"type": "error", "value": "unsupported"} gast = {} gast["type"] = "boolOp" gast["left"] = pr.node_to_gast(node_list[0]) gast["op"] = op_str if len(node_list[1:]) > 1: gast["right"] = bool_op_helper(node_list[1:], op_str) else: gast["right"] = pr.node_to_gast(node_list[1]) return gast
def assign_to_gast(node): """ takes python ast assigns and converts them to generic ast format note, that this assumes only a single assignment (i.e. x = 4) for now, it does not work for things link x,y = 4,5 example: exampleIn Assign(targets=[Name(id='x')], value=Num(n=5)) exampleOut {'type': 'varAssign', 'kind': 'let', 'varId': {'type': 'name', 'value': 'x'}, 'varValue': 5} """ gast = {} gast["type"] = "varAssign" gast["kind"] = "let" gast["varId"] = pr.node_to_gast( node.targets[0]) # FIXME: understand when targets won't be 0 gast["varValue"] = pr.node_to_gast(node.value) return gast
def expr_to_gast(node): """ Takes python ast.expr node and converts them to the generic ast format example print('hello') exampleIn Expr(value=Call(func=Name(id='print'), args=[Str(s='hello')], keywords=[])) exampleOut {'type': 'funcCall', 'value': {'type': 'logStatement'}, 'args': [{'type': 'str', 'value': 'hello'}]} """ return pr.node_to_gast(node.value)
def array_to_gast(node): """ takes an array of elements and recursively calls node_to_gast on each element """ gast = {"type": "arr"} list_elem = [] for elem in ast.iter_child_nodes(node): if type(elem) != ast.Load: list_elem.append(pr.node_to_gast(elem)) gast["elements"] = list_elem return gast
def module_to_gast(node): """ takes ast node of type module and returns a generic ast for that node example print("hello"): node (input): Module(body=[Expr(value=Call(func=Name(id='print'), args=[Str(s='hello')], keywords=[]))]) gast (output): {'type': 'root', 'body': [{'type': 'funcCall', 'value': {'type': 'logStatement'}, 'args': [{'type': 'str', 'value': 'hello'}]}]} """ gast = {"type": "root"} gast["body"] = pr.node_to_gast(node.body) return gast
def unary_op_to_gast(node): """ takes node of type unaryOp and converts it to our generic ast represenations """ pyop = pyop_to_str(node.op) if pyop == None: return {"type": "error", "value": "unsupported"} return { "type": "unaryOp", "op": pyop, "arg": pr.node_to_gast(node.operand) }
def py_to_gast(python_input): """ takes pyton code and converts it to a node node is then dealt with by node_to_gast """ input_ast = '' try: input_ast = ast.parse(python_input) except: # this will signal to translate that error occurred return None return py_router.node_to_gast(input_ast)
def for_range_statement_init_helper(var_node, start_num): """ Takes a node representing start of loop and the variable node. returns a gast node representing value for the init key in forRangeStatement gast Example: ast.parse("for i in range(0,10,2)") input: var_node = ast.Name(i), start_num = 10, output: {'type': 'varAssign', 'kind': 'let', 'varId': {'type': 'name', 'value': 'i'}, 'varValue': {'type': 'num', 'value': 0}} """ gast = {} gast["type"] = "varAssign" gast["kind"] = "let" gast["varId"] = pr.node_to_gast(var_node) gast["varValue"] = num_to_gast(start_num) return gast
def node_list_to_gast(node): """ takes a node that represents a list of nodes. returns a list of gast example print("hello"): node (input): [Expr(value=Call(func=Name(id='print'), args=[Str(s='hello')], keywords=[]))] gast (output): [{'type': 'funcCall', 'value': {'type': 'logStatement'}, args': [{'type': 'str', 'value': 'hello'}]}] example array of strings: input: [Str(s='hello'), Str(s='world')] output:[{'type': 'str', 'value': 'hello'}, {'type': 'str', 'value': 'world'}] """ gast_list = [] for i in range(0, len(node)): gast_list.append(pr.node_to_gast(node[i])) return gast_list
def attribute_to_gast(node): """ handles attributes for python expressions """ gast = {"value": pr.node_to_gast(node.value)} # The tool only currently supports the built in functions below # TODO add other built in function translations attribute = node.attr if attribute in {func.name for func in built_in.py_built_in_functions}: gast["type"] = "builtInAttribute" gast["id"] = built_in.py_built_in_functions[attribute].value return gast gast["type"] = "attribute" gast["id"] = attribute return gast
def for_range_statement_test_helper(var_node, start_num, end_num): """ Takes a variable node, start node and end node. Returns gast node representing value for the test key in forRangeStatement gast Example: ast.parse("for i in range(0,10,2)") input: var_node = ast.Name(i), start_num = 10, end_num = 2 output: {'type': 'binOp', 'left': {'type': 'name', 'value': 'i'}, 'op': '<', 'right': {'type': 'num', 'value': 10}} """ # first need to figure out whether to use "<" or ">" if start_num <= end_num: op_str = "<" else: op_str = ">" gast = {} gast["type"] = "binOp" gast["left"] = pr.node_to_gast(var_node) gast["op"] = op_str gast["right"] = num_to_gast(end_num) return gast
def for_range_statement_update_helper(var_node, step_num): """ takes a variable node and an integer that represents the step. Returns a gast node representing value for the update key in forRangeStatement gast Example: ast.parse("for i in range(0,10,2)") input: var_node = ast.Name(i), step_num = 2 output: {'type': 'augAssign', 'left': {'type': 'name', 'value': 'i'}, 'op': '+=', 'right': {'type': 'num', 'value': 2}} """ if step_num < 0: op_str = "-=" right_gast = { "type": "num", "value": -1 * step_num # FIXME: this feels very hacky } else: op_str = "+=" right_gast = {"type": "num", "value": step_num} gast = {} gast["type"] = "augAssign" gast["left"] = pr.node_to_gast(var_node) gast["op"] = op_str gast["right"] = right_gast return gast
def while_statement_to_gast(node): gast = {} gast["type"] = "whileStatement" gast["body"] = pr.node_to_gast(node.body) gast["test"] = pr.node_to_gast(node.test) return gast
def subscript_to_gast(node): gast = {"type": "subscript"} gast["index"] = pr.node_to_gast(node.slice.value) gast["value"] = pr.node_to_gast( node.value) # TODO expand to cover slices of a list return gast
def function_def_to_gast(node): gast = {"type": "functionDeclaration"} gast["id"] = pr.node_to_gast(node.name) gast["params"] = pr.node_to_gast(node.args) gast["body"] = pr.node_to_gast(node.body) return gast
def arg_to_gast(node): """ takes argument from function declaration and makes into gast node """ return pr.node_to_gast(node.arg)
def lamda_to_gast(node): gast = {"type": "arrowExpression"} gast["params"] = pr.node_to_gast(node.args) gast["body"] = [] gast["body"].append(pr.node_to_gast(node.body)) return gast
def return_statement_to_gast(node): """ Turns return statement into gast """ return {"type": "returnStatement", "value": pr.node_to_gast(node.value)}