Merge: understand writable as an annotation
authorJean Privat <jean@pryen.org>
Tue, 22 Jul 2014 03:17:01 +0000 (23:17 -0400)
committerJean Privat <jean@pryen.org>
Tue, 22 Jul 2014 03:17:01 +0000 (23:17 -0400)
~~~.rb
class Toto
   var x: Int writable = 5 # before
   var y: Int = 5 is writable # after
~~~

This should become the new way, so while an active migration is not needed yet, once this PR is merger, new code should use the new notation.

Bonus: writable accepts an optional agrument that is the name of the writer.
This allows the reserve the name `foo=` for high-level setters.

Eg.
~~~.rb
class Toto
   var x: Int is private writable(set_x) # generates `set_x` instead of `x=`
   fun x=(v: Int) do # `x=` is feee, so I can use it for a distinct method
      assert x >= 0
      set_x(v) # I use the generated `set_x` as a private internal setter
   end
end
~~~

Pull-Request: #601
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>

22 files changed:
src/annotation.nit
src/modelize_property.nit
tests/base_attr2.nit
tests/base_attr4.nit
tests/base_attr5.nit
tests/base_attr6.nit
tests/base_attr7.nit
tests/base_attr_named_setters.nit [new file with mode: 0644]
tests/base_prot_sig.nit
tests/base_prot_sig2.nit
tests/base_virtual_type.nit
tests/base_virtual_type2.nit
tests/base_virtual_type3.nit
tests/base_virtual_type6.nit
tests/base_virtual_type7.nit
tests/sav/base_attr_named_setters.res [new file with mode: 0644]
tests/sav/base_attr_named_setters_alt1.res [new file with mode: 0644]
tests/sav/base_attr_named_setters_alt2.res [new file with mode: 0644]
tests/sav/base_attr_named_setters_alt3.res [new file with mode: 0644]
tests/sav/base_attr_named_setters_alt4.res [new file with mode: 0644]
tests/sav/base_prot_sig_alt7.res
tests/test_gen_inh.nit

index d4a13ac..a0d397e 100644 (file)
@@ -84,6 +84,20 @@ redef class AAnnotation
                modelbuilder.error(self, "Annotation error: \"{name}\" expects a single Int as argument.")
                return null
        end
+
+       # Get the single argument of `self` as an identifier.
+       # Raise error and return null on any inconsistency.
+       fun arg_as_id(modelbuilder: ModelBuilder): nullable String
+       do
+               var args = n_args
+               if args.length == 1 then
+                       var arg = args.first.as_id
+                       if arg != null then return arg
+               end
+
+               modelbuilder.error(self, "Annotation error: \"{name}\" expects a single identifier as argument.")
+               return null
+       end
 end
 
 redef class AAtArg
index 04e022f..b618676 100644 (file)
@@ -720,13 +720,22 @@ redef class AAttrPropdef
 
                        var writename = name + "="
                        var nwritable = self.n_writable
+                       var atwritable = self.get_single_annotation("writable", modelbuilder)
+                       if atwritable != null then
+                               if not atwritable.n_args.is_empty then
+                                       writename = atwritable.arg_as_id(modelbuilder) or else writename
+                               end
+                       end
                        var mwriteprop = modelbuilder.try_get_mproperty_by_name(nid2, mclassdef, writename).as(nullable MMethod)
                        var nwkwredef: nullable Token = null
                        if nwritable != null then nwkwredef = nwritable.n_kwredef
+                       if atwritable != null then nwkwredef = atwritable.n_kwredef
                        if mwriteprop == null then
                                var mvisibility
                                if nwritable != null then
                                        mvisibility = new_property_visibility(modelbuilder, mclassdef, nwritable.n_visibility)
+                               else if atwritable != null then
+                                       mvisibility = new_property_visibility(modelbuilder, mclassdef, atwritable.n_visibility)
                                else
                                        mvisibility = private_visibility
                                end
@@ -736,6 +745,8 @@ redef class AAttrPropdef
                                if not self.check_redef_keyword(modelbuilder, mclassdef, nwkwredef or else n_kwredef, true, mwriteprop) then return
                                if nwritable != null then
                                        check_redef_property_visibility(modelbuilder, nwritable.n_visibility, mwriteprop)
+                               else if atwritable != null then
+                                       check_redef_property_visibility(modelbuilder, atwritable.n_visibility, mwriteprop)
                                end
                        end
                        mclassdef.mprop2npropdef[mwriteprop] = self
index 204b0c9..03c8413 100644 (file)
@@ -19,17 +19,17 @@ class A
        protected var a2: Object = self
        private var a3: Object = self
 
