示例#1
0
def get_tal_of_evaluated_node(node: ast.Node, env: en.Environment) -> en.Type:
    if node.node_type == ast.LITERAL:
        node: ast.Literal
        return LITERAL_TYPE_TABLE[node.lit_type]
    elif node.node_type == ast.STRING_LITERAL:
        node: ast.StringLiteralNode
        return en.Type("char", node.byte_length)
    elif node.node_type == ast.NAME_NODE:
        node: ast.NameNode
        return env.get_type_arr_len(node.name, (node.line_num, node.file))
    elif node.node_type == ast.UNARY_OPERATOR:
        node: ast.UnaryOperator
        tal = get_tal_of_evaluated_node(node.value, env)
        if node.operation == "unpack":
            if len(tal.type_name) > 1 and tal.type_name[0] == "*":
                return en.Type(tal.type_name[1:])
            else:
                raise lib.TypeException("Cannot unpack a non-pointer type")
        elif node.operation == "pack":
            return en.Type("*" + tal.type_name)
        else:
            return tal
    elif node.node_type == ast.BINARY_OPERATOR:
        node: ast.BinaryOperator
        return get_tal_of_evaluated_node(node.left, env)
    elif node.node_type == ast.FUNCTION_CALL:
        node: ast.FuncCall
        call_obj = node.call_obj
        if call_obj.node_type == ast.NAME_NODE:
            func_group: dict = env.get_function(call_obj.name,
                                                (node.line_num, node.file))
            arg_types = []
            for orig_arg in node.args.lines:
                tal = get_tal_of_evaluated_node(orig_arg, env)
                arg_types.append(tal)
            types_id = en.args_type_hash(arg_types)
            func = func_group[types_id]
            return func.r_tal
    elif node.node_type == ast.INDEXING_NODE:  # array
        node: ast.IndexingNode
        # return get_tal_of_ordinary_node(node.call_obj, env)
        tal_co = get_tal_of_evaluated_node(node.call_obj, env)
        if en.is_array(tal_co):
            return en.Type(tal_co.type_name, *tal_co.array_lengths[1:])
        elif tal_co.type_name[0] == "*":
            return en.Type(tal_co.type_name[1:])
        else:
            raise lib.TypeException()
    elif node.node_type == ast.IN_DECREMENT_OPERATOR:
        node: ast.InDecrementOperator
        return get_tal_of_evaluated_node(node.value, env)
    elif node.node_type == ast.NULL_STMT:
        return en.Type("*void")
示例#2
0
def eval_comparison(cmp_func, lp, l_tal: en.Type, rp, r_tal: en.Type,
                    env) -> int:
    if l_tal.type_name in PRIMITIVE_TYPES and r_tal.type_name in PRIMITIVE_TYPES and not en.is_array(l_tal) and \
            not en.is_array(r_tal):
        l_len = PRIMITIVE_TYPES[l_tal.type_name]
        r_len = PRIMITIVE_TYPES[r_tal.type_name]
        lb = mem.MEMORY.get(lp, l_len)
        rb = mem.MEMORY.get(rp, r_len)

        if l_tal.type_name == "int":
            if r_tal.type_name == "int":
                cmp = typ.int_cmp_int(lb, rb)
                return cmp_func(cmp)
        elif l_tal.type_name == "char":
            if r_tal.type_name == "char":
                cmp = typ.char_cmp_char(lb, rb)
                return cmp_func(cmp)
    elif l_tal.type_name[0] == "*":
        l_ptr_b = mem.MEMORY.get(lp, l_tal.total_len())
        # l_ptr = typ.bytes_to_int(l_ptr_b)
        if r_tal.type_name[0] == "*":
            r_ptr_b = mem.MEMORY.get(rp, r_tal.total_len())
            # r_ptr = typ.bytes_to_int(r_ptr_b)
            # print(l_ptr_b ,r_ptr_b)
            cmp = typ.int_cmp_int(l_ptr_b, r_ptr_b)
            return cmp_func(cmp)
        else:
            raise lib.TypeException(
                "Comparing pointer type '{}' to primitive type '{}'".format(
                    en.type_to_readable(l_tal), en.type_to_readable(r_tal)))
    else:
        print(2131212321)
