Пример #1
0
    def build_body_ir(self,
                      parent_symbol_table: SymbolTable,
                      concrete_func: ConcreteFunction,
                      body_context: CodegenContext,
                      ir_func_args: Optional[List[ir.Value]] = None):
        if not body_context.emits_ir or ir_func_args is None: return
        assert not self.is_extern

        template_parameter_names = [
            t.identifier
            for t in concrete_func.signature.placeholder_template_types
        ]
        template_args = concrete_func.template_args

        argument_symbols = {}
        for identifier, ir_value, mutates, typ in zip(
                concrete_func.arg_identifiers, ir_func_args,
                concrete_func.arg_mutates, concrete_func.arg_types):
            if mutates:
                argument_symbols[
                    identifier] = VariableSymbol.make_ref_to_variable(
                        ir_value, ReferenceType(typ), identifier, body_context)
            else:
                ir_value.name = identifier
                symbol = VariableSymbol.make_new_variable(
                    ReferenceType(typ), identifier, body_context)
                body_context.builder.store(ir_value, symbol.ir_alloca)
                argument_symbols[identifier] = symbol

        body_symbol_table = parent_symbol_table.make_child_scope(
            inherit_outer_variables=False,
            new_function=concrete_func,
            type_substitutions=zip(template_parameter_names, template_args),
            new_symbols=argument_symbols)

        # build function body
        self.body_scope.build_scope_ir(scope_symbol_table=body_symbol_table,
                                       scope_context=body_context)
        # maybe add implicit return
        if not body_context.is_terminated:
            return_pos = TreePosition(
                self.pos.word,
                self.pos.from_pos if len(self.body_scope.stmt_list) == 0 else
                self.body_scope.stmt_list[-1].pos.to_pos, self.pos.to_pos)
            return_ast = ReturnStatementAst(return_pos, [])
            if concrete_func.return_type != SLEEPY_UNIT:
                raise_error(
                    'Not all branches within function declaration of %r return something'
                    % self.identifier, return_ast.pos)
            return_ast.build_ir(symbol_table=body_symbol_table,
                                context=body_context)
        assert body_context.is_terminated
Пример #2
0
def _make_ref_symbol(symbol_table: SymbolTable,
                     context: CodegenContext) -> TypeTemplateSymbol:
    del symbol_table  # only to keep API consistent
    del context
    pointee_type = PlaceholderTemplateType(identifier='T')
    ref_type = ReferenceType(pointee_type=pointee_type)
    return TypeTemplateSymbol(template_parameters=[pointee_type],
                              signature_type=ref_type)
Пример #3
0
def test_exclude_type():
    from sleepy.types import exclude_type, UnionType, ReferenceType
    from sleepy.builtin_symbols import SLEEPY_INT, SLEEPY_BOOL, SLEEPY_DOUBLE
    assert_equal(exclude_type(SLEEPY_INT, SLEEPY_NEVER), SLEEPY_INT)
    assert_equal(exclude_type(SLEEPY_INT, SLEEPY_INT), SLEEPY_NEVER)
    assert_equal(
        exclude_type(UnionType({
            SLEEPY_INT: 0,
            SLEEPY_DOUBLE: 1
        }, 8), SLEEPY_DOUBLE), UnionType({SLEEPY_INT: 0}, 8))
    assert_equal(
        exclude_type(UnionType({
            SLEEPY_INT: 0,
            SLEEPY_DOUBLE: 1
        }, 8), SLEEPY_INT), UnionType({SLEEPY_DOUBLE: 1}, 8))
    assert_equal(
        exclude_type(UnionType({
            SLEEPY_INT: 0,
            SLEEPY_DOUBLE: 1
        }, 8), SLEEPY_BOOL), UnionType({
            SLEEPY_INT: 0,
            SLEEPY_DOUBLE: 1
        }, 8))
    assert_equal(
        exclude_type(ReferenceType(SLEEPY_INT), ReferenceType(SLEEPY_INT)),
        SLEEPY_NEVER)
    assert_equal(exclude_type(ReferenceType(SLEEPY_INT), SLEEPY_NEVER),
                 ReferenceType(SLEEPY_INT))
    assert_equal(
        exclude_type(
            ReferenceType(UnionType({
                SLEEPY_INT: 0,
                SLEEPY_BOOL: 1
            }, 4)), ReferenceType(SLEEPY_INT)),
        ReferenceType(UnionType({SLEEPY_BOOL: 1}, 4)))
    assert_equal(
        exclude_type(
            ReferenceType(UnionType({
                SLEEPY_INT: 0,
                SLEEPY_BOOL: 1
            }, 4)), ReferenceType(SLEEPY_BOOL)),
        ReferenceType(UnionType({SLEEPY_INT: 0}, 4)))
