fun add_new_array(stype: MMType, length: Int): IRegister
do
var prop = visitor.get_method(stype, once "with_capacity".to_symbol)
- var ni = expr(new INative("TAG_Int({length})", null), visitor.type_int)
+ var ni = expr(new IIntValue(length.to_s), visitor.type_int)
return expr(new INew(stype, prop, [ni]), stype)
end
v.seq = iclos.body
escapable.continue_seq = iclos.body
escapable.continue_value = iclos.result
+ escapable.break_seq = v.return_seq
+ escapable.break_value = v.return_value
n_signature.fill_iroutine_parameters(v, variable.closure.signature, iclos.params, null)
if n_expr != null then
v.generate_stmt(n_expr)
v.iroutine.closure_decls[position].default = iclos
+
+ # Add a final break in case of break block witout value
+ if variable.closure.is_break and v.return_value == null then
+ v.add_escape(v.return_seq.as(not null))
+ end
end
v.seq = old_seq
end
if ne != null then
v.add_assignment(v.return_value.as(not null), v.generate_expr(ne))
end
- v.stmt(new IEscape(v.return_seq.as(not null)))
+ v.add_escape(v.return_seq.as(not null))
return null
end
end
if ne != null then
v.add_assignment(escapable.break_value.as(not null), v.generate_expr(ne))
end
- v.stmt(new IEscape(escapable.break_seq.as(not null)))
+ v.add_escape(escapable.break_seq.as(not null))
return null
end
end
if ne != null then
v.add_assignment(escapable.continue_value.as(not null), v.generate_expr(ne))
end
- v.stmt(new IEscape(escapable.continue_seq.as(not null)))
+ v.add_escape(escapable.continue_seq.as(not null))
return null
end
end
# Process escape (condition is false)
v.seq = iif.else_seq
- v.stmt(new IEscape(iloop))
+ v.add_escape(iloop)
v.seq = seq_old
return null
redef class AForExpr
redef fun generate_icode(v)
do
- var expr_type = n_expr.stype
-
- # Get iterator
- var meth_iterator = v.visitor.get_method(expr_type, once "iterator".to_symbol)
-
- var iter_type = meth_iterator.signature_for(expr_type).return_type.as(not null)
- var ireg_iter = v.expr(new ICall(meth_iterator, [v.generate_expr(n_expr)]), iter_type)
-
- # Enter loop
- var seq_old = v.seq
- var iloop = new ILoop
- v.stmt(iloop)
- escapable.break_seq = iloop
- v.seq = iloop
-
- # Condition evaluation
- var meth_is_ok = v.visitor.get_method(iter_type, once ("is_ok".to_symbol))
- var ireg_isok = v.expr(new ICall(meth_is_ok, [ireg_iter]), v.visitor.type_bool)
- var iif = new IIf(ireg_isok)
+ var ne = n_expr
+ var expr_type = ne.stype
+ var tint = v.visitor.type_int
+ var meth # The method that call the closure
+ var args # The arguments of meth
+
+ if ne isa ARangeExpr and expr_type == v.visitor.type_range(tint) then
+ # Shortcut. No Range[Int] object allocated.
+ # 'for x in [y..z] do' become 'y.enumerate_to(z) !each(x) do'
+ # 'for x in [y..z[ do' become 'y.enumerate_before(z) !each(x) do'
+ # And both methods may be inlined
+ args = [v.generate_expr(ne.n_expr), v.generate_expr(ne.n_expr2)]
+ if ne isa ACrangeExpr then
+ meth = v.visitor.get_method(tint, once "enumerate_to".to_symbol)
+ else
+ assert ne isa AOrangeExpr
+ meth = v.visitor.get_method(tint, once "enumerate_before".to_symbol)
+ end
+ else
+ # Standard way.
+ # 'for x in e do' become 'e.iterate !each(x) do'
+ # Some iterate methods may be inlined (eg. the Array one)
+ meth = v.visitor.get_method(expr_type, once "iterate".to_symbol)
+ args = [v.generate_expr(n_expr)]
+ end
- # Process insite the loop (condition is true)
- v.stmt(iif)
- v.seq = iif.then_seq
- escapable.continue_seq = iif.then_seq
+ # Build closure
+ var iclos = meth.signature.closures.first.signature.generate_empty_iclosuredef(v)
+ var old_seq = v.seq
- # Automatic variable assignment
- var meth_item = v.visitor.get_method(iter_type, once ("item".to_symbol))
- var va_stype = variable.stype.as(not null)
- var ireg_item = v.expr(new ICall(meth_item, [ireg_iter]), va_stype)
- var ireg_va = v.variable(variable)
- v.add_assignment(ireg_va, ireg_item)
+ var seq = new ISeq
+ v.stmt(seq)
+ v.seq = seq
+ escapable.break_seq = seq
+ escapable.break_value = null
- # Body evaluation
+ v.seq = iclos.body
+ escapable.continue_seq = iclos.body
+ escapable.continue_value = null
+ v.stmt(new IMove(v.variable(variable), iclos.params.first))
v.generate_stmt(n_block)
- # Exit contition (condition is false)
- v.seq = iif.else_seq
- v.stmt(new IEscape(iloop))
-
- # Next step
- var meth_next = v.visitor.get_method(iter_type, once ("next".to_symbol))
- v.seq = iloop
- v.stmt(new ICall(meth_next, [ireg_iter]))
+ # Call closure
+ v.seq = seq
+ v.add_call(meth, args, [iclos])
- v.seq = seq_old
+ v.seq = old_seq
return null
end
end
redef class AIntExpr
redef fun generate_icode(v)
do
- return v.expr(new INative("TAG_Int({n_number.text})", null), stype)
+ return v.expr(new IIntValue(n_number.text), stype)
end
end
redef class AFloatExpr
redef fun generate_icode(v)
do
- return v.expr(new INative("BOX_Float({n_float.text})", null), stype)
+ return v.expr(new IFloatValue(n_float.text), stype)
end
end
redef class ACharExpr
redef fun generate_icode(v)
do
- return v.expr(new INative("TAG_Char({n_char.text})", null), stype)
+ return v.expr(new ICharValue(n_char.text), stype)
end
end
var ionce = new IOnce
var reg = v.expr(ionce, stype)
v.seq = ionce.body
- var ns = v.expr(new INative("BOX_NativeString(\"{_cstring}\")", null), v.visitor.type_nativestring)
- var ni = v.expr(new INative("TAG_Int({_cstring_length})", null), v.visitor.type_int)
+ var ns = v.expr(new IStringValue(_cstring.as(not null)), v.visitor.type_nativestring)
+ var ni = v.expr(new IIntValue(_cstring_length.to_s), v.visitor.type_int)
var prop = v.visitor.get_method(stype, once "with_native".to_symbol)
var e = v.expr(new INew(stype, prop, [ns, ni]), stype)
v.add_assignment(reg, e)
v.generate_stmt(n_expr)
+ # Add a final break in case of break block witout value
+ if closure.is_break and escapable.break_value == null then
+ v.add_escape(escapable.break_seq.as(not null))
+ end
+
v.seq = seq_old
_iclosure_def = iclos
return iclos