示例#3
0
def eval_call(node: ast.FuncCall, env: en.Environment):
    func_group: dict = evaluate(node.call_obj, env)
    some_func = list(func_group.values())[0]

    if isinstance(some_func, Function):
        return call_function(func_group, node.args.lines, env)
    elif isinstance(some_func, NativeFunction):
        return call_native_function(some_func, node.args.lines, env)
    else:
        raise lib.TypeException("Call on a non-callable object")
示例#4
0
def int_op_any(lv: bytes, right_ptr: int, right_tal: en.Type,
               op_set: dict) -> int:
    if right_tal.type_name in op_set:
        rv = mem.MEMORY.get(right_ptr, right_tal.total_len())
        op_func = op_set[right_tal.type_name]
        res = op_func(lv, rv)
        return mem.MEMORY.allocate(res)
    elif right_tal.type_name[0] == "*":
        rv = mem.MEMORY.get(right_ptr, PTR_LEN)
        op_func = op_set["int"]
        res = op_func(lv, rv)
        return mem.MEMORY.allocate(res)
    else:
        raise lib.TypeException("Cannot operates int with {}".format(
            en.type_to_readable(right_tal)))
示例#5
0
def basic_arithmetic(op_set: dict, left_ptr: int, left_tal: en.Type,
                     right_ptr: int, right_tal: en.Type,
                     env: en.Environment) -> int:
    if left_tal.type_name in op_set:
        left_len = left_tal.total_len()
        lv = mem.MEMORY.get(left_ptr, left_len)
        # print(right_ptr)
        return int_op_any(lv, right_ptr, right_tal, op_set[left_tal.type_name])
    elif left_tal.type_name[0] == "*":
        ptr_len = mem.MEMORY.pointer_length
        lv = mem.MEMORY.get(left_ptr, ptr_len)
        return int_op_any(lv, right_ptr, right_tal, op_set["int"])
    else:
        raise lib.TypeException("Cannot operates {}".format(
            en.type_to_readable(right_tal)))
示例#6
0
def get_indexing_location_and_unit_len(node: ast.IndexingNode,
                                       env: en.Environment) -> (int, int):
    l_ptr = evaluate(node.call_obj, env)
    l_tal = get_tal_of_node_self(node, env)
    if en.is_array(l_tal):
        depth = index_node_depth(node)
        unit_length = l_tal.total_len()
        for i in range(depth):
            unit_length //= l_tal.array_lengths[i]
    elif l_tal.type_name[0] == "*":
        ptr_b = mem.MEMORY.get(l_ptr, PTR_LEN)
        l_ptr = typ.bytes_to_int(ptr_b)
        unit_length = mem.MEMORY.get_type_size(l_tal.type_name[1:])
    else:
        raise lib.TypeException("Type '{}' not supporting indexing".format(
            en.type_to_readable(l_tal)))

    arg_ptr = evaluate(node.arg, env)  # arg type must be int
    arg_b = mem.MEMORY.get(arg_ptr, mem.MEMORY.get_type_size("int"))
    arg_v = typ.bytes_to_int(arg_b)
    return l_ptr + arg_v * unit_length, unit_length
示例#7
0
def eval_binary_operation(node: ast.BinaryOperator, env: en.Environment):
    if node.assignment and node.operation[:-1] in BINARY_OP_TABLE:
        left = evaluate(node.left, env)
        right = evaluate(node.right, env)

        ltl = get_tal_of_evaluated_node(node.left, env)
        rtl = get_tal_of_evaluated_node(node.right, env)

        op_type = BINARY_OP_TABLE[node.operation[:-1]]
        res = basic_arithmetic(op_type, left, ltl, right, rtl, env)
        mem.MEMORY.mem_copy(res, left, ltl.total_len())
        return left
    elif node.operation in BINARY_OP_TABLE:
        left = evaluate(node.left, env)
        right = evaluate(node.right, env)

        ltl = get_tal_of_evaluated_node(node.left, env)
        rtl = get_tal_of_evaluated_node(node.right, env)

        # print(left, right)

        op_type = BINARY_OP_TABLE[node.operation]
        return basic_arithmetic(op_type, left, ltl, right, rtl, env)
    elif node.operation in COMPARE_TABLE:
        left = evaluate(node.left, env)
        right = evaluate(node.right, env)

        ltl = get_tal_of_evaluated_node(node.left, env)
        rtl = get_tal_of_evaluated_node(node.right, env)

        cmp = COMPARE_TABLE[node.operation]
        return eval_comparison(cmp, left, ltl, right, rtl, env)
    else:
        raise lib.TypeException(
            "Unexpected binary operator '{}', in file '{}', at line {}".format(
                node.operation, node.file, node.line_num))