Пример #4
0
def test_struct_self_referencing():
    from sleepy.types import StructType, PlaceholderTemplateType, PartialIdentifiedStructType, ReferenceType
    from sleepy.builtin_symbols import SLEEPY_INT
    context = make_test_context()

    struct_identity = StructIdentity("List", context=context)
    T = PlaceholderTemplateType(identifier="T")
    ListTPartial = PartialIdentifiedStructType(identity=struct_identity,
                                               template_param_or_arg=[T])
    ListT = StructType(identity=struct_identity,
                       template_param_or_arg=[T],
                       member_identifiers=["val", "next"],
                       member_types=[T, ReferenceType(ListTPartial)],
                       partial_struct_type=ListTPartial)
    assert_equal(ListT.member_types, [T, ReferenceType(ListT)])

    Int = SLEEPY_INT
    ListInt = ListT.replace_types({T: Int})
    assert isinstance(ListInt, StructType)
    assert_equal(ListInt.member_types, [Int, ReferenceType(ListInt)])
Пример #5
0
def test_bind_and_unbind():
    from sleepy.types import TypedValue, ReferenceType
    from sleepy.builtin_symbols import SLEEPY_INT
    context = make_test_context(emits_ir=False)

    ref_int = TypedValue(typ=ReferenceType(SLEEPY_INT),
                         ir_val=None,
                         num_unbindings=0)
    assert ref_int.num_possible_unbindings() == 1
    int = ref_int.copy_collapse(context=context, name='bind')
    assert int.type == SLEEPY_INT
    assert int.num_possible_unbindings() == 0
    assert int.num_unbindings == 0

    unbound_ref_int = ref_int.copy_unbind()
    assert unbound_ref_int.num_unbindings == 1
    assert unbound_ref_int.num_possible_unbindings() == 1

    ref_int_ = unbound_ref_int.copy_collapse(context=context, name='bind')
    assert ref_int_.type == ReferenceType(SLEEPY_INT)
    assert ref_int_.num_unbindings == 1
    assert ref_int_.num_possible_unbindings() == 1
Пример #6
0
def test_copy_collapse():
    from sleepy.builtin_symbols import SLEEPY_INT, SLEEPY_DOUBLE
    Int = TypedValue(typ=SLEEPY_INT, num_unbindings=0, ir_val=None)
    RefInt = TypedValue(typ=ReferenceType(SLEEPY_INT),
                        num_unbindings=0,
                        ir_val=None)
    Int_RefInt = TypedValue(typ=UnionType.from_types([Int.type, RefInt.type]),
                            num_unbindings=0,
                            ir_val=None)
    RefInt_Int = TypedValue(typ=UnionType.from_types([RefInt.type, Int.type]),
                            num_unbindings=0,
                            ir_val=None)
    RefInt_Double = TypedValue(typ=UnionType.from_types(
        [RefInt.type, SLEEPY_DOUBLE]),
                               num_unbindings=0,
                               ir_val=None)
    assert_equal(RefInt.copy_collapse(context=None, name='a'), Int)
    assert_equal(Int.copy_collapse(context=None, name='a'), Int)
    assert_equal(RefInt_Int.copy_collapse(context=None, name='a'), Int)
    assert_equal(Int_RefInt.copy_collapse(context=None, name='a'), Int)