-       var a4: Object writable = self
-       protected var a5: Object writable = self
-       private var a6: Object writable = self
+       var a4: Object = self is writable
+       protected var a5: Object = self is writable
+       private var a6: Object = self is writable
 
-       var a7: Object protected writable = self
-       protected var a8: Object protected writable = self
-       private var a9: Object protected writable = self
+       var a7: Object = self is protected writable
+       protected var a8: Object = self is protected writable
+       private var a9: Object = self is protected writable
 
-       var a10: Object private writable = self
-       protected var a11: Object private writable = self
-       private var a12: Object private writable = self
+       var a10: Object = self is private writable
+       protected var a11: Object = self is private writable
+       private var a12: Object = self is private writable
 
        var cpt: Int = 0
 
index f7bf6a7..b8f02dc 100644 (file)
@@ -24,8 +24,8 @@ end
 class B
        super A
        redef var foo: Int = 20
-       var bar: Int redef writable = 30
-       redef var baz: Int redef writable = 40
+       var bar: Int = 30 is redef writable
+       redef var baz: Int = 40 is redef writable
 end
 
 class C
index 56c88da..8bb4171 100644 (file)
@@ -33,24 +33,24 @@ class B
        super A
        #alt1#var foo: Int = 10
        #alt2#redef var foo: Int = 10
-       #alt3#var foo: Int writable = 10
-       #alt4#redef var foo: Int writable = 10
-       #alt5#var foo: Int redef writable = 10
-       #alt6#redef var foo: Int redef writable = 10
+       #alt3#var foo: Int = 10 is writable
+       #alt4#redef var foo: Int = 10 is writable
+       #alt5#var foo: Int = 10 is redef writable
+       #alt6#redef var foo: Int = 10 is redef writable
        #alt7#redef var foo
        #alt11#var bar: Int = 20
        #alt12#redef var bar: Int = 20
-       #alt13#var bar: Int writable = 20
-       #alt14#redef var bar: Int writable = 20
-       #alt15#var bar: Int redef writable = 20
-       #alt16#redef var bar: Int redef writable = 20
+       #alt13#var bar: Int = 20 is writable
+       #alt14#redef var bar: Int = 20 is writable
+       #alt15#var bar: Int = 20 is redef writable
+       #alt16#redef var bar: Int = 20 is redef writable
        #alt17#redef var bar
        #alt21#var baz: Int = 30
        #alt22#redef var baz: Int = 30
-       #alt23#var baz: Int writable = 30
-       #alt24#redef var baz: Int writable = 30
-       #alt25#var baz: Int redef writable = 30
-       #alt26#redef var baz: Int redef writable = 30
+       #alt23#var baz: Int = 30 is writable
+       #alt24#redef var baz: Int = 30 is writable
+       #alt25#var baz: Int = 30 is redef writable
+       #alt26#redef var baz: Int = 30 is redef writable
        #alt27#redef var baz
 end
 
index a83f792..03fe206 100644 (file)
@@ -37,7 +37,7 @@ class B
                i.output
                super(i+30)
        end
-       redef var vaz: Int redef writable = 40
+       redef var vaz: Int = 40 is redef writable
 end
 
 var b = new B
index c3605cc..2aec253 100644 (file)
@@ -32,8 +32,8 @@ end
 class B
        super A
        #alt1#redef var foo: Bool = true
-       #alt2#var bar: Bool redef writable = true
-       #alt3#redef var baz: Bool redef writable = true
+       #alt2#var bar: Bool = true is redef writable
+       #alt3#redef var baz: Bool = true is redef writable
 end
 
 var b = new B
diff --git a/tests/base_attr_named_setters.nit b/tests/base_attr_named_setters.nit
new file mode 100644 (file)
index 0000000..136c740
--- /dev/null
@@ -0,0 +1,67 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+class A
+       fun foo: Int do return 1
+       fun set_bar(i: Int) do i.output
+       fun baz: Int do return 4
+       fun set_baz(i: Int) do i.output
+       fun zz do end
+end
+
+class B
+       super A
+       redef var foo: Int = 20 is writable(set_foo)
+       var bar: Int = 30 is redef writable(set_bar)
+       redef var baz: Int = 40 is writable(set_baz)
+       #alt2#var z: Int is writable(set_baz)
+       #alt3#var z: Int is writable(zz)
+       #alt4#var z: Int is redef writable(zz)
+end
+
+class C
+       super B
+       fun foo=(i: Int) do set_foo(i)
+       fun bar=(i: Int) do set_bar(i)
+       fun baz=(i: Int) do set_baz(i)
+end
+
+var a = new A
+a.foo.output
+a.set_bar 2
+a.set_baz 3
+a.baz.output
+
+'\n'.output
+
+var b = new B
+b.set_foo 10
+#alt1#b.foo = 10
+b.foo.output
+b.set_bar 20
+b.bar.output
+b.set_baz 30
+b.baz.output
+
+'\n'.output
+
+var c = new C
+c.foo = 100
+c.foo.output
+c.bar = 200
+c.bar.output
+c.baz = 300
+c.baz.output
index 1adc321..f78b9b5 100644 (file)
@@ -18,24 +18,24 @@ class A
        protected fun proA(a: A) do end
        private fun priA(a: A) do end
 
