def test_narrow_type_templates(): from sleepy.types import narrow_type, UnionType, PlaceholderTemplateType, StructType from sleepy.builtin_symbols import SLEEPY_INT, SLEEPY_BOOL context = make_test_context() Int, Bool = SLEEPY_INT, SLEEPY_BOOL T = PlaceholderTemplateType('T') List = StructType(identity=StructIdentity('List', context=context), template_param_or_arg=[T], member_identifiers=[], member_types=[]) # narrow(0:List[Int]|1:List[Bool], List[Int]) = 0:List[Int] assert_equal( narrow_type( UnionType.from_types( [List.replace_types({T: Int}), List.replace_types({T: Bool})]), List.replace_types({T: Int})), UnionType.from_types([List.replace_types({T: Int})])) # narrow(List[Int|Bool], List[Int]) = List[Int|Bool] assert_equal( narrow_type(List.replace_types({T: UnionType.from_types([Int, Bool])}), List.replace_types({T: Int})), List.replace_types({T: UnionType.from_types([Int, Bool])})) # narrow(List[Int|Bool]|List[Int], List[Int]) = List[Int|Bool]|List[Int] assert_equal( narrow_type( UnionType.from_types([ List.replace_types({T: UnionType.from_types([Int, Bool])}), List.replace_types({T: Int}) ]), List.replace_types({T: Int})), UnionType.from_types([ List.replace_types({T: UnionType.from_types([Int, Bool])}), List.replace_types({T: 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_narrow_type_references(): from sleepy.types import narrow_type, UnionType, ReferenceType from sleepy.builtin_symbols import SLEEPY_INT, SLEEPY_BOOL Int, Bool = SLEEPY_INT, SLEEPY_BOOL Ref = ReferenceType # narrow(Ref[A], Ref[A]) = Ref[A] assert_equal(narrow_type(Ref(Int), Ref(Int)), Ref(Int)) # narrow(Ref[0:A|1:B], Ref[A]) = Ref[0:A] assert_equal(narrow_type(Ref(UnionType({ Int: 0, Bool: 1 }, 4)), Ref(Int)), Ref(UnionType.from_types([Int]))) # narrow(0:Ref[0:A|1:B]|1:Ref[A], Ref[B]) = 0:Ref[1:B] assert_equal( narrow_type( UnionType.from_types( [Ref(UnionType({ Int: 0, Bool: 1 }, 4)), Ref(Int)]), Ref(Bool)), UnionType({Ref(UnionType({Bool: 1}, 4)): 0}, 8)) # narrow(Ref[0:A|1:B], Ref[A]|Ref[B]) = Ref[0:A|1:B] assert_equal( narrow_type(Ref(UnionType({ Int: 0, Bool: 1 }, 8)), UnionType({ Ref(Int): 0, Ref(Bool): 1 }, 8)), Ref(UnionType({ Int: 0, Bool: 1 }, 8))) # narrow(Ref[A]|Ref[B], Ref[A|B]) = Ref[A]|Ref[B] assert_equal( narrow_type(UnionType.from_types([Ref(Int), Ref(Bool)]), Ref(UnionType.from_types([Int, Bool]))), UnionType.from_types([Ref(Int), Ref(Bool)])) # narrow(Ref[0:A|1:B]|Ref[A], Ref[A]) = Ref[0:A]|Ref[A] assert_equal( narrow_type( UnionType.from_types( [Ref(UnionType.from_types([Int, Bool])), Ref(Int)]), Ref(Int)), UnionType.from_types([Ref(UnionType.from_types([Int])), Ref(Int)])) # narrow(Ref[0:A], Ref[0:A|1:B]) = Ref[0:A] assert_equal( narrow_type(Ref(UnionType.from_types([Int])), Ref(UnionType.from_types([Int, Bool]))), Ref(UnionType.from_types([Int])))
def test_narrow_type(): from sleepy.types import narrow_type, UnionType from sleepy.builtin_symbols import SLEEPY_INT, SLEEPY_BOOL assert_equal(narrow_type(SLEEPY_INT, SLEEPY_INT), SLEEPY_INT) assert_equal(narrow_type(UnionType.from_types([SLEEPY_INT]), SLEEPY_INT), UnionType.from_types([SLEEPY_INT])) assert_equal(narrow_type(SLEEPY_INT, UnionType.from_types([SLEEPY_INT])), SLEEPY_INT) assert_equal( narrow_type(UnionType.from_types([SLEEPY_INT, SLEEPY_BOOL]), UnionType.from_types([SLEEPY_INT])), UnionType.from_types([SLEEPY_INT])) assert_equal( narrow_type(UnionType.from_types([SLEEPY_INT, SLEEPY_BOOL]), SLEEPY_BOOL), UnionType({SLEEPY_BOOL: 1}, val_size=4)) assert_equal( narrow_type(UnionType.from_types([SLEEPY_INT, SLEEPY_BOOL]), UnionType.from_types([SLEEPY_BOOL])), UnionType({SLEEPY_BOOL: 1}, val_size=4)) assert_equal(narrow_type(SLEEPY_INT, SLEEPY_BOOL), SLEEPY_NEVER)
def copy_narrow_type(self, narrow_to: Type) -> VariableSymbol: return self.copy_set_narrowed_type( new_narrow_type=narrow_type(self.narrowed_var_type, narrow_to))
def copy_set_narrowed_type(self, new_narrow_type: Type) -> VariableSymbol: new_var_symbol = VariableSymbol(self.ir_alloca, self.declared_var_type) # explicitly apply narrowing from declared type here: always stay compatible to the base type new_var_symbol.narrowed_var_type = narrow_type( from_type=self.declared_var_type, narrow_to=new_narrow_type) return new_var_symbol