示例#1
0
    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_)
示例#2
0
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
示例#3
0
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()
示例#4
0
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
示例#5
0
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)
示例#6
0
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
示例#7
0
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)
示例#8
0
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))
示例#9
0
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
示例#10
0
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()