Пример #7
0
def test_narrow_with_collapsed_type():
    from sleepy.builtin_symbols import SLEEPY_INT, SLEEPY_DOUBLE
    Int = SLEEPY_INT
    RefInt = ReferenceType(Int)
    RefRefInt = ReferenceType(RefInt)
    Int_RefInt = UnionType.from_types([Int, RefInt])
    Double = SLEEPY_DOUBLE
    RefDouble = ReferenceType(Double)
    Int_Double = UnionType.from_types([Int, Double])
    RefDouble_RefInt = UnionType.from_types([RefDouble, RefInt])
    assert_equal(narrow_with_collapsed_type(Int, Int), Int)
    assert_equal(narrow_with_collapsed_type(RefInt, Int), RefInt)
    assert_equal(narrow_with_collapsed_type(RefRefInt, Int), RefRefInt)
    assert_equal(narrow_with_collapsed_type(Int_RefInt, Int), Int_RefInt)
    assert_equal(narrow_with_collapsed_type(RefInt, RefInt), RefInt)
    assert_equal(narrow_with_collapsed_type(Int, RefInt), SLEEPY_NEVER)
    assert_equal(narrow_with_collapsed_type(Int_RefInt, RefInt),
                 narrow_type(Int_RefInt, RefInt))
    assert_equal(narrow_with_collapsed_type(Int_Double, Int),
                 narrow_type(Int_Double, Int))
    assert_equal(narrow_with_collapsed_type(RefDouble_RefInt, Int),
                 narrow_type(RefDouble_RefInt, RefInt))
    assert_equal(narrow_with_collapsed_type(ReferenceType(Int_Double), Int),
                 ReferenceType(narrow_type(Int_Double, Int)))
    assert_equal(
        narrow_with_collapsed_type(ReferenceType(ReferenceType(Int_Double)),
                                   Int),
        ReferenceType(ReferenceType(narrow_type(Int_Double, Int))))
    assert_equal(
        narrow_with_collapsed_type(ReferenceType(ReferenceType(Int_Double)),
                                   ReferenceType(Int)),
        ReferenceType(ReferenceType(narrow_type(Int_Double, Int))))
Пример #8
0
def test_can_implicit_cast_to():
    from sleepy.types import can_implicit_cast_to, ReferenceType, UnionType, StructType, PlaceholderTemplateType
    from sleepy.builtin_symbols import SLEEPY_INT, SLEEPY_DOUBLE
    context = make_test_context()
    assert_equal(can_implicit_cast_to(SLEEPY_INT, SLEEPY_DOUBLE), False)
    assert_equal(can_implicit_cast_to(SLEEPY_INT, SLEEPY_INT), True)
    assert_equal(
        can_implicit_cast_to(UnionType.from_types([SLEEPY_INT]), SLEEPY_INT),
        True)
    assert_equal(
        can_implicit_cast_to(UnionType.from_types([SLEEPY_INT, SLEEPY_DOUBLE]),
                             SLEEPY_DOUBLE), False)
    assert_equal(
        can_implicit_cast_to(SLEEPY_DOUBLE,
                             UnionType.from_types([SLEEPY_INT,
                                                   SLEEPY_DOUBLE])), True)
    assert_equal(
        can_implicit_cast_to(ReferenceType(SLEEPY_INT),
                             ReferenceType(SLEEPY_DOUBLE)), False)
    assert_equal(
        can_implicit_cast_to(ReferenceType(SLEEPY_INT),
                             ReferenceType(SLEEPY_INT)), True)
    assert_equal(
        can_implicit_cast_to(
            ReferenceType(UnionType.from_types([SLEEPY_INT, SLEEPY_DOUBLE])),
            ReferenceType(SLEEPY_INT)), False)
    assert_equal(
        can_implicit_cast_to(
            ReferenceType(SLEEPY_INT),
            ReferenceType(UnionType.from_types([SLEEPY_INT, SLEEPY_DOUBLE]))),
        False)
    T = PlaceholderTemplateType('T')
    List = StructType(identity=StructIdentity('List', context=context),
                      template_param_or_arg=[T],
                      member_identifiers=[],
                      member_types=[])
    assert_equal(
        can_implicit_cast_to(
            ReferenceType(SLEEPY_INT),
            ReferenceType(UnionType.from_types([SLEEPY_INT, SLEEPY_DOUBLE]))),
        False)
    assert_equal(
        can_implicit_cast_to(
            ReferenceType(UnionType.from_types([SLEEPY_INT, SLEEPY_DOUBLE])),
            ReferenceType(SLEEPY_INT)), False)
    assert_equal(
        can_implicit_cast_to(
            ReferenceType(UnionType.from_types([SLEEPY_INT, SLEEPY_DOUBLE])),
            UnionType.from_types(
                [ReferenceType(SLEEPY_INT),
                 ReferenceType(SLEEPY_DOUBLE)])), False)
    assert_equal(
        can_implicit_cast_to(
            List.replace_types(
                {T: UnionType.from_types([SLEEPY_INT, SLEEPY_DOUBLE])}),
            List.replace_types({T: SLEEPY_INT})), False)
    assert_equal(
        can_implicit_cast_to(
            List.replace_types({T: SLEEPY_INT}),
            List.replace_types(
                {T: UnionType.from_types([SLEEPY_INT, SLEEPY_DOUBLE])})),
        False)
