X-Git-Url: http://nitlanguage.org diff --git a/src/compiling/compiling_methods.nit b/src/compiling/compiling_methods.nit index 7e27df8..1253a51 100644 --- a/src/compiling/compiling_methods.nit +++ b/src/compiling/compiling_methods.nit @@ -73,12 +73,12 @@ redef class CompilerVisitor # Generate an fprintf to display an error location meth printf_locate_error(node: PNode): String do - var s = "fprintf(stderr, \"" + var s = new Buffer.from("fprintf(stderr, \"") if nmc != null then s.append(" in %s") s.append(" (%s:%d)\\n\", ") if nmc != null then s.append("LOCATE_{nmc.method.cname}, ") s.append("LOCATE_{module.name}, {node.line_number});") - return s + return s.to_s end redef init(module: MMSrcModule) @@ -302,7 +302,7 @@ redef class MMMethod cargs.add("init_table /*YYY*/") end - var m = "(({cname}_t)CALL({cargs[0]},{global.color_id}))" + var m = "{global.meth_call}({cargs[0]})" var vcall = "{m}({cargs.join(", ")}) /*{local_class}::{name}*/" if name == ee then vcall = "UNTAG_Bool({vcall})" @@ -331,7 +331,7 @@ redef class MMMethod # Compile a call as call-next-method on self with given args meth compile_super_call(v: CompilerVisitor, cargs: Array[String]): String do - var m = "(({cname}_t)CALL({cargs[0]},{color_id_for_super}))" + var m = "{super_meth_call}({cargs[0]})" var vcall = "{m}({cargs.join(", ")}) /*super {local_class}::{name}*/" return vcall end @@ -530,44 +530,54 @@ redef class AMethPropdef meth do_compile_inside(v: CompilerVisitor, method: MMSrcMethod, params: Array[String]): String is abstract end +redef class PSignature + meth compile_parameters(v: CompilerVisitor, orig_sig: MMSignature, params: Array[String]) is abstract +end + +redef class ASignature + redef meth compile_parameters(v: CompilerVisitor, orig_sig: MMSignature, params: Array[String]) + do + for ap in n_params do + var cname = v.cfc.register_variable(ap.variable) + v.nmc.method_params.add(ap.variable) + var orig_type = orig_sig[ap.position] + if not orig_type < ap.variable.stype then + # FIXME: do not test always + # FIXME: handle formal types + v.add_instr("/* check if p<{ap.variable.stype} with p:{orig_type} */") + ap.variable.stype.compile_type_check(v, params[ap.position], ap) + end + v.add_assignment(cname, params[ap.position]) + end + for i in [0..n_closure_decls.length[ do + var wd = n_closure_decls[i] + var cname = v.cfc.register_closurevariable(wd.variable) + wd.variable.ctypename = "struct {v.nmc.method.closure_cname(i)} *" + v.add_assignment(cname, "{params[orig_sig.arity + i]}") + end + end +end + redef class AConcreteMethPropdef redef meth do_compile_inside(v, method, params) do var old_nmc = v.nmc v.nmc = new NitMethodContext(method) - var cname = v.cfc.register_variable(self_var) - v.add_assignment(cname, params[0]) + var selfcname = v.cfc.register_variable(self_var) + v.add_assignment(selfcname, params[0]) + params.shift v.nmc.method_params = [self_var] - var orig_meth: MMLocalProperty = method.global.intro - var orig_sig = orig_meth.signature_for(method.signature.recv) if n_signature != null then - var sig = n_signature - assert sig isa ASignature - for ap in sig.n_params do - var cname = v.cfc.register_variable(ap.variable) - v.nmc.method_params.add(ap.variable) - var orig_type = orig_sig[ap.position] - if not orig_type < ap.variable.stype then - # FIXME: do not test always - # FIXME: handle formal types - v.add_instr("/* check if p<{ap.variable.stype} with p:{orig_type} */") - ap.variable.stype.compile_type_check(v, params[ap.position + 1], ap) - end - v.add_assignment(cname, params[ap.position + 1]) - end - for i in [0..sig.n_closure_decls.length[ do - var wd = sig.n_closure_decls[i] - var cname = v.cfc.register_closurevariable(wd.variable) - wd.variable.ctypename = "struct {method.closure_cname(i)} *" - v.add_assignment(cname, "{params[orig_sig.arity + i + 1]}") - end + var orig_meth: MMLocalProperty = method.global.intro + var orig_sig = orig_meth.signature_for(method.signature.recv) + n_signature.compile_parameters(v, orig_sig, params) end var itpos: String = null if self isa AConcreteInitPropdef then - itpos = "VAL2OBJ({params[0]})->vft[{method.local_class.global.init_table_pos_id}].i" + itpos = "VAL2OBJ({selfcname})->vft[{method.local_class.global.init_table_pos_id}].i" # v.add_instr("printf(\"{method.full_name}: inittable[%d] = %d\\n\", {itpos}, init_table[{itpos}]);") v.add_instr("if (init_table[{itpos}]) return;") end @@ -992,37 +1002,17 @@ redef class AForVardeclExpr redef meth compile_stmt(v) do var e = v.compile_expr(n_expr) - var prop = n_expr.stype.local_class.select_method(once "iterator".to_symbol) - if prop == null then - printl("No iterator") - return - end - var ittype = prop.signature.return_type + var ittype = meth_iterator.signature.return_type v.cfc.free_var(e) var iter = v.cfc.get_var - v.add_assignment(iter, prop.compile_call(v, [e])) - var prop2 = ittype.local_class.select_method(once "is_ok".to_symbol) - if prop2 == null then - printl("No is_ok") - return - end - var prop3 = ittype.local_class.select_method(once "item".to_symbol) - if prop3 == null then - printl("No item") - return - end - var prop4 = ittype.local_class.select_method(once "next".to_symbol) - if prop4 == null then - printl("No next") - return - end + v.add_assignment(iter, meth_iterator.compile_call(v, [e])) v.add_instr("while (true) \{ /*for*/") v.indent var ok = v.cfc.get_var - v.add_assignment(ok, prop2.compile_call(v, [iter])) + v.add_assignment(ok, meth_is_ok.compile_call(v, [iter])) v.add_instr("if (!UNTAG_Bool({ok})) break; /*for*/") v.cfc.free_var(ok) - var e = prop3.compile_call(v, [iter]) + var e = meth_item.compile_call(v, [iter]) e = v.ensure_var(e) var cname = v.cfc.register_variable(variable) v.add_assignment(cname, e) @@ -1033,7 +1023,7 @@ redef class AForVardeclExpr v.compile_stmt(n_block) end v.add_instr("{v.nmc.continue_label}: while(0);") - e = prop4.compile_call(v, [iter]) + e = meth_next.compile_call(v, [iter]) assert e == null v.unindent v.add_instr("}") @@ -1186,9 +1176,8 @@ end redef class AStringFormExpr redef meth compile_expr(v) do - var prop = stype.local_class.select_method(once "with_native".to_symbol) compute_string_info - return prop.compile_constructor_call(v, stype , ["BOX_NativeString(\"{_cstring}\")", "TAG_Int({_cstring_length})"]) + return meth_with_native.compile_constructor_call(v, stype , ["BOX_NativeString(\"{_cstring}\")", "TAG_Int({_cstring_length})"]) end # The raw string value @@ -1205,7 +1194,7 @@ redef class AStringFormExpr do var len = 0 var str = string_text - var res = new String + var res = new Buffer var i = 0 while i < str.length do var c = str[i] @@ -1221,7 +1210,7 @@ redef class AStringFormExpr res.add(c) i = i + 1 end - _cstring = res + _cstring = res.to_s _cstring_length = len end end @@ -1242,21 +1231,17 @@ end redef class ASuperstringExpr redef meth compile_expr(v) do - var prop = stype.local_class.select_method(once "init".to_symbol) - var recv = prop.compile_constructor_call(v, stype, new Array[String]) - - var prop2 = stype.local_class.select_method(once "append".to_symbol) + var array = meth_with_capacity.compile_constructor_call(v, atype, ["TAG_Int({n_exprs.length})"]) - var prop3 = stype.local_class.select_method(once "to_s".to_symbol) for ne in n_exprs do var e = v.ensure_var(v.compile_expr(ne)) if ne.stype != stype then - v.add_assignment(e, prop3.compile_call(v, [e])) + v.add_assignment(e, meth_to_s.compile_call(v, [e])) end - prop2.compile_call(v, [recv, e]) + meth_add.compile_call(v, [array, e]) end - return recv + return meth_to_s.compile_call(v, [array]) end end @@ -1270,13 +1255,11 @@ end redef class AArrayExpr redef meth compile_expr(v) do - var prop = stype.local_class.select_method(once "with_capacity".to_symbol) - var recv = prop.compile_constructor_call(v, stype, ["TAG_Int({n_exprs.length})"]) + var recv = meth_with_capacity.compile_constructor_call(v, stype, ["TAG_Int({n_exprs.length})"]) - var prop2 = stype.local_class.select_method(once "add".to_symbol) for ne in n_exprs do var e = v.compile_expr(ne) - prop2.compile_call(v, [recv, e]) + meth_add.compile_call(v, [recv, e]) end return recv end @@ -1285,20 +1268,10 @@ end redef class ARangeExpr redef meth compile_expr(v) do - var prop = stype.local_class.select_method(propname) var e = v.compile_expr(n_expr) var e2 = v.compile_expr(n_expr2) - return prop.compile_constructor_call(v, stype, [e, e2]) + return meth_init.compile_constructor_call(v, stype, [e, e2]) end - # The constructor that must be used for the range - protected meth propname: Symbol is abstract -end - -redef class ACrangeExpr - redef meth propname do return once "init".to_symbol -end -redef class AOrangeExpr - redef meth propname do return once "without_last".to_symbol end redef class ASuperExpr @@ -1608,30 +1581,62 @@ redef class AClosureDef end end +redef class PClosureDecl + meth do_compile_inside(v: CompilerVisitor, params: Array[String]): String is abstract +end +redef class AClosureDecl + redef meth do_compile_inside(v, params) + do + if n_signature != null then n_signature.compile_parameters(v, variable.closure.signature, params) + + var old_cv = v.nmc.continue_value + var old_cl = v.nmc.continue_label + var old_bl = v.nmc.break_label + + v.nmc.continue_value = v.cfc.get_var + v.nmc.continue_label = "continue_label{v.new_number}" + v.nmc.break_label = v.nmc.return_label + + if n_expr != null then v.compile_stmt(n_expr) + + v.add_instr("{v.nmc.continue_label}: while(false);") + + var ret: String = null + if variable.closure.signature.return_type != null then ret = v.nmc.continue_value + + v.nmc.continue_value = old_cv + v.nmc.continue_label = old_cl + v.nmc.break_label = old_bl + + return ret + end +end + redef class AClosureCallExpr redef meth compile_expr(v) do + var cargs = new Array[String] + for a in arguments do cargs.add(v.compile_expr(a)) + var va: String = null + if variable.closure.signature.return_type != null then va = v.cfc.get_var + if variable.closure.is_optional then v.add_instr("if({v.cfc.varname(variable)}==NULL) \{") v.indent var n = variable.decl assert n isa AClosureDecl - v.compile_stmt(n.n_expr) + var s = n.do_compile_inside(v, cargs) + if s != null then v.add_assignment(va, s) v.unindent v.add_instr("} else \{") v.indent end - var cargs = new Array[String] var ivar = "(({variable.ctypename})({v.cfc.varname(variable)}))" - cargs.add(ivar) - for a in arguments do - cargs.add(v.compile_expr(a)) - end - var s = "({ivar}->fun({cargs.join(", ")})) /* Invoke closure {variable} */" - var va: String = null - if variable.closure.signature.return_type != null then - va = v.cfc.get_var + var cargs2 = [ivar] + cargs2.append(cargs) + var s = "({ivar}->fun({cargs2.join(", ")})) /* Invoke closure {variable} */" + if va != null then v.add_assignment(va, s) else v.add_instr("{s};")