X-Git-Url: http://nitlanguage.org?ds=sidebyside diff --git a/src/global_compiler.nit b/src/global_compiler.nit index c6e61b1..5865869 100644 --- a/src/global_compiler.nit +++ b/src/global_compiler.nit @@ -133,9 +133,19 @@ redef class ModelBuilder end self.toolcontext.info("Total methods to compile to C: {compiler.visitors.length}", 2) + var time1 = get_time + self.toolcontext.info("*** END VISITING: {time1-time0} ***", 2) + write_and_make(compiler) + end + + protected fun write_and_make(compiler: GlobalCompiler) + do + var mainmodule = compiler.mainmodule + # Generate the .h and .c files # A single C file regroups many compiled rumtime functions # Note that we do not try to be clever an a small change in a Nit source file may change the content of all the generated .c files + var time0 = get_time var outname = self.toolcontext.opt_output.value if outname == null then @@ -206,7 +216,7 @@ redef class ModelBuilder ofiles.add(o) end # Link edition - makefile.write("{outname}: {ofiles.join(" ")}\n\t$(CC) $(LDFLAGS) $(LDLIBS) -o {outname} {ofiles.join(" ")}\n\n") + makefile.write("{outname}: {ofiles.join(" ")}\n\t$(CC) $(LDFLAGS) -o {outname} {ofiles.join(" ")} $(LDLIBS)\n\n") # Clean makefile.write("clean:\n\trm {ofiles.join(" ")} 2>/dev/null\n\n") makefile.close @@ -239,7 +249,7 @@ redef class ModelBuilder end # Singleton that store the knowledge about the compilation process -private class GlobalCompiler +class GlobalCompiler # The main module of the program var mainmodule: MModule @@ -270,11 +280,11 @@ private class GlobalCompiler var live_primitive_types: Array[MClassType] # runtime_functions that need to be compiled - private var todos: List[RuntimeFunction] = new List[RuntimeFunction] + private var todos: List[AbstractRuntimeFunction] = new List[AbstractRuntimeFunction] # runtime_functions already seen (todo or done) - private var seen: HashSet[RuntimeFunction] = new HashSet[RuntimeFunction] - fun todo(m: RuntimeFunction) + private var seen: HashSet[AbstractRuntimeFunction] = new HashSet[AbstractRuntimeFunction] + fun todo(m: AbstractRuntimeFunction) do if seen.has(m) then return todos.add(m) @@ -285,7 +295,7 @@ private class GlobalCompiler # # FIXME: should not be a vistor but just somewhere to store lines # FIXME: should not have a global .h since it does not help recompilations - var header: nullable GlobalCompilerVisitor = null + var header: nullable GlobalCompilerVisitor writable = null # The list of all associated visitors # Used to generate .c files @@ -307,7 +317,7 @@ private class GlobalCompiler end # Cache for classid (computed by declare_runtimeclass) - private var classids: HashMap[MClassType, String] = new HashMap[MClassType, String] + protected var classids: HashMap[MClassType, String] = new HashMap[MClassType, String] # Declare C structures and identifiers for a runtime class fun declare_runtimeclass(v: GlobalCompilerVisitor, mtype: MClassType) @@ -322,6 +332,11 @@ private class GlobalCompiler v.add_decl("struct {mtype.c_name} \{") v.add_decl("int classid; /* must be {idname} */") + if mtype.mclass.name == "NativeArray" then + # NativeArrays are just a instance header followed by an array of values + v.add_decl("{mtype.arguments.first.ctype} values[1];") + end + if mtype.ctype != "val*" then # Is the Nit type is native then the struct is a box with two fields: # * the `classid` to be polymorph @@ -349,12 +364,26 @@ private class GlobalCompiler assert mtype.ctype == "val*" var v = new GlobalCompilerVisitor(self) - self.header.add_decl("{mtype.ctype} NEW_{mtype.c_name}(void);") + var is_native_array = mtype.mclass.name == "NativeArray" + + var sig + if is_native_array then + sig = "int length" + else + sig = "void" + end + + self.header.add_decl("{mtype.ctype} NEW_{mtype.c_name}({sig});") v.add_decl("/* allocate {mtype} */") - v.add_decl("{mtype.ctype} NEW_{mtype.c_name}(void) \{") + v.add_decl("{mtype.ctype} NEW_{mtype.c_name}({sig}) \{") var res = v.new_var(mtype) res.is_exact = true - v.add("{res} = GC_MALLOC(sizeof(struct {mtype.c_name}));") + if is_native_array then + var mtype_elt = mtype.arguments.first + v.add("{res} = GC_MALLOC(sizeof(struct {mtype.c_name}) + length*sizeof({mtype_elt.ctype}));") + else + v.add("{res} = GC_MALLOC(sizeof(struct {mtype.c_name}));") + end v.add("{res}->classid = {self.classid(mtype)};") for cd in mtype.collect_mclassdefs(self.mainmodule) @@ -506,8 +535,8 @@ redef class MClassType else if mclass.name == "NativeString" then return "char*" else if mclass.name == "NativeArray" then - assert self isa MGenericType - return "{self.arguments.first.ctype}*" + #return "{self.arguments.first.ctype}*" + return "val*" else if mclass.kind == extern_kind then return "void*" else @@ -530,6 +559,17 @@ redef class MGenericType end end +redef class MParameterType + redef fun c_name + do + var res = self.c_name_cache + if res != null then return res + res = "FT{self.rank}" + self.c_name_cache = res + return res + end +end + redef class MNullableType redef fun c_name do @@ -543,12 +583,25 @@ end # A C function associated to a Nit method # Because of customization, a given Nit method can be compiler more that once -private abstract class RuntimeFunction +abstract class AbstractRuntimeFunction # The associated Nit method var mmethoddef: MMethodDef # The mangled c name of the runtime_function - fun c_name: String is abstract + # Subclasses should redefine `build_c_name` instead + fun c_name: String + do + var res = self.c_name_cache + if res != null then return res + res = self.build_c_name + self.c_name_cache = res + return res + end + + # Non cached version of `c_name` + protected fun build_c_name: String is abstract + + private var c_name_cache: nullable String = null # Implements a call of the runtime_function # May inline the body or generate a C function call @@ -561,7 +614,7 @@ end # A runtime function customized on a specific monomrph receiver type private class CustomizedRuntimeFunction - super RuntimeFunction + super AbstractRuntimeFunction # The considered reciever # (usually is a live type but no strong guarantee) @@ -573,8 +626,7 @@ private class CustomizedRuntimeFunction self.recv = recv end - # The mangled c name of the runtime_function - redef fun c_name: String + redef fun build_c_name: String do var res = self.c_name_cache if res != null then return res @@ -587,8 +639,6 @@ private class CustomizedRuntimeFunction return res end - private var c_name_cache: nullable String = null - redef fun ==(o) # used in the compiler worklist do @@ -646,8 +696,8 @@ private class CustomizedRuntimeFunction sig.append("void ") end sig.append(self.c_name) - sig.append("({recv.ctype} self") - comment.append("(self: {recv}") + sig.append("({recv.ctype} {selfvar}") + comment.append("(self: {selfvar}") arguments.add(selfvar) for i in [0..mmethoddef.msignature.arity[ do var mtype = mmethoddef.msignature.mparameters[i].mtype @@ -688,7 +738,7 @@ private class CustomizedRuntimeFunction do var ret = self.mmethoddef.msignature.return_mtype if self.mmethoddef.mproperty.is_new then - ret = arguments.first.mtype + ret = recv end if ret != null then ret = v.resolve_for(ret, arguments.first) @@ -725,7 +775,7 @@ end # Runtime variables are associated to Nit local variables and intermediate results in Nit expressions. # # The tricky point is that a single C variable can be associated to more than one RuntimeVariable because the static knowledge of the type of an expression can vary in the C code. -private class RuntimeVariable +class RuntimeVariable # The name of the variable in the C code var name: String @@ -733,11 +783,11 @@ private class RuntimeVariable var mtype: MType # The current casted type of the variable (as known in Nit) - var mcasttype: MType + var mcasttype: MType writable # If the variable exaclty a mcasttype? # false (usual value) means that the variable is a mcasttype or a subtype. - var is_exact: Bool = false + var is_exact: Bool writable = false init(name: String, mtype: MType, mcasttype: MType) do @@ -770,7 +820,7 @@ end # A visitor on the AST of property definition that generate the C code. # Because of inlining, a visitor can visit more than one property. -private class GlobalCompilerVisitor +class GlobalCompilerVisitor # The associated compiler var compiler: GlobalCompiler @@ -795,11 +845,11 @@ private class GlobalCompilerVisitor # Force to get the primitive property named `name' in the instance `recv' or abort fun get_property(name: String, recv: MType): MMethod do - return self.compiler.mainmodule.force_get_primitive_method(name, recv) + return self.compiler.modelbuilder.force_get_primitive_method(self.current_node.as(not null), name, recv, self.compiler.mainmodule) end # The current Frame - var frame: nullable Frame + var frame: nullable Frame writable # Anchor a type to the main module and the current receiver fun anchor(mtype: MType): MType @@ -826,7 +876,7 @@ private class GlobalCompilerVisitor private var decl_lines: List[String] = new List[String] # The current visited AST node - var current_node: nullable AExpr = null + var current_node: nullable ANode = null # Compile an expression an return its result # `mtype` is the expected return type, pass null if no specific type is expected. @@ -871,7 +921,7 @@ private class GlobalCompilerVisitor if value.mtype.ctype == mtype.ctype then return value else if value.mtype.ctype == "val*" then - return self.new_expr("((struct {mtype.c_name}*){value})->value /* autounbox from {value.mtype} to {mtype} */", mtype) + return self.new_expr("((struct {mtype.c_name}*){value})->value; /* autounbox from {value.mtype} to {mtype} */", mtype) else if mtype.ctype == "val*" then var valtype = value.mtype.as(MClassType) var res = self.new_var(mtype) @@ -938,6 +988,15 @@ private class GlobalCompilerVisitor return res end + # Return a new uninitialized named runtime_variable + fun new_named_var(mtype: MType, name: String): RuntimeVariable + do + mtype = self.anchor(mtype) + var res = new RuntimeVariable(name, mtype, mtype) + self.add_decl("{mtype.ctype} {name} /* : {mtype} */;") + return res + end + # Return a new local runtime_variable initialized with the C expression `cexpr'. fun new_expr(cexpr: String, mtype: MType): RuntimeVariable do @@ -1040,6 +1099,28 @@ private class GlobalCompilerVisitor return res end + fun native_array_def(pname: String, ret_type: nullable MType, arguments: Array[RuntimeVariable]) + do + var elttype = arguments.first.mtype + var recv = "((struct {arguments[0].mcasttype.c_name}*){arguments[0]})->values" + if pname == "[]" then + self.ret(self.new_expr("{recv}[{arguments[1]}]", ret_type.as(not null))) + return + else if pname == "[]=" then + self.add("{recv}[{arguments[1]}]={arguments[2]};") + return + else if pname == "copy_to" then + var recv1 = "((struct {arguments[1].mcasttype.c_name}*){arguments[1]})->values" + self.add("memcpy({recv1},{recv},{arguments[2]}*sizeof({elttype.ctype}));") + return + end + end + + fun calloc_array(ret_type: MType, arguments: Array[RuntimeVariable]) + do + self.ret(self.new_expr("NEW_{ret_type.c_name}({arguments[1]})", ret_type)) + end + # Generate a polymorphic send for the method `m' and the arguments `args' fun send(m: MMethod, args: Array[RuntimeVariable]): nullable RuntimeVariable do @@ -1138,6 +1219,21 @@ private class GlobalCompilerVisitor return res end + # Generate a monomorphic send for the method `m', the type `t' and the arguments `args' + fun monomorphic_send(m: MMethod, t: MType, args: Array[RuntimeVariable]): nullable RuntimeVariable + do + assert t isa MClassType + var propdefs = m.lookup_definitions(self.compiler.mainmodule, t) + if propdefs.length == 0 then + abort + end + if propdefs.length > 1 then + self.debug("NOT YET IMPLEMENTED conflict for {t}.{m}: {propdefs.join(" ")}. choose the first") + end + var propdef = propdefs.first + return self.call(propdef, t, args) + end + fun check_valid_reciever(recvtype: MClassType) do if self.compiler.runtime_type_analysis.live_types.has(recvtype) or recvtype.mclass.name == "Object" then return @@ -1184,7 +1280,11 @@ private class GlobalCompilerVisitor else args = args.to_a end - assert args.length == m.msignature.arity + 1 # because of self + if args.length != m.msignature.arity + 1 then # because of self + add("printf(\"NOT YET IMPLEMENTED: Invalid arity for {m}. {args.length} arguments given.\\n\"); exit(1);") + debug("NOT YET IMPLEMENTED: Invalid arity for {m}. {args.length} arguments given.") + return null + end args.first = recv var rm = new CustomizedRuntimeFunction(m, recvtype) @@ -1210,6 +1310,48 @@ private class GlobalCompilerVisitor self.add("fprintf(stderr, \"BTD BUG: Dynamic type is %s, static type is %s\\n\", class_names[{recv}->classid], \"{recv.mcasttype}\");") end + # Generate a polymorphic attribute is_set test + fun isset_attribute(a: MAttribute, recv: RuntimeVariable): RuntimeVariable + do + var types = self.collect_types(recv) + + var res = self.new_var(bool_type) + + if types.is_empty then + self.add("/*BUG: no live types for {recv.inspect} . {a}*/") + return res + end + self.add("/* isset {a} on {recv.inspect} */") + self.add("switch({recv}->classid) \{") + var last = types.last + for t in types do + if not self.compiler.hardening and t == last then + self.add("default: /*{self.compiler.classid(t)}*/") + else + self.add("case {self.compiler.classid(t)}:") + end + var recv2 = self.autoadapt(recv, t) + var ta = a.intro.static_mtype.as(not null) + ta = self.resolve_for(ta, recv2) + var attr = self.new_expr("((struct {t.c_name}*){recv})->{a.intro.c_name}", ta) + if not ta isa MNullableType then + if ta.ctype == "val*" then + self.add("{res} = ({attr} != NULL);") + else + self.add("{res} = 1; /*NOTYET isset on primitive attributes*/") + end + end + self.add("break;") + end + if self.compiler.hardening then + self.add("default: /* Bug */") + self.bugtype(recv) + end + self.add("\}") + + return res + end + # Generate a polymorphic attribute read fun read_attribute(a: MAttribute, recv: RuntimeVariable): RuntimeVariable do @@ -1333,6 +1475,42 @@ private class GlobalCompilerVisitor return res end + # Generate the code required to dynamically check if 2 objects share the same runtime type + fun is_same_type_test(value1, value2: RuntimeVariable): RuntimeVariable + do + var res = self.new_var(bool_type) + if value2.mtype.ctype == "val*" then + if value1.mtype.ctype == "val*" then + self.add "{res} = {value1}->classid == {value2}->classid;" + else + self.add "{res} = {self.compiler.classid(value1.mtype.as(MClassType))} == {value2}->classid;" + end + else + if value1.mtype.ctype == "val*" then + self.add "{res} = {value1}->classid == {self.compiler.classid(value2.mtype.as(MClassType))};" + else if value1.mcasttype == value2.mcasttype then + self.add "{res} = 1;" + else + self.add "{res} = 0;" + end + end + return res + end + + # Return a "const char*" variable associated to the classname of the dynamic type of an object + # NOTE: we do not return a RuntimeVariable "NativeString" as the class may not exist in the module/program + fun class_name_string(value: RuntimeVariable): String + do + var res = self.get_name("var_class_name") + self.add_decl("const char* {res};") + if value.mtype.ctype == "val*" then + self.add "{res} = class_names[{value}->classid];" + else + self.add "{res} = class_names[{self.compiler.classid(value.mtype.as(MClassType))}];" + end + return res + end + # Generate a Nit "is" for two runtime_variables fun equal_test(value1, value2: RuntimeVariable): RuntimeVariable do @@ -1371,9 +1549,19 @@ private class GlobalCompilerVisitor end # Generate a check-init-instance - # TODO: is an empty stub currently fun check_init_instance(recv: RuntimeVariable) do + var mtype = self.anchor(recv.mcasttype) + for cd in mtype.collect_mclassdefs(self.compiler.mainmodule) + do + var n = self.compiler.modelbuilder.mclassdef2nclassdef[cd] + for npropdef in n.n_propdefs do + if npropdef isa AAttrPropdef then + # Force read to check the initialization + self.read_attribute(npropdef.mpropdef.mproperty, recv) + end + end + end end # Generate an integer value @@ -1388,17 +1576,18 @@ private class GlobalCompilerVisitor fun array_instance(array: Array[RuntimeVariable], elttype: MType): RuntimeVariable do elttype = self.anchor(elttype) - var res = self.init_instance(self.get_class("Array").get_mtype([elttype])) + var arraytype = self.get_class("Array").get_mtype([elttype]) + var res = self.init_instance(arraytype) self.add("\{ /* {res} = array_instance Array[{elttype}] */") var nat = self.new_var(self.get_class("NativeArray").get_mtype([elttype])) nat.is_exact = true - self.add("{nat} = GC_MALLOC({array.length} * sizeof({elttype.ctype}));") + self.add("{nat} = NEW_{nat.mtype.c_name}({array.length});") for i in [0..array.length[ do var r = self.autobox(array[i], elttype) - self.add("{nat}[{i}] = {r};") + self.add("((struct {nat.mtype.c_name}*) {nat})->values[{i}] = {r};") end var length = self.int_instance(array.length) - self.send(self.get_property("with_native", res.mtype), [res, nat, length]) + self.send(self.get_property("with_native", arraytype), [res, nat, length]) self.check_init_instance(res) self.add("\}") return res @@ -1419,7 +1608,7 @@ private class GlobalCompilerVisitor var res2 = self.init_instance(mtype) self.add("{res} = {res2};") var length = self.int_instance(string.length) - self.send(self.get_property("with_native", res.mtype), [res, nat, length]) + self.send(self.get_property("with_native", mtype), [res, nat, length]) self.check_init_instance(res) self.add("{name} = {res};") self.add("\}") @@ -1440,7 +1629,7 @@ private class GlobalCompilerVisitor end # A frame correspond to a visited property in a GlobalCompilerVisitor -private class Frame +class Frame # The associated visitor var visitor: GlobalCompilerVisitor @@ -1456,10 +1645,10 @@ private class Frame var arguments: Array[RuntimeVariable] # The runtime_variable associated to the return (in a function) - var returnvar: nullable RuntimeVariable = null + var returnvar: nullable RuntimeVariable writable = null # The label at the end of the property - var returnlabel: nullable String = null + var returnlabel: nullable String writable = null end redef class MPropDef @@ -1478,7 +1667,7 @@ end redef class MMethodDef # Can the body be inlined? - private fun can_inline(v: GlobalCompilerVisitor): Bool + fun can_inline(v: GlobalCompilerVisitor): Bool do var modelbuilder = v.compiler.modelbuilder if modelbuilder.mpropdef2npropdef.has_key(self) then @@ -1493,15 +1682,21 @@ redef class MMethodDef end # Inline the body in another visitor - private fun compile_inside_to_c(v: GlobalCompilerVisitor, arguments: Array[RuntimeVariable]): nullable RuntimeVariable + fun compile_inside_to_c(v: GlobalCompilerVisitor, arguments: Array[RuntimeVariable]): nullable RuntimeVariable do var modelbuilder = v.compiler.modelbuilder if modelbuilder.mpropdef2npropdef.has_key(self) then var npropdef = modelbuilder.mpropdef2npropdef[self] + var oldnode = v.current_node + v.current_node = npropdef npropdef.compile_to_c(v, self, arguments) + v.current_node = oldnode else if self.mproperty.name == "init" then var nclassdef = modelbuilder.mclassdef2nclassdef[self.mclassdef] + var oldnode = v.current_node + v.current_node = nclassdef nclassdef.compile_to_c(v, self, arguments) + v.current_node = oldnode else abort end @@ -1510,13 +1705,13 @@ redef class MMethodDef end redef class APropdef - private fun compile_to_c(v: GlobalCompilerVisitor, mpropdef: MMethodDef, arguments: Array[RuntimeVariable]) + fun compile_to_c(v: GlobalCompilerVisitor, mpropdef: MMethodDef, arguments: Array[RuntimeVariable]) do v.add("printf(\"NOT YET IMPLEMENTED {class_name} {mpropdef} at {location.to_s}\\n\");") debug("Not yet implemented") end - private fun can_inline: Bool do return true + fun can_inline: Bool do return true end redef class AConcreteMethPropdef @@ -1538,7 +1733,6 @@ redef class AConcreteMethPropdef end end end - v.stmt(self.n_block) end @@ -1635,6 +1829,12 @@ redef class AInternMethPropdef else if pname == "object_id" then v.ret(arguments.first) return + else if pname == "+" then + v.ret(v.new_expr("{arguments[0]} + {arguments[1]}", ret.as(not null))) + return + else if pname == "-" then + v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null))) + return else if pname == "==" then v.ret(v.equal_test(arguments[0], arguments[1])) return @@ -1766,17 +1966,8 @@ redef class AInternMethPropdef return end else if cname == "NativeArray" then - var elttype = arguments.first.mtype - if pname == "[]" then - v.ret(v.new_expr("{arguments[0]}[{arguments[1]}]", ret.as(not null))) - return - else if pname == "[]=" then - v.add("{arguments[0]}[{arguments[1]}]={arguments[2]};") - return - else if pname == "copy_to" then - v.add("memcpy({arguments[1]},{arguments[0]},{arguments[2]}*sizeof({elttype.ctype}));") - return - end + v.native_array_def(pname, ret, arguments) + return end if pname == "exit" then v.add("exit({arguments[1]});") @@ -1788,35 +1979,24 @@ redef class AInternMethPropdef v.ret(v.new_expr("(char*)GC_MALLOC({arguments[1]})", ret.as(not null))) return else if pname == "calloc_array" then - var elttype = arguments.first.mtype.supertype_to(v.compiler.mainmodule,arguments.first.mtype.as(MClassType),v.get_class("ArrayCapable")).as(MGenericType).arguments.first - v.ret(v.new_expr("({elttype.ctype}*)GC_MALLOC({arguments[1]} * sizeof({elttype.ctype}))", ret.as(not null))) + v.calloc_array(ret.as(not null), arguments) return else if pname == "object_id" then v.ret(v.new_expr("(long){arguments.first}", ret.as(not null))) return else if pname == "is_same_type" then - if arguments[0].mtype.ctype == "val*" then - v.ret(v.new_expr("{arguments[0]}->classid == {arguments[1]}->classid", ret.as(not null))) - else - v.ret(v.new_expr("{v.compiler.classid(arguments[0].mtype.as(MClassType))} == {arguments[1]}->classid", ret.as(not null))) - end + v.ret(v.is_same_type_test(arguments[0], arguments[1])) return else if pname == "output_class_name" then - if arguments[0].mtype.ctype == "val*" then - v.add("printf(\"%s\\n\", class_names[{arguments.first}->classid]);") - else - v.add("printf(\"%s\\n\", class_names[{v.compiler.classid(arguments.first.mtype.as(MClassType))}]);") - end + var nat = v.class_name_string(arguments.first) + v.add("printf(\"%s\\n\", {nat});") return else if pname == "native_class_name" then - if arguments[0].mtype.ctype == "val*" then - v.ret(v.new_expr("(char*)(void*)class_names[{arguments.first}->classid]", ret.as(not null))) - else - v.ret(v.new_expr("(char*)(void*)class_names[{v.compiler.classid(arguments.first.mtype.as(MClassType))}]", ret.as(not null))) - end + var nat = v.class_name_string(arguments.first) + v.ret(v.new_expr("(char*){nat}", ret.as(not null))) return end - v.add("printf(\"NOT IMPLEMENTED {class_name}:{mpropdef} at {location.to_s}\\n\");") + v.add("printf(\"NOT YET IMPLEMENTED {class_name}:{mpropdef} at {location.to_s}\\n\");") debug("Not implemented {mpropdef}") end end @@ -1841,6 +2021,7 @@ redef class AExternMethPropdef ret = v.resolve_for(ret, arguments.first) res = v.new_var(ret) end + v.adapt_signature(mpropdef, arguments) if res == null then v.add("{externname}({arguments.join(", ")});") @@ -1865,6 +2046,7 @@ redef class AExternInitPropdef var file = location.file.filename v.compiler.add_extern(file) end + v.adapt_signature(mpropdef, arguments) var ret = arguments.first.mtype var res = v.new_var(ret) @@ -1886,7 +2068,7 @@ redef class AAttrPropdef end end - private fun init_expr(v: GlobalCompilerVisitor, recv: RuntimeVariable) + fun init_expr(v: GlobalCompilerVisitor, recv: RuntimeVariable) do var nexpr = self.n_expr if nexpr != null then @@ -2121,21 +2303,31 @@ redef class AForExpr redef fun stmt(v) do var cl = v.expr(self.n_expr, null) - var it = v.send(v.get_property("iterator", cl.mtype), [cl]) + var it_meth = self.method_iterator + assert it_meth != null + var it = v.send(it_meth, [cl]) assert it != null v.add("for(;;) \{") - var ok = v.send(v.get_property("is_ok", it.mtype), [it]) + var isok_meth = self.method_is_ok + assert isok_meth != null + var ok = v.send(isok_meth, [it]) assert ok != null v.add("if(!{ok}) break;") if self.variables.length == 1 then - var i = v.send(v.get_property("item", it.mtype), [it]) + var item_meth = self.method_item + assert item_meth != null + var i = v.send(item_meth, [it]) assert i != null v.assign(v.variable(variables.first), i) else if self.variables.length == 2 then - var i = v.send(v.get_property("key", it.mtype), [it]) + var key_meth = self.method_key + assert key_meth != null + var i = v.send(key_meth, [it]) assert i != null v.assign(v.variable(variables[0]), i) - i = v.send(v.get_property("item", it.mtype), [it]) + var item_meth = self.method_item + assert item_meth != null + i = v.send(item_meth, [it]) assert i != null v.assign(v.variable(variables[1]), i) else @@ -2143,7 +2335,9 @@ redef class AForExpr end v.stmt(self.n_block) v.add("CONTINUE_{v.escapemark_name(escapemark)}: (void)0;") - v.send(v.get_property("next", it.mtype), [it]) + var next_meth = self.method_next + assert next_meth != null + v.send(next_meth, [it]) v.add("\}") v.add("BREAK_{v.escapemark_name(escapemark)}: (void)0;") end @@ -2251,7 +2445,7 @@ end redef class AArrayExpr redef fun expr(v) do - var mtype = self.mtype.as(MGenericType).arguments.first + var mtype = self.mtype.as(MClassType).arguments.first var array = new Array[RuntimeVariable] for nexpr in self.n_exprs.n_exprs do var i = v.expr(nexpr, mtype) @@ -2450,6 +2644,7 @@ redef class ASuperExpr # FIXME: we do not want an ugly static call! var mpropdefs = mpropdef.mproperty.lookup_super_definitions(mpropdef.mclassdef.mmodule, mpropdef.mclassdef.bound_mtype) if mpropdefs.length != 1 then + v.add("printf(\"NOT YET IMPLEMENTED {class_name} {mpropdef} at {location.to_s}\\n\");") debug("MPRODFEFS for super {mpropdef} for {recv}: {mpropdefs.join(", ")}") end mpropdef = mpropdefs.first @@ -2521,6 +2716,12 @@ redef class AAttrReassignExpr end redef class AIssetAttrExpr + redef fun expr(v) + do + var recv = v.expr(self.n_expr, null) + var mproperty = self.mproperty.as(not null) + return v.isset_attribute(mproperty, recv) + end end redef class ADebugTypeExpr