Пример #9
0
def _make_ptr_symbol(symbol_table: SymbolTable,
                     context: CodegenContext) -> TypeTemplateSymbol:
    pointee_type = PlaceholderTemplateType(identifier='T')
    ptr_type = PointerType(pointee_type=pointee_type)

    assert 'load' not in symbol_table
    load_signature = BuiltinOperationFunctionSignature(
        identifier='load',
        placeholder_template_types=[pointee_type],
        return_type=ReferenceType(pointee_type),
        arg_identifiers=['ptr'],
        arg_types=[ptr_type],
        arg_type_narrowings=[ptr_type],
        instruction=lambda builder, ptr: ptr)
    symbol_table.add_overload('load', load_signature)

    assert 'store' not in symbol_table
    store_signature = BuiltinOperationFunctionSignature(
        identifier='store',
        placeholder_template_types=[pointee_type],
        return_type=SLEEPY_UNIT,
        arg_identifiers=['ptr', 'value'],
        arg_types=[ptr_type, pointee_type],
        arg_type_narrowings=[ptr_type, pointee_type],
        instruction=lambda builder, ptr, value: builder.store(value=value,
                                                              ptr=ptr))
    symbol_table.add_overload('store', store_signature)

    # cast from RawPtr -> Ptr[T] and Ref[T] -> Ptr[T]
    constructor_signature = BitcastFunctionSignature(
        placeholder_template_types=[pointee_type],
        return_type=ptr_type,
        arg_identifiers=['raw_ptr'],
        arg_types=[SLEEPY_RAW_PTR],
        arg_type_narrowings=[ptr_type])
    ref_cast_signature = BuiltinOperationFunctionSignature(
        identifier='Ptr',
        placeholder_template_types=[pointee_type],
        return_type=ptr_type,
        arg_identifiers=['reference'],
        arg_types=[ReferenceType(pointee_type)],
        arg_type_narrowings=[ReferenceType(pointee_type)],
        instruction=lambda builder, ptr: ptr)
    ptr_type.constructor = OverloadSet(
        'Ptr', [constructor_signature, ref_cast_signature])

    ptr_op_decls = [
        (BuiltinBinaryOps.Addition,
         [(lambda builder, lhs, rhs: builder.gep(lhs, (rhs, )), [ptr_type, i
                                                                 ], ptr_type)
          for i in INT_TYPES] +
         [(lambda builder, lhs, rhs: builder.gep(rhs, (lhs, )), [i, ptr_type
                                                                 ], ptr_type)
          for i in INT_TYPES]),
        (BuiltinBinaryOps.Subtraction, [(lambda builder, lhs, rhs: builder.gep(
            lhs,
            (builder.mul(ir.Constant(i.ir_type, -1), rhs), )), [ptr_type,
                                                                i], ptr_type)
                                        for i in INT_TYPES])
    ]
    ptr_op_decls += [(op, [
        (lambda builder, lhs, rhs, op=op: builder.icmp_unsigned(
            op.value, lhs, rhs), [ptr_type, ptr_type], SLEEPY_BOOL)
    ]) for op in Simple_Comparison_Ops]
    for operator, overloads in ptr_op_decls:
        for instruction, arg_types, return_type in overloads:
            signature = _make_func_signature(
                identifier=operator.value,
                instruction=instruction,
                op_placeholder_templ_types=[pointee_type],
                op_arg_types=arg_types,
                op_return_type=return_type)
            symbol_table.add_overload(operator.value, signature)

    free_signature = BuiltinOperationFunctionSignature(
        identifier='free',
        placeholder_template_types=[pointee_type],
        return_type=SLEEPY_UNIT,
        arg_identifiers=['ptr'],
        arg_types=[ptr_type],
        arg_type_narrowings=[SLEEPY_NEVER],
        instruction=lambda builder, value: SLEEPY_UNIT.unit_constant())
    symbol_table.add_overload('free', free_signature)
    return TypeTemplateSymbol(template_parameters=[pointee_type],
                              signature_type=ptr_type)