-       var vpubA: nullable A writable
-       protected var vproA: nullable A protected writable
+       var vpubA: nullable A is writable
+       protected var vproA: nullable A is protected writable
        private var vpriA: nullable A
 
-       var vpubA2 writable = new A
-       protected var vproA2 protected writable = new A
+       var vpubA2 = new A is writable
+       protected var vproA2 = new A is protected writable
        private var vpriA2 = new A
 
        #alt1#fun pubB(a: B) do end
        #alt2#protected fun proB(a: B) do end
        private fun priB(a: B) do end
 
-       #alt3#var vpubB: nullable B writable
-       #alt4#protected var vproB: nullable B protected writable
+       #alt3#var vpubB: nullable B is writable
+       #alt4#protected var vproB: nullable B is protected writable
        private var vpriB: nullable B
 
-       #alt5#var vpubB2 writable = new B
-       #alt6#protected var vproB2 protected writable = new B
+       #alt5#var vpubB2 = new B is writable
+       #alt6#protected var vproB2 = new B is protected writable
        private var vpriB2 = new B
 
        init do end
@@ -46,24 +46,24 @@ private class B
        #alt7#protected fun proA(a: A) do end
        private fun priA(a: A) do end
 
-       var vpubA: nullable A writable
-       #alt7#protected var vproA: nullable A protected writable
+       var vpubA: nullable A is writable
+       #alt7#protected var vproA: nullable A is protected writable
        private var vpriA: nullable A
 
-       var vpubA2 writable = new A
-       #alt7#protected var vproA2 protected writable = new A
+       var vpubA2 = new A is writable
+       #alt7#protected var vproA2 = new A is protected writable
        private var vpriA2 = new A
 
        fun pubB(a: B) do end
        #alt7#protected fun proB(a: B) do end
        private fun priB(a: B) do end
 
-       var vpubB: nullable B writable
-       #alt7#protected var vproB: nullable B protected writable
+       var vpubB: nullable B is writable
+       #alt7#protected var vproB: nullable B is protected writable
        private var vpriB: nullable B
 
-       var vpubB2 writable = new B
-       #alt7#protected var vproB2 protected writable = new B
+       var vpubB2 = new B is writable
+       #alt7#protected var vproB2 = new B is protected writable
        private var vpriB2 = new B
 
        init do end
index 9009a88..89fff9e 100644 (file)
@@ -20,12 +20,12 @@ class C
        #alt2#protected fun proA(a: A) do end
        private fun priA(a: A) do end
 
-       #alt3#var vpubA: nullable A writable
-       #alt4#protected var vproA: nullable A protected writable
+       #alt3#var vpubA: nullable A is writable
+       #alt4#protected var vproA: nullable A is protected writable
        private var vpriA: nullable A
 
-       #alt5#var vpubA2 writable = new A
-       #alt6#protected var vproA2 protected writable = new A
+       #alt5#var vpubA2 = new A is writable
+       #alt6#protected var vproA2 = new A is protected writable
        private var vpriA2 = new A
 
        init do end
@@ -35,10 +35,10 @@ private class D
        fun pubA(a: A) do end
        private fun priA(a: A) do end
 
-       var vpubA: nullable A writable
+       var vpubA: nullable A is writable
        private var vpriA: nullable A
 
-       var vpubA2 writable = new A
+       var vpubA2 = new A is writable
        private var vpriA2 = new A
 
        init do end
index 2f2a73f..277cc6d 100644 (file)
@@ -19,7 +19,7 @@ import kernel
 class A
        type E: T
 
-       var e: nullable E writable = null
+       var e: nullable E = null is writable
 end
 
 class B
index af6da5c..5f86a26 100644 (file)
@@ -19,7 +19,7 @@ import kernel
 class A
        type E: T
        
-       var e: nullable E writable = null
+       var e: nullable E = null is writable
 end
 
 class B
index 6f66799..545092f 100644 (file)
@@ -19,7 +19,7 @@ import base_virtual_type2
 
 class C
        super A
-       var tab: nullable Array[E] writable
+       var tab: nullable Array[E] is writable
        init do end
 end
 
