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
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
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
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
+
+ visit_all(v)
+
+ if mtype == null and not is_typed then return # Skip broken
+
+ accept_transform_visitor(v)
+ 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`
#
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
#
# 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