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
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)
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)))
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)])
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
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)
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))))
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)
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)