index 4d5ce65..07d5fda 100644 (file)
@@ -20,9 +20,9 @@ class G[E]
        type F: E
        type F2: F
 
-       var e: E writable
-       var f: F writable
-       var f2: F2 writable
+       var e: E is writable
+       var f: F is writable
+       var f2: F2 is writable
 
        init(e: E, f: F, f2: F2)
        do
index b4a79d0..76fd5dc 100644 (file)
@@ -19,7 +19,7 @@ import kernel
 class A
        type E: F
        type F: E
-       var e: nullable E writable = null
+       var e: nullable E = null is writable
        init do end
 end
 
diff --git a/tests/sav/base_attr_named_setters.res b/tests/sav/base_attr_named_setters.res
new file mode 100644 (file)
index 0000000..9e263e5
--- /dev/null
@@ -0,0 +1,12 @@
+1
+2
+3
+4
+
+10
+20
+30
+
+100
+200
+300
diff --git a/tests/sav/base_attr_named_setters_alt1.res b/tests/sav/base_attr_named_setters_alt1.res
new file mode 100644 (file)
index 0000000..cf8d660
--- /dev/null
@@ -0,0 +1 @@
+alt/base_attr_named_setters_alt1.nit:52,1--10: Error: Method 'foo=' doesn't exists in B.
diff --git a/tests/sav/base_attr_named_setters_alt2.res b/tests/sav/base_attr_named_setters_alt2.res
new file mode 100644 (file)
index 0000000..ada80a6
--- /dev/null
@@ -0,0 +1 @@
+alt/base_attr_named_setters_alt2.nit:30,6: Error: A property set_baz is already defined in class B at line 29.
diff --git a/tests/sav/base_attr_named_setters_alt3.res b/tests/sav/base_attr_named_setters_alt3.res
new file mode 100644 (file)
index 0000000..ed64fb8
--- /dev/null
@@ -0,0 +1 @@
+alt/base_attr_named_setters_alt3.nit:31,6: Redef error: B::zz is an inherited property. To redefine it, add the redef keyword.
diff --git a/tests/sav/base_attr_named_setters_alt4.res b/tests/sav/base_attr_named_setters_alt4.res
new file mode 100644 (file)
index 0000000..9409278
--- /dev/null
@@ -0,0 +1 @@
+alt/base_attr_named_setters_alt4.nit:32,9--11: Redef Error: 1 parameters found, 0 expected. Signature is base_attr_named_setters_alt4#B#zz
index 18547d4..a5c0088 100644 (file)
@@ -1,10 +1,10 @@
 alt/base_prot_sig_alt7.nit:46,2--10: Error: The only legal visibility for properties in a private class is private.
 alt/base_prot_sig_alt7.nit:50,2--10: Error: The only legal visibility for properties in a private class is private.
-alt/base_prot_sig_alt7.nit:50,34--42: Error: The only legal visibility for properties in a private class is private.
+alt/base_prot_sig_alt7.nit:50,37--45: Error: The only legal visibility for properties in a private class is private.
 alt/base_prot_sig_alt7.nit:54,2--10: Error: The only legal visibility for properties in a private class is private.
-alt/base_prot_sig_alt7.nit:54,23--31: Error: The only legal visibility for properties in a private class is private.
+alt/base_prot_sig_alt7.nit:54,34--42: Error: The only legal visibility for properties in a private class is private.
 alt/base_prot_sig_alt7.nit:58,2--10: Error: The only legal visibility for properties in a private class is private.
 alt/base_prot_sig_alt7.nit:62,2--10: Error: The only legal visibility for properties in a private class is private.
-alt/base_prot_sig_alt7.nit:62,34--42: Error: The only legal visibility for properties in a private class is private.
+alt/base_prot_sig_alt7.nit:62,37--45: Error: The only legal visibility for properties in a private class is private.
 alt/base_prot_sig_alt7.nit:66,2--10: Error: The only legal visibility for properties in a private class is private.
-alt/base_prot_sig_alt7.nit:66,23--31: Error: The only legal visibility for properties in a private class is private.
+alt/base_prot_sig_alt7.nit:66,34--42: Error: The only legal visibility for properties in a private class is private.
index 24b69e2..cc99b1e 100644 (file)
@@ -33,8 +33,8 @@ end
 
 class Gen3[H: Int]
        super Gen1[H, Char]
-   redef var e: H redef writable
-   redef var f_: Char redef writable = 'N'
+   redef var e: H is redef writable
+   redef var f_: Char = 'N' is redef writable
    redef fun f: Char do return f_ end
    redef fun f=(x: Char) do f_ = x end