comp: compile `lazy` in the getter
authorJean Privat <jean@pryen.org>
Mon, 21 Jul 2014 19:59:36 +0000 (15:59 -0400)
committerJean Privat <jean@pryen.org>
Tue, 22 Jul 2014 11:58:09 +0000 (07:58 -0400)
For primitive and nullables, lazy is implemented with an additionnal
boolean attribute used as a guard.
The guard is also update in the setter.

For nonnullable val*, lazy is implemented with issset that is currently
only correctly implemented in this subcase.

One isset has a good implementation, the guard implemnatation can be
removed.

Signed-off-by: Jean Privat <jean@pryen.org>

src/abstract_compiler.nit

index ac308b2..fb376ac 100644 (file)
@@ -2123,11 +2123,44 @@ redef class AAttrPropdef
        do
                if mpropdef == mreadpropdef then
                        assert arguments.length == 1
-                       var res = v.read_attribute(self.mpropdef.mproperty, arguments.first)
+                       var res
+                       if is_lazy then
+                               var nexpr = n_expr
+                               assert nexpr != null
+                               var set
+                               var ret = self.mpropdef.static_mtype
+                               var useiset = ret.ctype == "val*" and not ret isa MNullableType
+                               var guard = self.mlazypropdef.mproperty
+                               if useiset then
+                                       set = v.isset_attribute(self.mpropdef.mproperty, arguments.first)
+                               else
+                                       set = v.read_attribute(guard, arguments.first)
+                               end
+                               v.add("if(likely({set})) \{")
+                               res = v.read_attribute(self.mpropdef.mproperty, arguments.first)
+                               v.add("\} else \{")
+                               var value = v.expr(nexpr, self.mpropdef.static_mtype)
+                               v.write_attribute(self.mpropdef.mproperty, arguments.first, value)
+                               v.assign(res, value)
+                               if not useiset then
+                                       var true_v = v.new_expr("1", v.bool_type)
+                                       v.write_attribute(guard, arguments.first, true_v)
+                               end
+                               v.add("\}")
+                       else
+                               res = v.read_attribute(self.mpropdef.mproperty, arguments.first)
+                       end
                        v.assign(v.frame.returnvar.as(not null), res)
                else if mpropdef == mwritepropdef then
                        assert arguments.length == 2
                        v.write_attribute(self.mpropdef.mproperty, arguments.first, arguments[1])
+                       if is_lazy then
+                               var ret = self.mpropdef.static_mtype
+                               var useiset = ret.ctype == "val*" and not ret isa MNullableType
+                               if not useiset then
+                                       v.write_attribute(self.mlazypropdef.mproperty, arguments.first, v.new_expr("1", v.bool_type))
+                               end
+                       end
                else
                        abort
                end
@@ -2136,7 +2169,7 @@ redef class AAttrPropdef
        fun init_expr(v: AbstractCompilerVisitor, recv: RuntimeVariable)
        do
                var nexpr = self.n_expr
-               if nexpr != null then
+               if nexpr != null and not is_lazy then
                        var oldnode = v.current_node
                        v.current_node = self
                        var old_frame = v.frame