X-Git-Url: http://nitlanguage.org diff --git a/src/transform.nit b/src/transform.nit index 2c0fb02..ebe2c73 100644 --- a/src/transform.nit +++ b/src/transform.nit @@ -20,12 +20,13 @@ import astbuilder import astvalidation import semantize intrude import semantize::scope +intrude import semantize::typing redef class ToolContext var transform_phase: Phase = new TransformPhase(self, [typing_phase, auto_super_init_phase]) # --no-shortcut-range - var opt_no_shortcut_range: OptionBool = new OptionBool("Always insantiate a range and its iterator on 'for' loops", "--no-shortcut-range") + var opt_no_shortcut_range: OptionBool = new OptionBool("Always instantiate a range and its iterator on 'for' loops", "--no-shortcut-range") redef init do @@ -41,7 +42,9 @@ private class TransformPhase do var val - var v = new TransformVisitor(self, npropdef.mpropdef.as(not null)) + var m = npropdef.mpropdef + if m == null then return + var v = new TransformVisitor(self, m) v.enter_visit(npropdef) val = new ASTValidationVisitor @@ -71,12 +74,6 @@ private class TransformVisitor node.full_transform_visitor(self) end - # Get a primitive class or display a fatal error on `location`. - fun get_class(location: AExpr, name: String): MClass - do - return mmodule.get_primitive_class(name) - end - # Get a primitive method or display a fatal error on `location`. fun get_method(location: AExpr, name: String, recv: MClass): MMethod do @@ -95,6 +92,30 @@ redef class ANode end end +redef class AExpr + redef fun full_transform_visitor(v: TransformVisitor) + do + var na = comprehension + if na != null then + # We are building a comprehension array `array` + # Replace `self` with `array.push(self)` + var place = detach_with_placeholder + var recv = na.nnew.make_var_read + var nadd = v.builder.make_call(recv, na.push_callsite.as(not null), [self]) + place.replace_with(nadd) + end + super + end + + redef fun replace_with(other) + do + super + if other isa AExpr then + if other.implicit_cast_to == null then other.implicit_cast_to = implicit_cast_to + end + end +end + redef class AVardeclExpr # `var x = y` is replaced with `x = y` # @@ -273,6 +294,57 @@ redef class AForExpr end end +redef class AWithExpr + # is replaced with a do/end and injected calls to `start` and `finish` + # + # Basically, the following + # + # ~~~nitish + # with expr do + # block + # end label l + # ~~~ + # + # is transformed into + # + # ~~~nitish + # var x = expr + # do + # x.start + # block + # end label l + # x.finish + # ~~~ + # + # The point is that `finish` is called even if the block is escaped. + redef fun accept_transform_visitor(v) + do + var escapemark = self.break_mark + assert escapemark != null + + var nblock = v.builder.make_block + + var nexpr = n_expr + + nblock.add nexpr + + var ndo = v.builder.make_do + ndo.break_mark = escapemark + + var start = v.builder.make_call(nexpr.make_var_read, method_start.as(not null), null) + + ndo.add start + + ndo.add self.n_block.as(not null) + + nblock.add ndo + + nblock.add v.builder.make_call(nexpr.make_var_read, method_finish.as(not null), null) + + replace_with(nblock) + end +end + redef class AArrayExpr # `[x,y]` is replaced with # @@ -282,22 +354,27 @@ redef class AArrayExpr # t.add(y) # t # ~~~ - redef fun accept_transform_visitor(v) + redef fun full_transform_visitor(v) do var nblock = v.builder.make_block var nnew = v.builder.make_new(with_capacity_callsite.as(not null), [v.builder.make_int(n_exprs.length)]) + self.nnew = nnew + nblock.add nnew + super + for nexpr in self.n_exprs do - var nadd = v.builder.make_call(nnew.make_var_read, push_callsite.as(not null), [nexpr]) - nblock.add nadd + nblock.add nexpr end var nres = nnew.make_var_read nblock.add nres replace_with(nblock) end + + private var nnew: ANewExpr is noinit end redef class ACrangeExpr