X-Git-Url: http://nitlanguage.org diff --git a/src/syntax/icode_generation.nit b/src/syntax/icode_generation.nit index acf2efe..6993719 100644 --- a/src/syntax/icode_generation.nit +++ b/src/syntax/icode_generation.nit @@ -24,7 +24,7 @@ private import primitive_info # An AST2ICode context stores the currently built icode informations class A2IContext -special ICodeBuilder + super ICodeBuilder redef fun stmt(s: ICode) do if _current_node != null then @@ -82,9 +82,12 @@ special ICodeBuilder # The method associated to the iroutine (if any) readable var _method: nullable MMMethod + # The register of self (if any) + var selfreg: nullable IRegister writable + init(visitor: AbsSyntaxVisitor, r: IRoutine, m: nullable MMMethod) do - super(visitor.module, r) + super(visitor.mmmodule, r) _visitor = visitor _return_seq = r.body _return_value = r.result @@ -177,8 +180,8 @@ redef class MMSrcModule fun generate_icode(tc: ToolContext) do var v = new A2IVisitor(tc, self) - for c in src_local_classes do - for p in c.src_local_properties do + for c in src_local_classes.values do + for p in c.src_local_properties.values do if p isa MMSrcMethod then p.generate_iroutine(v) else if p isa MMSrcAttribute then @@ -279,7 +282,7 @@ redef class MMImplicitInit end class A2IVisitor -special AbsSyntaxVisitor + super AbsSyntaxVisitor writable var _icode_ctx: nullable A2IContext fun icode_ctx: A2IContext do return _icode_ctx.as(not null) redef fun visit(n) do n.accept_icode_generation(self) @@ -368,6 +371,7 @@ redef class AConcreteMethPropdef var params = v.iroutine.params.to_a var selfreg = v.variable(self_var) v.stmt(new IMove(selfreg, params[0])) + v.selfreg = selfreg params.shift var orig_meth: MMLocalProperty = method.global.intro @@ -383,6 +387,39 @@ redef class AConcreteMethPropdef if n_block != null then v.generate_stmt(n_block) end + v.selfreg = null + end +end + +redef class AExternPropdef + redef fun fill_iroutine(v, method) + do + # add all explicit extern calls for this extern method + for explicit_import in method.as(MMMethSrcMethod).explicit_imports + do + var prop = explicit_import.method + var ic : IAbsCall + if prop.is_init then + ic = new INew(prop.signature.recv, prop, new List[IRegister]) + else + ic = new ICall(prop, new List[IRegister]) + end + ic.is_explicit_from_extern = true + v.stmt(ic) + end + end +end + +redef class AExternInitPropdef + redef fun fill_iroutine(v, method) + do + var params = v.iroutine.params + var sig = method.signature + assert params.length == sig.arity + 1 + var rtype = sig.recv # sig.return_type + v.add_assignment(new IRegister(rtype), v.expr(new INative(method, params), rtype)) + + super end end @@ -403,6 +440,8 @@ redef class AExternMethPropdef else v.stmt(new INative(method, params)) end + + super end end @@ -625,7 +664,9 @@ redef class AForExpr v.seq = iclos.body escapable.continue_seq = iclos.body escapable.continue_value = null - v.stmt(new IMove(v.variable(variable), iclos.params.first)) + for i in [0..variables.length[ do + v.stmt(new IMove(v.variable(variables[i]), iclos.params[i])) + end v.generate_stmt(n_block) # Call closure @@ -650,7 +691,7 @@ redef class AAssertExpr if id == null then v.add_abort("Assert failed") else - v.add_abort("Assert %s failed", id.to_s) + v.add_abort("Assert '%s' failed", id.text.to_s) end v.seq = seq_old return null @@ -746,6 +787,28 @@ redef class AOrExpr end end +redef class AImpliesExpr + redef fun generate_icode(v) + do + # Prepare result + var reg = v.new_register(stype) + + # Process left operand (in a if/then) + var iif = new IIf(v.generate_expr(n_expr)) + v.stmt(iif) + var seq_old = v.seq + v.seq = iif.else_seq + v.add_assignment(reg, v.lit_true_reg) + + # Process right operand (in the else) + v.seq = iif.then_seq + v.add_assignment(reg, v.generate_expr(n_expr2)) + + v.seq = seq_old + return reg + end +end + redef class AAndExpr redef fun generate_icode(v) do @@ -776,11 +839,41 @@ redef class ANotExpr end end +redef class AOrElseExpr + redef fun generate_icode(v) + do + # Compute left operand + var e = v.generate_expr(n_expr) + + # Prepare result + var reg = v.new_register(stype) + + # Compare left and null + var n = v.lit_null_reg + var c = v.expr(new IIs(e, n), v.mmmodule.type_bool) + var iif = new IIf(c) + v.stmt(iif) + var old_seq = v.seq + + # if equal, result = right opr + v.seq = iif.then_seq + v.add_assignment(reg, v.generate_expr(n_expr2)) + + # else, result = left operand + v.seq = iif.else_seq + v.add_assignment(reg, e) + + v.seq = old_seq + + return reg + end +end + redef class AIsaExpr redef fun generate_icode(v) do var e = v.generate_expr(n_expr) - return v.expr(new ITypeCheck(e, n_type.stype), stype) + return v.expr(new ITypeCheck(v.selfreg.as(not null), e, n_type.stype), stype) end end @@ -866,9 +959,14 @@ redef class AStringFormExpr # Compute _cstring and _cstring_length using string_text protected fun compute_string_infos do - var len = 0 - var str = string_text + var str = n_string.text + if str.length >= 6 and str[0] == str[1] then + str = str.substring(3, str.length - 6) + else + str = str.substring(1, str.length - 2) + end var res = new Buffer + var len = 0 var i = 0 while i < str.length do var c = str[i] @@ -879,6 +977,11 @@ redef class AStringFormExpr res.add(c) end c = c2 + else if c == '"' then + res.add('\\') + else if c == '\n' then + res.add('\\') + c = 'n' end len = len + 1 res.add(c) @@ -928,8 +1031,9 @@ end redef class AArrayExpr redef fun generate_icode(v) do - var recv = v.add_new_array(stype, n_exprs.length) - for ne in n_exprs do + var nes = n_exprs.n_exprs + var recv = v.add_new_array(stype, nes.length) + for ne in nes do var e = v.generate_expr(ne) v.add_call_array_add(recv, e) end @@ -966,12 +1070,13 @@ redef class ASuperExpr end var args = new Array[IRegister].with_capacity(arity + 1) args.add(v.iroutine.params[0]) - if n_args.length != arity then + var nas = n_args.n_exprs + if nas.length != arity then for i in [0..arity[ do args.add(v.iroutine.params[i + 1]) end else - for na in n_args do + for na in nas do args.add(v.generate_expr(na)) end end @@ -1288,3 +1393,11 @@ redef class AClosureCallExpr return r end end + +redef class ADebugTypeExpr + redef fun generate_icode(v) + do + # Do nothing. + return null + end +end