示例#8
0
def call_function(func_group: dict, orig_args: list, call_env: en.Environment):
    arg_types = []
    for orig_arg in orig_args:
        tal = get_tal_of_evaluated_node(orig_arg, call_env)
        arg_types.append(tal)

    types_id = en.args_type_hash(arg_types)
    func = func_group[types_id]

    rtn_type = func.r_tal
    rtn_len = rtn_type.total_len()
    rtn_loc = mem.MEMORY.allocate_empty(rtn_len)

    scope = en.FunctionEnvironment(func.outer_scope)
    mem.MEMORY.push_stack()

    for i in range(len(orig_args)):
        param: ParameterPair = func.params[i]
        orig_arg = orig_args[i]
        p = evaluate(orig_arg, call_env)
        tal = param.tal
        total_len = tal.total_len()
        arg_ptr = mem.MEMORY.allocate_empty(total_len)
        scope.define_var(param.name, tal, arg_ptr)
        mem.MEMORY.mem_copy(p, arg_ptr, total_len)

    r = evaluate(func.body, scope)

    if rtn_len > 0 and r is None:
        raise lib.TypeException(
            "Missing return statement of a function declared to return type '{}'"
            .format(en.type_to_readable(rtn_type)))
    mem.MEMORY.mem_copy(r, rtn_loc, rtn_len)

    mem.MEMORY.restore_stack()
    return rtn_loc
示例#9
0
 def add_namespace(self, namespace):
     raise lib.TypeException("Sub environment does not support namespace definition")
示例#10
0
def eval_assignment_node(node: ast.AssignmentNode, env: en.Environment):
    r = evaluate(node.right, env)
    lf = node.line_num, node.file

    if node.left.node_type == ast.NAME_NODE:
        name: str = node.left.name
        if node.level == ast.FUNC_DEFINE:
            if not isinstance(r, Function):
                raise lib.TypeException("Unexpected function declaration")
            env.define_function(name, r)
        else:
            tal = get_tal_of_evaluated_node(node.left, env)
            total_len = tal.total_len()
            rv = mem.MEMORY.get(r, total_len)
            current_ptr = env.get(name, lf)
            mem.MEMORY.set(current_ptr, rv)
            # env.assign(name, r, lf)
    elif node.left.node_type == ast.TYPE_NODE:
        type_node: ast.TypeNode = node.left
        tal = get_tal_of_defining_node(type_node.right, env)
        name: str = type_node.left.name
        total_len = tal.total_len()
        if total_len == 0:  # array with undefined length
            tal = get_tal_of_evaluated_node(node.right, env)
            total_len = tal.total_len()

        ptr = mem.MEMORY.allocate_empty(total_len)
        if r != 0:  # is not undefined
            mem.MEMORY.mem_copy(r, ptr, total_len)

        if node.level == ast.VAR:
            env.define_var(name, tal, ptr)
        elif node.level == ast.CONST:
            env.define_const(name, tal, ptr)
    elif node.left.node_type == ast.DOT:
        dot: ast.Dot = node.left
        l_ptr = evaluate(dot.left, env)
        l_tal = get_tal_of_evaluated_node(dot.left, env)
        # print(l_tal)
        struct: Struct = env.get_struct(l_tal.type_name)
        attr: ast.NameNode = dot.right
        pos_in_struct = struct.get_attr_pos(attr.name)
        attr_tal = struct.get_attr_tal(attr.name)
        attr_len = attr_tal.total_len()
        rv = mem.MEMORY.get(r, attr_len)
        mem.MEMORY.set(l_ptr + pos_in_struct, rv)
    elif node.left.node_type == ast.INDEXING_NODE:
        eval_setitem(node.left, r, env)
    elif node.left.node_type == ast.UNARY_OPERATOR:
        uo: ast.UnaryOperator = node.left
        tal = get_tal_of_evaluated_node(uo, env)
        total_len = tal.total_len()
        l_ptr = evaluate(uo, env)
        rv = mem.MEMORY.get(r, total_len)
        if uo.operation == "pack" and uo.value.node_type == ast.NAME_NODE:
            ri = typ.bytes_to_int(rv)
            env.assign(uo.value.name, ri, lf)
        else:
            mem.MEMORY.set(l_ptr, rv)
    else:
        raise lib.TypeException("Currently unimplemented")