def __init__(self, classinfo): super().__init__() members = inspect.getmembers(classinfo) init_func = [m[1] for m in members if m[0] == '__init__'] assert(len(init_func) == 1) func = init_func[0] self.inst = func self.name = func.__name__ self.filename = inspect.getfile(func) sourcelines = inspect.getsourcelines(func) if sourcelines is None or len(sourcelines) < 1: utils.print_warning('Failed to parase {}'.format(classinfo), utils.LineProperty()) return self.lineno = sourcelines[1] self.classinfo = classinfo original_code = inspect.getsource(func) code = utils.clip_head(original_code) self.args.analyze_args(func) ast_ = gast.ast_to_gast(ast.parse(code)).body[0] self.ast = canonicalizer.Canonicalizer().visit(ast_)
def veval_ast_call(astc: 'AstContext', local_field: 'values.Field', graph: 'Graph') -> 'Attribute': assert (isinstance(astc.nast, gast.gast.Call)) lineprop = utils.LineProperty(astc.lineno, astc.filename) func = veval_ast(astc.c(astc.nast.func), local_field, graph) if func == None or not func.has_obj(): utils.print_warning( 'Unknown function "{}" is called'.format( get_ast_name_forcibly(astc.nast.func)), lineprop) return None func_obj = try_get_ref(func, 'call', lineprop) func_value = try_get_value(func, 'call', lineprop) finput = functions.FunctionArgInput() for arg in astc.nast.args: arg_ = veval_ast(astc.c(arg), local_field, graph) finput.inputs.append(try_get_ref(arg_, 'call', lineprop)) for keyword in astc.nast.keywords: arg_ = veval_ast(astc.c(keyword.value), local_field, graph) finput.keywords[keyword.arg] = try_get_ref(arg_, 'call', lineprop) lineprop = utils.LineProperty(astc.lineno, astc.filename) # check arguments for o in finput.inputs: if o is None: utils.print_warning( 'Invalid arguments exists in "{}"'.format( get_ast_name_forcibly(astc.nast.func)), lineprop) return None ret = None if isinstance(func_value, values.FuncValue): ret = func_value.func.vcall(func_value.module, graph, func_value.obj, finput, lineprop) return ret elif isinstance(func_value, values.Instance): # __call__ call_func_ref = func_obj.try_get_and_store_obj('__call__', graph.root_graph) if call_func_ref is not None: func_value = call_func_ref.get_value() ret = func_value.func.vcall(func_value.module, graph, func_obj, finput, lineprop) return ret if config.show_warnings: print('Unknown function is called in L.{}'.format(astc.lineno)) return None
def veval(op: 'nodes.BinOpType', left: 'values.Value', right: 'values.Value', lineprop: 'utils.LineProperty'): initialize_lazy() if isinstance(left, values.ListValue): return functions.generate_value_with_same_type(left) if isinstance(left, values.TupleValue): return functions.generate_value_with_same_type(left) if isinstance(right, values.NumberValue) or isinstance( right, values.TensorValue): if not isinstance(left, values.NumberValue) and not isinstance( left, values.TensorValue): utils.print_warning('Unestimated type is on left', lineprop) left = values.NumberValue(0.0) left_type = left.dtype right_type = right.dtype if not config.float_restrict: if left_type == utils.dtype_float64: left_type = utils.dtype_float32 if right_type == utils.dtype_float64: right_type = utils.dtype_float32 if left_type is None: left_type = np.array(0.0, np.float32).dtype if right_type is None: right_type = np.array(0.0, np.float32).dtype result_type = None for v in binop_type_table: if v[0] == op and v[1] == left_type and v[2] == right_type: result_type = v[3] break assert (result_type is not None) if isinstance(right, values.TensorValue): return functions.generate_value_with_type(right, type_=result_type) else: return functions.generate_value_with_type(left, type_=result_type) return values.Value()
def try_get_ref(value, name, lineprop) -> 'values.ValueRef': if value is None: utils.print_warning('Failed to get value in "{}".'.format(name), lineprop) return None if isinstance(value, values.Value): assert (False) if isinstance(value, values.Attribute): if value.has_obj(): return value.get_ref() if isinstance(value, values.ValueRef): return value return None
def veval_ast_bin_op(astc: 'AstContext', local_field: 'values.Field', graph: 'Graph'): """ eval binary operation. Ex. a + b, b // c, etc """ assert (isinstance(astc.nast, gast.gast.BinOp)) lineprop = utils.LineProperty(astc.lineno, astc.filename) left = veval_ast(astc.c(astc.nast.left), local_field, graph) right = veval_ast(astc.c(astc.nast.right), local_field, graph) left_value = try_get_value(left, 'compare', lineprop) right_value = try_get_value(right, 'compare', lineprop) binop = nodes.BinOpType.Unknown if isinstance(astc.nast.op, gast.Add): binop = nodes.BinOpType.Add elif isinstance(astc.nast.op, gast.Sub): binop = nodes.BinOpType.Sub elif isinstance(astc.nast.op, gast.Mult): binop = nodes.BinOpType.Mul elif isinstance(astc.nast.op, gast.Div): binop = nodes.BinOpType.Div elif isinstance(astc.nast.op, gast.FloorDiv): binop = nodes.BinOpType.FloorDiv else: utils.print_warning('Unknown binary operator {}'.format(astc.nast.op), lineprop) return None node_bin_op = nodes.NodeBinOp(left_value, right_value, binop, astc.lineno) ret_value = veval_bin.veval(binop, left_value, right_value, lineprop) node_bin_op.set_outputs([ret_value]) graph.add_node(node_bin_op) return values.ValueRef(ret_value)
def veval_ast_attribute(astc: 'AstContext', local_field: 'values.Field', graph: 'Graph', option: 'VEvalOption' = None) -> 'Attribute': assert (isinstance(astc.nast, gast.gast.Attribute)) lineprop = utils.LineProperty(astc.lineno, astc.filename) from_module = True if option is not None and option.eval_as_written_target: from_module = False value = veval_ast(astc.c(astc.nast.value), local_field, graph) value_ref = try_get_ref(value, 'attribute', lineprop) if (value_ref is None): utils.print_warning( 'Unknown or disabled attribute "{}" is accessed'.format( get_ast_name_forcibly(astc.nast.value)), lineprop) return None attr = value_ref.get_field().get_attribute(astc.nast.attr, graph.root_graph, from_module) # property(getter) if attr.has_obj() and isinstance( attr.get_ref().get_value(), values.FuncValue) and attr.get_ref().get_value().func.is_property: func_value = attr.get_ref().get_value() ret = func_value.func.vcall(func_value.module, graph, func_value.obj, functions.FunctionArgInput(), lineprop) return ret if attr.has_obj(): return attr # if attr is not found gotten_obj = value_ref.try_get_and_store_obj(astc.nast.attr, graph.root_graph) if gotten_obj is not None: return value_ref.get_field().get_attribute(astc.nast.attr, graph.root_graph, from_module) if option is not None and option.eval_as_written_target: return attr # value is unknown if value is None: utils.print_warning( 'Assigning value {} is not found'.format( get_ast_name_forcibly(astc.nast.value)), lineprop) else: utils.print_warning( 'Assigning value {} is not found'.format( get_ast_name_forcibly(astc.nast.attr)), lineprop) return None
def veval_ast_tuple(astc: 'AstContext', local_field: 'values.Field', graph: 'Graph', option: 'VEvalOption' = None): assert (isinstance(astc.nast, gast.gast.Tuple)) lineprop = utils.LineProperty(astc.lineno, astc.filename) if option is not None and option.eval_as_written_target: vs = [] for v in astc.nast.elts: a_ = veval_ast(astc.c(v), local_field, graph, option=option) vs.append(a_) return vs else: vs_ref = [] vs = [] for v in astc.nast.elts: a_ = veval_ast(astc.c(v), local_field, graph, option=option) v_ = try_get_ref(a_, 'tuple', lineprop) if v_ is None: utils.print_warning('Unknown tuple element {}'.format(v), lineprop) return None vs_ref.append(v_) vs.append(v_.get_value()) v_.in_container = True tuple_value = values.TupleValue(vs_ref) node = nodes.NodeGenerate('Tuple', vs, line=lineprop) node.set_outputs([tuple_value]) graph.add_node(node) return values.ValueRef(tuple_value)
def try_get_value(value, name, lineprop, is_none_allowed=False) -> 'values.Value': if value is None: utils.print_warning('Failed to get value in "{}".'.format(name), lineprop) return None if isinstance(value, values.NoneValue) and not is_none_allowed: if config.show_warnings: print('Value {} is none. in {}'.format(name, lineprop)) return None if isinstance(value, values.Value): return value if isinstance(value, values.ValueRef): return value.get_value() if isinstance(value, values.Attribute): return value.get_ref().get_value() raise Exception('Value {} is invalid. in L.{}'.format(name, lineprop))
def veval_ast_if(astc: 'AstContext', local_field: 'values.Field', graph: 'Graph'): assert (isinstance(astc.nast, gast.gast.If)) lineprop = utils.LineProperty(astc.lineno, astc.filename) # if condition test = veval_ast(astc.c(astc.nast.test), local_field, graph) test_value = try_get_value(test, 'if', lineprop) id_str = str(utils.get_guid()) if_id = 'if_' + id_str true_id = 'true_' + id_str false_id = 'false_' + id_str # True values.push_history(true_id) true_graph = Graph() true_graph.root_graph = graph.root_graph true_graph.name = 'True' true_body = veval_ast(astc.c(astc.nast.body), local_field, true_graph) true_value_inputs = values.get_inputs() true_value_outputs = values.get_outputs() values.pop_history() # False values.push_history(false_id) false_graph = Graph() false_graph.root_graph = graph.root_graph false_graph.name = 'False' false_body = veval_ast(astc.c(astc.nast.orelse), local_field, false_graph) false_value_inputs = values.get_inputs() false_value_outputs = values.get_outputs() values.pop_history() # generate pairs value_pairs = {} for v in true_value_inputs: key = str(v.field.id) + '_' + v.name if not (key in value_pairs.keys()): value_pairs[key] = {} value_pairs[key]['field'] = v.field value_pairs[key]['name'] = v.name value_pairs[key]['true_input_value'] = v.input_value value_pairs[key]['true_input_body_value'] = v.value value_pairs[key]['true_input_obj'] = v.obj for v in true_value_outputs: key = str(v.field.id) + '_' + v.name if not (key in value_pairs.keys()): value_pairs[key] = {} value_pairs[key]['field'] = v.field value_pairs[key]['name'] = v.name value_pairs[key]['true_output_body_value'] = v.value value_pairs[key]['true_output_obj'] = v.obj for v in false_value_inputs: key = str(v.field.id) + '_' + v.name if not (key in value_pairs.keys()): value_pairs[key] = {} value_pairs[key]['field'] = v.field value_pairs[key]['name'] = v.name value_pairs[key]['false_input_value'] = v.input_value value_pairs[key]['false_input_body_value'] = v.value value_pairs[key]['false_input_obj'] = v.obj for v in false_value_outputs: key = str(v.field.id) + '_' + v.name if not (key in value_pairs.keys()): value_pairs[key] = {} value_pairs[key]['field'] = v.field value_pairs[key]['name'] = v.name value_pairs[key]['false_output_body_value'] = v.value value_pairs[key]['false_output_obj'] = v.obj inputs = [] outputs = [] for k, v in value_pairs.items(): name = v['name'] field = v['field'] input_value = None true_input_body_value = None false_input_body_value = None # search input value if 'true_input_value' in v: input_value = v['true_input_value'] elif 'false_input_value' in v: input_value = v['false_input_value'] if input_value is not None: if 'true_input_body_value' in v: true_input_body_value = v['true_input_body_value'] else: true_input_body_value = functions.generate_value_with_same_type( input_value) if 'false_input_body_value' in v: false_input_body_value = v['false_input_body_value'] else: false_input_body_value = functions.generate_value_with_same_type( input_value) true_output_body_value = None false_output_body_value = None output_value = None # search output value if 'true_output_body_value' in v: true_output_body_value = v['true_output_body_value'] if 'false_output_body_value' in v: false_output_body_value = v['false_output_body_value'] if true_output_body_value is not None or false_output_body_value is not None: if true_output_body_value is None: if true_input_body_value is not None: # e.x. not changed true_output_body_value = true_input_body_value else: # e.x. make a value in false statement true_output_body_value = functions.generate_value_with_same_type( false_output_body_value, is_dummy_value=True) if false_output_body_value is None: if false_input_body_value is not None: # e.x. not changed false_output_body_value = false_input_body_value else: # e.x. make a value in true statement false_output_body_value = functions.generate_value_with_same_type( true_output_body_value, is_dummy_value=True) # check types between true and false true_output_body_value_type = None false_output_body_value_type = None if true_output_body_value is not None and true_output_body_value.is_not_none_or_any_value( ): true_output_body_value_type = true_output_body_value if false_output_body_value is not None and false_output_body_value.is_not_none_or_any_value( ): false_output_body_value_type = false_output_body_value if true_output_body_value_type is not None and false_output_body_value_type is not None and type( true_output_body_value_type) != type( false_output_body_value_type): utils.print_warning( 'Values with differenet type were generated {} between true ande false' .format(k), lineprop) if true_output_body_value_type != None: output_value = functions.generate_value_with_same_type( true_output_body_value_type) elif false_output_body_value_type != None: output_value = functions.generate_value_with_same_type( false_output_body_value_type) elif true_output_body_value is not None: output_value = functions.generate_value_with_same_type( true_output_body_value) elif false_output_body_value is not None: output_value = functions.generate_value_with_same_type( false_output_body_value) if input_value is not None: inputs.append(input_value) true_graph.add_input_value(true_input_body_value) false_graph.add_input_value(false_input_body_value) if output_value is not None: outputs.append(output_value) true_graph.add_output_value(true_output_body_value) false_graph.add_output_value(false_output_body_value) if 'true_output_obj' in v and not 'false_output_obj' in v: obj = v['true_output_obj'] elif not 'true_output_obj' in v and 'false_output_obj' in v: obj = v['false_output_obj'] elif 'true_output_obj' in v and 'false_output_obj' in v: obj = None else: assert (False) if obj is not None: obj.revise(output_value) field.get_attribute(name).revise(obj) elif field.get_attribute(name).has_obj(): field.get_attribute(name).get_ref().revise(output_value) else: field.get_attribute(name).revise(values.ValueRef(output_value)) node = nodes.NodeIf(test_value, inputs, true_graph, false_graph, astc.lineno) node.set_outputs(outputs) graph.add_node(node) return None
def veval(op: 'nodes.BinOpType', left: 'values.Value', right: 'values.Value', lineprop: 'utils.LineProperty'): initialize_lazy() if isinstance(left, values.ListValue): return functions.generate_value_with_same_type(left) if isinstance(left, values.TupleValue): return functions.generate_value_with_same_type(left) if isinstance(left, values.StrValue): if not (isinstance(right, values.NumberValue) or isinstance( right, values.StrValue) or isinstance(right, values.BoolValue) or isinstance(right, values.TupleValue)): assert False if not (left.has_constant_value() or right.has_constant_value()): assert False if op == nodes.BinOpType.Add: if not isinstance(right, values.StrValue): assert False return values.StrValue(left.internal_value + right.internal_value) elif op == nodes.BinOpType.Mod: right_internal_value = right.internal_value if isinstance(right, values.TupleValue): values_ = [] for ref in right_internal_value: if not (isinstance(ref.get_value(), values.NumberValue) or isinstance(ref.get_value(), values.StrValue) or isinstance(ref.get_value(), values.BoolValue)): assert False if not ref.get_value().has_constant_value(): assert False values_.append(ref.get_value()) right_internal_value = tuple(value.internal_value for value in values_) return values.StrValue(left.internal_value % right_internal_value) return values.StrValue("") if isinstance(right, values.NumberValue) or isinstance( right, values.TensorValue): if not isinstance(left, values.NumberValue) and not isinstance( left, values.TensorValue): utils.print_warning('Unestimated type is on left', lineprop) left = values.NumberValue(0.0) left_type = left.dtype right_type = right.dtype if not config.float_restrict: if left_type == utils.dtype_float64: left_type = utils.dtype_float32 if right_type == utils.dtype_float64: right_type = utils.dtype_float32 if left_type is None: left_type = np.array(0.0, np.float32).dtype if right_type is None: right_type = np.array(0.0, np.float32).dtype result_type = None for v in binop_type_table: if v[0] == op and v[1] == left_type and v[2] == right_type: result_type = v[3] break assert (result_type is not None) if isinstance(right, values.TensorValue): return functions.generate_value_with_type(right, type_=result_type) else: return functions.generate_value_with_type(left, type_=result_type) return values.Value()