transform: transforms `while` and `for`
authorJean Privat <jean@pryen.org>
Sat, 11 Oct 2014 04:28:37 +0000 (00:28 -0400)
committerJean Privat <jean@pryen.org>
Wed, 15 Oct 2014 18:57:04 +0000 (14:57 -0400)
Signed-off-by: Jean Privat <jean@pryen.org>

src/astbuilder.nit
src/transform.nit

index 428a5ca..fd2e22e 100644 (file)
@@ -154,7 +154,7 @@ redef class AExpr
        # Note: this method, aimed to `ABlockExpr` is promoted to `AExpr` because of the limitations of the hierarchies generated by sablecc3
        fun add(expr: AExpr)
        do
-               print "add not inplemented in {inspect}"
+               print "add not implemented in {inspect}"
                abort
        end
 end
index 6a209c3..50ea215 100644 (file)
@@ -19,6 +19,7 @@ module transform
 import astbuilder
 import astvalidation
 import semantize
+intrude import semantize::scope
 
 redef class ToolContext
        var transform_phase: Phase = new TransformPhase(self, [typing_phase, auto_super_init_phase])
@@ -151,14 +152,78 @@ end
 redef class AWhileExpr
        redef fun accept_transform_visitor(v)
        do
-               # TODO
+               var nloop = v.builder.make_loop
+               var nif = v.builder.make_if(n_expr, null)
+               nloop.add nif
+
+               var nblock = n_block
+               if nblock != null then nif.n_then.add nblock
+
+               var escapemark = self.break_mark.as(not null)
+               var nbreak = v.builder.make_break(escapemark)
+               nif.n_else.add nbreak
+
+               nloop.break_mark = self.break_mark
+               nloop.continue_mark = self.continue_mark
+
+               replace_with(nloop)
        end
 end
 
 redef class AForExpr
        redef fun accept_transform_visitor(v)
        do
-               # TODO
+               var escapemark = self.break_mark
+               assert escapemark != null
+
+               var nblock = v.builder.make_block
+
+               var nexpr = n_expr
+
+               nblock.add nexpr
+
+               var iter = v.builder.make_call(nexpr.make_var_read, method_iterator.as(not null), null)
+               nblock.add iter
+
+               var nloop = v.builder.make_loop
+               nloop.break_mark = escapemark
+               nblock.add nloop
+
+               var is_ok = v.builder.make_call(iter.make_var_read, method_is_ok.as(not null), null)
+
+               var nif = v.builder.make_if(is_ok, null)
+               nloop.add nif
+
+               var nthen = nif.n_then
+               var ndo = v.builder.make_do
+               ndo.break_mark = escapemark.continue_mark
+               nthen.add ndo
+
+               if self.variables.length == 1 then
+                       var item = v.builder.make_call(iter.make_var_read, method_item.as(not null), null)
+                       ndo.add v.builder.make_var_assign(variables.first, item)
+               else if self.variables.length == 2 then
+                       var key = v.builder.make_call(iter.make_var_read, method_key.as(not null), null)
+                       ndo.add v.builder.make_var_assign(variables[0], key)
+                       var item = v.builder.make_call(iter.make_var_read, method_item.as(not null), null)
+                       ndo.add v.builder.make_var_assign(variables[1], item)
+               else
+                       abort
+               end
+
+               ndo.add self.n_block.as(not null)
+
+               nthen.add v.builder.make_call(iter.make_var_read, method_next.as(not null), null)
+
+               var nbreak = v.builder.make_break(escapemark)
+               nif.n_else.add nbreak
+
+               var method_finish = self.method_finish
+               if method_finish != null then
+                       nblock.add v.builder.make_call(iter.make_var_read, method_finish, null)
+               end
+
+               replace_with(nblock)
        end
 end