def visitDictionaryType(self, ctx): key_type, value_type = ctx.expression() key_type = self.visit(key_type) value_type = self.visit(value_type) return composite_type([ object_template_op({ "type": literal_op("get-wildcard"), "params": list_template_op([key_type, value_type, literal_op(True)]) }), object_template_op({ "type": literal_op("set-wildcard"), "params": list_template_op([ key_type, value_type, literal_op(False), literal_op(False), ]) }), object_template_op({ "type": literal_op("delete-wildcard"), "params": list_template_op([key_type, literal_op(True)]) }), ])
def test_return_rev_const_and_inferred(self): _, result = bootstrap_function(function_lit( no_value_type(), comma_op( return_op( object_template_op( {"foo": object_template_op({"bar": literal_op(42)})})))), check_safe_exit=True) self.assertEquals(result.caught_break_mode, "return") self.assertTrue(isinstance(result.value, Universal)) get_manager( result.value).add_composite_type(DEFAULT_READONLY_COMPOSITE_TYPE) self.assertEquals(result.value._get("foo")._get("bar"), 42)
def visitFunction(self, ctx): argument_destructuring = ctx.argumentDestructurings() code_block = self.visit(ctx.codeBlock()) if argument_destructuring: argument_destructuring = self.visit(argument_destructuring) function_builder = argument_destructuring.chain( code_block, get_debug_info(ctx)) elif ctx.raw_argument: function_builder = CodeBlockBuilder( argument_type_expression=self.visit(ctx.raw_argument)).chain( code_block, get_debug_info(ctx)) else: function_builder = code_block if ctx.return_type: return_type = self.visit(ctx.return_type) function_builder.set_breaks_types({ "value": list_template_op([object_template_op({"out": return_type})]) }) function_name = None function_name_symbol = ctx.SYMBOL() if function_name_symbol: function_name = function_name_symbol.getText() return function_name, function_builder.create("first-class-function", get_debug_info(ctx))
def type_conditional_converter(expression): is_conditional = expression.opcode == "conditional" if not is_conditional: return expression condition_is_type_check = expression.condition.opcode == "is" if not condition_is_type_check: return expression lvalue_of_condition_is_dereference = expression.condition.expression.opcode == "unbound_dereference" if not lvalue_of_condition_is_dereference: return expression shadow_name = expression.condition.expression.reference new_match = match_op(expression.condition.expression, [ prepared_function( expression.condition.type, invoke_op(prepared_function( object_type({shadow_name: expression.condition.type}), expression.when_true), argument_expression=object_template_op( {shadow_name: dereference("argument")}))), prepared_function(inferred_type(), expression.when_false) ]) get_manager(new_match).add_composite_type(DEFAULT_READONLY_COMPOSITE_TYPE) return new_match
def test_return_with_dereference4(self): _, result = bootstrap_function(function_lit( int_type(), build_break_types( object_type({ "foo": any_type(), "bar": any_type() })), comma_op( return_op( object_template_op({ "foo": literal_op(42), "bar": dereference_op(context_op(), literal_op("argument"), True) })))), argument=42, check_safe_exit=True) self.assertEquals(result.caught_break_mode, "return") self.assertTrue(isinstance(result.value, Universal)) get_manager( result.value).add_composite_type(DEFAULT_READONLY_COMPOSITE_TYPE) self.assertEquals(result.value._get("foo"), 42) self.assertEquals(result.value._get("bar"), 42)
def visitForGeneratorLoop(self, ctx): iterator_name = ctx.SYMBOL().getText() generator_expression = self.visit(ctx.expression()) loop_code = self.visit(ctx.codeBlock()) loop_code = CodeBlockBuilder(argument_type_expression=object_type( {iterator_name: inferred_type()})).chain(loop_code, get_debug_info(ctx)) loop_code = loop_code.create("second-class-function", get_debug_info(ctx)) # get_manager(loop_code).add_composite_type(READONLY_DEFAULT_OBJECT_TYPE) return transform_op( "break", "value", invoke_op( local_function( object_template_op({"callback": generator_expression}), loop_op( invoke_op( local_function( transform( ("yield", "value"), ("value", "end"), reset_op( dereference("outer.local.callback", **get_debug_info(ctx)), nop(), **get_debug_info(ctx)), **get_debug_info(ctx)), comma_op( assignment_op( dereference("outer.local"), literal_op("callback"), dereference("local.continuation"), **get_debug_info(ctx)), invoke_op( prepare_function_lit(loop_code), object_template_op( { iterator_name: dereference("local.value") }, **get_debug_info(ctx)), **get_debug_info(ctx))), **get_debug_info(ctx)), **get_debug_info(ctx)), **get_debug_info(ctx)), **get_debug_info(ctx))))
def visitFunctionType(self, ctx): argument_type, return_type = ctx.expression() argument_type = self.visit(argument_type) return_type = self.visit(return_type) argument_type = list_type([argument_type], None) return function_type(argument_type, { "value": list_template_op([object_template_op({"out": return_type})]) })
def test_unbound_reference_to_locals_and_arguments(self): _, result = bootstrap_function(function_lit( object_type({"foo": int_type()}), infer_all(), object_type({"bar": int_type()}), object_template_op({"bar": literal_op(3)}), return_op( addition_op(unbound_dereference("foo"), unbound_dereference("bar")))), argument=PythonObject({"foo": 39})) self.assertEquals(result.caught_break_mode, "return") self.assertEquals(result.value, 42)
def visitToListDestructuring(self, ctx): lvalues = [ self.visit(l) for l in ctx.assignmentOrInitializationLvalue() ] rvalue = self.visit(ctx.expression()) code_block = ctx.codeBlock() if code_block: code_block = self.visit(code_block) assignments = [(i, n) for i, n in enumerate(lvalues) if isinstance(n, basestring)] initializers = [(i, n) for i, n in enumerate(lvalues) if isinstance(n, tuple)] local_variable_types = {} local_variable_initializers = {} for index, (type, name) in initializers: local_variable_types[name] = type local_variable_initializers[name] = dereference( "outer.local._temp", index) code_block = CodeBlockBuilder( local_variable_type=object_type(local_variable_types), local_initializer=object_template_op( local_variable_initializers)).chain(code_block, get_debug_info(ctx)) code_block = CodeBlockBuilder( local_variable_type=object_type( {"_temp": list_type([inferred_type()] * len(lvalues), None)}), local_initializer=object_template_op({"_temp": rvalue}), code_expressions=[ unbound_assignment(name, dereference("local._temp", index)) for index, name in assignments ]).chain(code_block, get_debug_info(ctx)) return code_block
def test_silly_tostring_casing(self): func = function_lit( any_type(), try_catch_op( return_op( match_op(dereference("argument"), [ prepared_function(unit_type(1), literal_op("one")), prepared_function(unit_type(2), literal_op("two")), prepared_function( int_type(), throw_op( object_template_op( {"type": literal_op("UnknownInt")}))), prepared_function( any_type(), throw_op( object_template_op( {"type": literal_op("TypeError")}))) ])), prepared_function( object_type({"type": unit_type("UnknownInt")}), return_op(literal_op("unknown"))))) _, result = bootstrap_function(func, argument=1, check_safe_exit=False) self.assertEquals(result.caught_break_mode, "return") self.assertEquals(result.value, "one") _, result = bootstrap_function(func, argument=2, check_safe_exit=False) self.assertEquals(result.caught_break_mode, "return") self.assertEquals(result.value, "two") _, result = bootstrap_function(func, argument=3, check_safe_exit=False) self.assertEquals(result.caught_break_mode, "return") self.assertEquals(result.value, "unknown") _, result = bootstrap_function(func, argument="hello", check_safe_exit=False) self.assertEquals(result.caught_break_mode, "exception") self.assertIsInstance(result.value, Universal) self.assertEquals(result.value._get("type"), "TypeError")
def visitTupleType(self, ctx): micro_ops = [] expressions = [self.visit(e) for e in ctx.expression()] inferred_splat_type = None if ctx.splat(): inferred_splat_type = expressions.pop() for index, expression in enumerate(expressions): micro_ops.append( object_template_op({ "type": literal_op("get"), "index": literal_op(index), "params": list_template_op([literal_op(index), expression]) })) micro_ops.append( object_template_op({ "type": literal_op("set"), "index": literal_op(index), "params": list_template_op([literal_op(index), any_type()]) })) if inferred_splat_type: micro_ops.append( object_template_op({ "type": literal_op("infer-remainder"), "params": list_template_op([]) })) return composite_type(micro_ops)
def visitArgumentDestructurings(self, ctx): initializers = [self.visit(l) for l in ctx.argumentDestructuring()] argument_types = [None] * len(initializers) local_variable_types = {} local_variable_initializers = {} for index, (type, name) in enumerate(initializers): argument_types[index] = type local_variable_types[name] = type local_variable_initializers[name] = dereference("argument", index) return CodeBlockBuilder( argument_type_expression=list_type(argument_types, None), local_variable_type=object_type(local_variable_types), local_initializer=object_template_op(local_variable_initializers))
def test_misc1(self): _, result = bootstrap_function( function_lit( no_value_type(), infer_all(), object_type({ "foo": int_type(), "bar": int_type() }), object_template_op({ "foo": literal_op(39), "bar": literal_op(3) }), return_op( addition_op(dereference("local.foo"), dereference("local.bar"))))) self.assertEquals(result.caught_break_mode, "return") self.assertEquals(result.value, 42)
def visitLocalVariableDeclaration(self, ctx): type = self.visit(ctx.expression()) remaining_code = ctx.codeBlock() if remaining_code: remaining_code = self.visit(remaining_code) for symbol_initialization in reversed(ctx.symbolInitialization()): name, initial_value = self.visit(symbol_initialization) new_code_block = CodeBlockBuilder( local_variable_type=object_type({name: type}), local_initializer=object_template_op({name: initial_value})) if remaining_code: new_code_block = new_code_block.chain(remaining_code, get_debug_info(ctx)) remaining_code = new_code_block return new_code_block
def test_return_with_dereference5(self): with self.assertRaises(Exception): bootstrap_function(function_lit( int_type(), build_break_types( object_type({ "foo": any_type(), "bar": unit_type(42) })), return_op( object_template_op({ "foo": literal_op(42), "bar": dereference_op(context_op(), literal_op("argument"), True) }))), argument=42, check_safe_exit=True)
def visitForListLoop(self, ctx): iterator_name = ctx.SYMBOL().getText() composite_expression = self.visit(ctx.expression()) loop_code = self.visit(ctx.codeBlock()) loop_code = CodeBlockBuilder(argument_type_expression=object_type( {iterator_name: inferred_type()})).chain(loop_code, get_debug_info(ctx)) loop_code = loop_code.create("second-class-function", get_debug_info(ctx)) return map_op( composite_expression, prepared_function( inferred_type(), invoke_op( prepare_function_lit(loop_code, **get_debug_info(ctx)), object_template_op( { iterator_name: dereference("argument", **get_debug_info(ctx)) }, **get_debug_info(ctx)), **get_debug_info(ctx)), **get_debug_info(ctx)))
def get_default_global_context(): return PythonObject( { "static": PythonObject( { "any": PythonObject({"type": "Any"}, debug_reason="default-global-context"), "int": PythonObject({"type": "Integer"}, debug_reason="default-global-context"), "bool": PythonObject({"type": "Boolean"}, debug_reason="default-global-context"), "string": PythonObject({"type": "String"}, debug_reason="default-global-context"), "void": PythonObject({"type": "NoValue"}, debug_reason="default-global-context"), "var": PythonObject({"type": "Inferred"}, debug_reason="default-global-context"), "range": prepare( function_lit( list_type([int_type(), int_type()], None), infer_all(), int_type(), dereference("argument.0"), prepared_function( loop_op( condition_op( binary_integer_op( "lt", dereference("outer.local"), dereference("outer.argument.1")), comma_op( shift_op( dereference("outer.local"), no_value_type()), assignment_op( dereference("outer"), literal_op("local"), addition_op( dereference("outer.local"), literal_op(1)))), transform_op("break"))))), NO_VALUE, FrameManager()).close(NO_VALUE), "list": prepare( function_lit( list_type([ function_type( no_value_type(), { "yield": list_template_op([ object_template_op( { "in": no_value_type(), "out": int_type() }) ]), "value": list_template_op([ object_template_op( {"out": no_value_type()}) ]), }), ], None), infer_all(), inferred_type(), dereference("argument.0"), loop_op( invoke_op( local_function( transform( ("yield", "value"), ("value", "end"), reset_op( dereference("outer.local"), nop())), comma_op( assignment_op( dereference("outer"), literal_op("local"), dereference( "local.continuation")), transform_op( "value", "continue", dereference("local.value")))))) ), NO_VALUE, FrameManager()).close(NO_VALUE), "max": prepare( function_lit( list_type([int_type()], int_type()), infer_all(), inferred_type(), dereference("argument.0"), comma_op( map_op( dereference("argument"), prepared_function( int_type(), condition_op( binary_integer_op( "gt", dereference("argument"), dereference("outer.local")), assignment_op( dereference("outer"), literal_op("local"), dereference("argument")), nop()))), dereference("local"))), NO_VALUE, FrameManager()).close(NO_VALUE), }, debug_reason="default-global-context") }, bind=DEFAULT_READONLY_COMPOSITE_TYPE, debug_reason="default-global-context")
def visitObjectTemplate(self, ctx): result = {} for pair in ctx.objectPropertyPair(): key, value = self.visit(pair) result[key] = value return object_template_op(result)
def create(self, output_mode, debug_info): if output_mode not in ("first-class-function", "second-class-function", "expression"): raise FatalError() code_expressions = default(self.code_expressions, MISSING, []) for c in code_expressions: if not is_opcode(c): raise FatalError() if not self.requires_function() and output_mode == "expression": return combine_opcodes(code_expressions) if self.argument_type_expression is not MISSING: argument_type = self.argument_type_expression else: argument_type = no_value_type() if self.local_variable_type is not MISSING: local_type = self.local_variable_type else: local_type = object_type( {}) # For future python local variables... if self.local_initializer is not MISSING: local_initializer = self.local_initializer else: local_initializer = object_template_op({}) if self.breaks_types is not MISSING: break_types = self.breaks_types else: break_types = infer_all() if self.extra_statics is not MISSING: extra_statics = self.extra_statics else: extra_statics = {} if output_mode == "first-class-function": # A function created by the user, which mangles returns as expected code = transform_op("return", "value", combine_opcodes(code_expressions), **debug_info) return function_lit(extra_statics, argument_type, break_types, local_type, local_initializer, code, **debug_info) if output_mode == "second-class-function": # A function created by the environment, which leaves returns unmangled code = combine_opcodes(code_expressions) return function_lit(extra_statics, argument_type, break_types, local_type, local_initializer, code, **debug_info) elif output_mode == "expression": return invoke_op( prepare_function_lit( function_lit(extra_statics, argument_type, break_types, local_type, local_initializer, combine_opcodes(code_expressions), **debug_info), **debug_info), **debug_info)