# 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)
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})"
# 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
var first_closure_index = signature.arity + 1 # Wich parameter is the first closure
for i in [0..signature.closures.length[ do
var closcn = closure_cname(i)
- var cs = signature.closures[i] # Closure signature
+ var cs = signature.closures[i].signature # Closure signature
var subparams = new Array[String] # Parameters of the closure
subparams.add("struct {closcn}*")
for j in [0..cs.arity[ do
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
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)
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("}")
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
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]
res.add(c)
i = i + 1
end
- _cstring = res
+ _cstring = res.to_s
_cstring_length = len
end
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 array = meth_with_capacity.compile_constructor_call(v, atype, ["TAG_Int({n_exprs.length})"])
- var prop2 = stype.local_class.select_method(once "append".to_symbol)
-
- 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
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
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
cargs.add(v.compile_expr(a))
end
- var cd = closure_defs
var e: String
- if cd == null then
+ if prop_signature.closures.is_empty then
e = prop.compile_call(v, cargs)
else
+ var cd = closure_defs
+ var arity = 0
+ if cd != null then arity = cd.length
var closcns = new Array[String]
var ve: String = null
v.nmc.break_value = ve
# Compile closure to c function
- for i in [0..cd.length[ do
+ for i in [0..arity[ do
var cn = cd[i].compile_closure(v, prop.closure_cname(i))
closcns.add(cn)
cargs.add(cn)
end
+ for i in [arity..prop_signature.closures.length[ do
+ cargs.add("NULL")
+ end
v.nmc.break_value = old_bv
end
# Intercept returns and breaks
- for i in [0..cd.length[ do
+ for i in [0..arity[ do
# A break or a return is intercepted
v.add_instr("if ({closcns[i]}->has_broke != NULL) \{")
v.indent
var cname = "OC_{v.nmc.method.cname}_{v.out_contexts.length}"
_cname = cname
var args = new Array[String]
- for i in [0..signature.arity[ do
+ for i in [0..closure.signature.arity[ do
args.add(" param{i}")
end
do
var params = new Array[String]
params.add("struct {closcn}* closctx")
- for i in [0..signature.arity[ do
+ for i in [0..closure.signature.arity[ do
var p = "val_t {args[i]}"
params.add(p)
end
var ret: String
- if signature.return_type != null then
+ if closure.signature.return_type != null then
ret = "val_t"
else
ret = "void"
v.add_instr("{v.nmc.continue_label}: while(false);")
var ret: String = null
- if signature.return_type != null then ret = v.nmc.continue_value
+ if 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 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
redef meth compile_expr(v)
do
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} */"
+ for a in arguments do cargs.add(v.compile_expr(a))
var va: String = null
- if variable.signature.return_type != null then
- va = v.cfc.get_var
+ 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
+ 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 ivar = "(({variable.ctypename})({v.cfc.varname(variable)}))"
+ 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};")
v.add_instr("goto {v.nmc.return_label};")
v.unindent
v.add_instr("\}")
+
+ if variable.closure.is_optional then
+ v.unindent
+ v.add_instr("\}")
+ end
return va
end
end