def test_rev_const_merge_types_in_list(self): rev_const_type = CompositeType({ ("get", 0): GetterMicroOpType(0, StringType()), ("set", 0): SetterMicroOpType(0, StringType()), ("get", 1): GetterMicroOpType(1, IntegerType()), ("set", 1): SetterMicroOpType(1, IntegerType()), ("get", 2): GetterMicroOpType(2, AnyType()), ("set", 2): SetterMicroOpType(2, AnyType()), ("insert-start", ): InsertStartMicroOpType(StringType(), False) }, name="test") normal_broad_type = CompositeType({ ("get", 0): GetterMicroOpType(0, StringType()), ("set", 0): SetterMicroOpType(0, StringType()), ("get", 1): GetterMicroOpType(1, IntegerType()), ("set", 1): SetterMicroOpType(1, IntegerType()), ("get", 2): GetterMicroOpType(2, AnyType()), ("set", 2): SetterMicroOpType(2, AnyType()), }, name="test") self.assertFalse(rev_const_type.is_self_consistent(DUMMY_REASONER)) rev_const_type = prepare_lhs_type(rev_const_type, None) self.assertTrue(rev_const_type.is_self_consistent(DUMMY_REASONER)) self.assertTrue(normal_broad_type.is_copyable_from(rev_const_type, DUMMY_REASONER))
def test_composite_object_broad_dereference(self): obj = PythonObject({ "foo": "hello" }) get_manager(obj).add_composite_type(CompositeType({ ("get", "foo"): GetterMicroOpType("foo", AnyType()), ("set", "foo"): SetterMicroOpType("foo", AnyType()) }, name="test")) self.assertEquals(obj.foo, "hello")
def test_rev_const_assigned_to_broad_type(self): rev_const_type = CompositeType({ ("get", "foo"): GetterMicroOpType("foo", StringType()), ("set", "foo"): SetterMicroOpType("foo", AnyType()), }, name="test") normal_broad_type = CompositeType({ ("get", "foo"): GetterMicroOpType("foo", AnyType()), ("set", "foo"): SetterMicroOpType("foo", AnyType()) }, name="test") self.assertTrue(normal_broad_type.is_copyable_from(rev_const_type, DUMMY_REASONER))
def test_outside_tuple_access_allowed(self): foo = PythonList([ 4, 6, 8 ]) get_manager(foo).add_composite_type(UniversalListType(AnyType())) self.assertEqual(foo[2], 8) foo[2] = "hello" self.assertEqual(foo[2], "hello")
def test_failed_setup_broad_writing_property(self): with self.assertRaises(CompositeTypeIsInconsistent): obj = PythonObject({ "foo": "hello" }) get_manager(obj).add_composite_type(CompositeType({ ("get", "foo"): GetterMicroOpType("foo", StringType()), ("set", "foo"): SetterMicroOpType("foo", AnyType()) }, name="test"))
def test_outside_tuple_access_blocked(self): foo = PythonList([ 4, 6, 8 ]) get_manager(foo).add_composite_type(UniversalTupleType([ IntegerType(), AnyType() ])) with self.assertRaises(IndexError): foo[2] with self.assertRaises(IndexError): foo[2] = "hello"
def __init__(self, data, code, prepare_context, static, argument_type, outer_type, local_type, local_initializer, break_types): self.data = data self.code = code self.prepare_context = prepare_context self.static = static self.argument_type = argument_type self.outer_type = outer_type self.local_type = local_type self.local_initializer = local_initializer self.break_types = break_types self.types_context = Universal( True, initial_wrapped={ "outer": self.outer_type, "argument": self.argument_type }, debug_reason="local-initialization-context") self.local_initialization_context_type = UniversalObjectType( { "outer": self.outer_type, "argument": self.argument_type, # "types": readonly_rich_composite_type }, wildcard_type=AnyType(), name="local-initialization-context-type") self.execution_context_type = UniversalObjectType( { # "prepare": readonly_rich_composite_type, "outer": self.outer_type, "argument": self.argument_type, # "static": readonly_rich_composite_type, "local": self.local_type, # "types": readonly_rich_composite_type }, wildcard_type=AnyType(), name="code-execution-context-type") if not self.execution_context_type.is_self_consistent(DUMMY_REASONER): raise FatalError() self.compiled_ast = None
def test_rev_const_can_not_be_added_to_object(self): rev_const_type = CompositeType({ ("get", "foo"): GetterMicroOpType("foo", StringType()), ("set", "foo"): SetterMicroOpType("foo", AnyType()) }, name="test") obj = PythonObject({ "foo": "hello" }) with self.assertRaises(Exception): get_manager(obj).add_composite_type(rev_const_type)
def test_broad_type_assignments_blocked(self): T = UniversalObjectType({ "foo": AnyType() }) S = UniversalObjectType({ "foo": IntegerType() }) self.assertFalse(T.is_copyable_from(S, DUMMY_REASONER)) self.assertFalse(S.is_copyable_from(T, DUMMY_REASONER))
def test_const_allows_broader_types(self): T = UniversalObjectType({ "foo": Const(AnyType()) }) S = UniversalObjectType({ "foo": IntegerType() }) self.assertTrue(T.is_copyable_from(S, DUMMY_REASONER)) self.assertFalse(S.is_copyable_from(T, DUMMY_REASONER))
def test_mixed_type_tuple(self): foo = PythonList([ 4, 6, 8 ]) get_manager(foo).add_composite_type(UniversalTupleType([ IntegerType(), AnyType() ])) with self.assertRaises(TypeError): foo[0] = "hello" self.assertEqual(foo[0], 4) foo[1] = "what" self.assertEqual(foo[1], "what")
def test_very_broad_assignment(self): foo = PythonObject({ "bar": PythonObject({ "baz": 42 }) }) get_manager(foo).add_composite_type( UniversalObjectType({ "bar": AnyType() }) ) foo.bar = "hello" self.assertEquals(foo.bar, "hello")
def test_rev_const_flatten_tuple(self): rev_const_type = CompositeType({ ("get", 0): GetterMicroOpType(0, StringType()), ("set", 0): SetterMicroOpType(0, AnyType()) }, name="test") normal_broad_type = CompositeType({ ("get", 0): GetterMicroOpType(0, StringType()), ("set", 0): SetterMicroOpType(0, StringType()) }, name="test") rev_const_type = prepare_lhs_type(rev_const_type, None) self.assertTrue(isinstance(rev_const_type.get_micro_op_type(("set", 0)).value_type, StringType)) self.assertTrue(normal_broad_type.is_copyable_from(rev_const_type, DUMMY_REASONER))
def test_rev_const_wildcard(self): rev_const_type = CompositeType({ ("get-wildcard", ): GetterWildcardMicroOpType(StringType(), StringType(), True), ("set-wildcard", ): SetterWildcardMicroOpType(StringType(), AnyType(), False, False) }, name="test") normal_broad_type = CompositeType({ ("get", "foo"): GetterWildcardMicroOpType(StringType(), StringType(), True), ("set", "foo"): SetterWildcardMicroOpType(StringType(), StringType(), False, False) }, name="test") rev_const_type = prepare_lhs_type(rev_const_type, None) self.assertTrue(isinstance(rev_const_type.get_micro_op_type(("set-wildcard",)).value_type, StringType)) self.assertTrue(normal_broad_type.is_copyable_from(rev_const_type, DUMMY_REASONER))
def test_broad_assignment(self): foo = PythonObject({ "bar": PythonObject({ "baz": 42 }) }) Bar = UniversalObjectType({ "baz": AnyType() }) get_manager(foo).add_composite_type( UniversalObjectType({ "bar": Bar }) ) foo.bar = PythonObject({ "baz": "hello" }, bind=Bar) self.assertEquals(foo.bar.baz, "hello")
def test_conflicting_types(self): foo = PythonObject({ "bar": PythonObject({ "baz": 42 }) }) get_manager(foo).add_composite_type( UniversalObjectType({ "bar": UniversalObjectType({ "baz": IntegerType() }) }) ) with self.assertRaises(Exception): get_manager(foo).add_composite_type( UniversalObjectType({ "bar": UniversalObjectType({ "baz": AnyType() }) }) )
def test_broadening_tuple_assignment_allowed_with_const(self): foo = UniversalTupleType([ Const(AnyType()), Const(AnyType()) ]) bar = UniversalTupleType([ IntegerType(), IntegerType() ]) self.assertTrue(foo.is_copyable_from(bar, DUMMY_REASONER))
def test_combined_const_list_and_tuple(self): foo = PythonList([ 4, 6, 8 ]) get_manager(foo).add_composite_type(UniversalLupleType([ IntegerType(), AnyType() ], Const(AnyType()))) self.assertEqual(foo[2], 8)
def test_setup_broad_reading_property(self): obj = PythonObject({ "foo": "hello" }) get_manager(obj).add_composite_type(CompositeType({ ("get", "foo"): GetterMicroOpType("foo", AnyType()), ("set", "foo"): SetterMicroOpType("foo", StringType()) }, name="test"))
def test_extreme_type_tamed2_contains_conflicts(self): foo = UniversalLupleType([ IntegerType() ], AnyType()) self.assertTrue(foo.is_self_consistent(DUMMY_REASONER))
def test_narrowing_assignment_blocked(self): foo = UniversalListType(IntegerType()) bar = UniversalListType(Const(AnyType())) self.assertTrue(bar.is_copyable_from(foo, DUMMY_REASONER)) self.assertFalse(foo.is_copyable_from(bar, DUMMY_REASONER))
def test_covariant_array_assignment_blocked(self): foo = UniversalListType(AnyType()) bar = UniversalListType(IntegerType()) self.assertFalse(foo.is_copyable_from(bar, DUMMY_REASONER))
def prepare(data, outer_context, frame_manager, immediate_context=None): if not isinstance(data, Composite): raise FatalError() get_manager(data).add_composite_type(DEFAULT_READONLY_COMPOSITE_TYPE) if not hasattr(data, "code"): raise PreparationException("Code missing from function") actual_break_types_factory = BreakTypesFactory(None) context = Universal(True, initial_wrapped={"prepare": outer_context}, bind=DEFAULT_READONLY_COMPOSITE_TYPE, debug_reason="static-prepare-context") static = evaluate( enrich_opcode( data.static, combine(type_conditional_converter, UnboundDereferenceBinder(context))), context, frame_manager) get_manager(static).add_composite_type(DEFAULT_READONLY_COMPOSITE_TYPE) argument_type = enrich_type(static._get("argument")) outer_type = enrich_type(static._get("outer")) suggested_argument_type = suggested_outer_type = None if immediate_context: suggested_argument_type = immediate_context.get( "suggested_argument_type", None) suggested_outer_type = immediate_context.get("suggested_outer_type", None) if suggested_outer_type is None: suggested_outer_type = NoValueType() try: argument_type = prepare_piece_of_context(argument_type, suggested_argument_type) except DanglingInferredType: raise PreparationException( "Failed to infer argument types in {} from {}".format( argument_type, suggested_argument_type)) try: outer_type = prepare_piece_of_context(outer_type, suggested_outer_type) except DanglingInferredType: raise PreparationException( "Failed to infer outer types in {} from {}".format( argument_type, suggested_argument_type)) local_type = enrich_type(static._get("local")) context = Universal( True, initial_wrapped={ "prepare": outer_context, "static": static, # "types": derich_type( # UniversalObjectType({ # "outer": outer_type, # "argument": argument_type, ## "local": local_type # }), {} # ), "_types": Universal( True, initial_wrapped={ "outer": outer_type, "argument": argument_type, # "local": local_type }, debug_reason="local-prepare-context") }, bind=DEFAULT_READONLY_COMPOSITE_TYPE, debug_reason="local-prepare-context") # optimization to avoid generating context_type lazily get_manager(context)._context_type = UniversalObjectType( { "outer": outer_type, "argument": argument_type, # "local": local_type }, wildcard_type=AnyType(), name="local-prepare-context-type") local_initializer = enrich_opcode( data.local_initializer, combine(type_conditional_converter, UnboundDereferenceBinder(context))) actual_local_type, local_other_break_types = get_expression_break_types( local_initializer, context, frame_manager) get_manager(context).remove_composite_type(DEFAULT_READONLY_COMPOSITE_TYPE) if actual_local_type is MISSING: raise PreparationException( "Actual local type missing. local_other_break_types: {}".format( local_other_break_types)) actual_local_type = flatten_out_types(actual_local_type) local_type = prepare_piece_of_context(local_type, actual_local_type) local_type_reasoner = Reasoner() if not local_type.is_copyable_from(actual_local_type, local_type_reasoner): raise PreparationException("Invalid local type: {} != {}: {}".format( local_type, actual_local_type, local_type_reasoner.to_message())) actual_break_types_factory.merge(local_other_break_types) declared_break_types = PythonDict({ mode: PythonList([ enrich_break_type(break_type) for break_type in break_types._values() ]) for mode, break_types in static._get("break_types")._items() }) get_manager(declared_break_types).add_composite_type( DEFAULT_READONLY_COMPOSITE_TYPE) context = Universal( True, initial_wrapped={ "prepare": outer_context, "static": static, # "types": derich_type( # UniversalObjectType({ # "outer": outer_type, # "argument": argument_type, # "local": local_type # }), {} # ), "_types": Universal(True, initial_wrapped={ "outer": outer_type, "argument": argument_type, "local": local_type }, debug_reason="code-prepare-context") }, bind=DEFAULT_READONLY_COMPOSITE_TYPE, debug_reason="code-prepare-context") get_manager(context)._context_type = UniversalObjectType( { "outer": outer_type, "argument": argument_type, "local": local_type }, wildcard_type=AnyType(), name="code-prepare-context-type") code = enrich_opcode( data.code, combine(type_conditional_converter, UnboundDereferenceBinder(context))) code_break_types = code.get_break_types(context, frame_manager) get_manager(context).remove_composite_type(DEFAULT_READONLY_COMPOSITE_TYPE) actual_break_types_factory.merge(code_break_types) final_declared_break_types = BreakTypesFactory(None) for mode, actual_break_types in actual_break_types_factory.build().items(): for actual_break_type in actual_break_types: declared_break_types_for_mode = declared_break_types.get( mode, declared_break_types.get("wildcard", [])) for declared_break_type_for_mode in declared_break_types_for_mode: # Check if this declared_break_type_for_mode is enough to capture the actual_break_types declared_out = declared_break_type_for_mode["out"] declared_in = declared_break_type_for_mode.get("in", None) actual_out = actual_break_type["out"] actual_in = actual_break_type.get("in", None) final_out = prepare_lhs_type(declared_out, actual_out) if declared_in is not None: if isinstance(declared_in, InferredType) and actual_in is None: final_in = None else: final_in = prepare_lhs_type(declared_in, actual_in) else: final_in = declared_in # if declared_in is not None and actual_in is None: # continue out_is_compatible = final_out.is_copyable_from( actual_out, DUMMY_REASONER) in_is_compatible = final_in is None or actual_in.is_copyable_from( final_in, DUMMY_REASONER) if out_is_compatible and in_is_compatible: final_declared_break_types.add(mode, final_out, final_in) break else: raise PreparationException( """Nothing declared for {}, {}.\nFunction declares break types {}.\nBut local_initialization breaks {}, code breaks {}""" .format(mode, actual_break_type, declared_break_types, local_other_break_types, code_break_types)) return OpenFunction(data, code, outer_context, static, argument_type, outer_type, local_type, local_initializer, final_declared_break_types.build())
def test_narrowing_tuple_assignment_blocked(self): foo = UniversalTupleType([ IntegerType(), IntegerType() ]) bar = UniversalTupleType([ AnyType(), AnyType() ]) self.assertFalse(foo.is_copyable_from(bar, DUMMY_REASONER))
def test_merge_pairwise_parent_and_child_types(self): self.assertTrue(isinstance(merge_types([ AnyType(), IntegerType() ], "super"), AnyType)) self.assertTrue(isinstance(merge_types([ AnyType(), IntegerType() ], "sub"), IntegerType)) self.assertTrue(isinstance(merge_types([ AnyType(), IntegerType() ], "exact"), OneOfType)) self.assertTrue(len(merge_types([ AnyType(), IntegerType() ], "exact").types) == 2)
# "type": "iter", # "params": PythonDict([ derich_type(micro_op.value_type, results) ]) # }) # # def deconstruct_universal_type(type, results): # micro_ops = [] # for key, micro_op_type in type.get_micro_op_types().items(): # micro_ops.append(deconstruct_micro_op(micro_op_type, results)) # # return PythonDict({ # "type": "Universal", # "micro_ops": PythonList(micro_ops) # }) TYPES = { "Any": lambda data: AnyType(), "Object": build_object_type, "List": build_list_type, "Universal": build_universal_type, "Function": build_closed_function_type, "OneOf": build_one_of_type, "Integer": lambda data: IntegerType(), "Boolean": lambda data: BooleanType(), "NoValue": lambda data: NoValueType(), "String": lambda data: StringType(), "Unit": build_unit_type, "Inferred": lambda data: InferredType() } def enrich_type(data):
def test_const_covariant_array_assignment_allowed(self): foo = UniversalListType(Const(AnyType())) bar = UniversalListType(IntegerType()) self.assertTrue(foo.is_copyable_from(bar, DUMMY_REASONER))