A big set of loosely coupled but related changed on the annotations on attributes and methods.
Here is a summary of the changes on the user-side:
* No more special case for the kind of classes, so you can use `autoinit` in interfaces.
* Explicit annotation `autoinit` is understood on attributes and is the default on value-less concrete attribute.
* Abstract attributes are `noautoinit` by default, if `autoinit` is given, it is applied on the setter. This way abstract attributes are basically just a couple of getter-setter. close #1311
This way there is less special cases and behaviors. Still more work is required to finish #1322.
Pull-Request: #1433
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Romain Chanoir <chanoir.romain@courrier.uqam.ca>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
var res
if is_lazy then
var set
- var ret = self.mpropdef.static_mtype
+ var ret = self.mtype
var useiset = not ret.is_c_primitive and not ret isa MNullableType
var guard = self.mlazypropdef.mproperty
if useiset 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 ret = self.mtype
var useiset = not ret.is_c_primitive and not ret isa MNullableType
if not useiset then
v.write_attribute(self.mlazypropdef.mproperty, arguments.first, v.bool_instance(true))
var oldnode = v.current_node
v.current_node = self
var old_frame = v.frame
- var frame = new StaticFrame(v, self.mpropdef.as(not null), recv.mcasttype.undecorate.as(MClassType), [recv])
+ var frame = new StaticFrame(v, self.mreadpropdef.as(not null), recv.mcasttype.undecorate.as(MClassType), [recv])
v.frame = frame
var value
- var mtype = self.mpropdef.static_mtype
+ var mtype = self.mtype
assert mtype != null
var nexpr = self.n_expr
do
if is_lazy then return
if has_value then
- var f = v.new_frame(self, mpropdef.as(not null), [recv])
+ var f = v.new_frame(self, mreadpropdef.as(not null), [recv])
evaluate_expr(v, recv, f)
return
end
var mpropdef = self.mpropdef
if mpropdef == null then return
- var mtype = mpropdef.static_mtype.as(not null)
+ var mtype = self.mtype.as(not null)
mtype = mtype.anchor_to(v.mainmodule, recv.mtype.as(MClassType))
if mtype isa MNullableType then
v.write_attribute(self.mpropdef.mproperty, recv, v.null_instance)
return
end
- # Is the class forbid constructors?
- if not mclassdef.mclass.kind.need_init then return
-
# Is there already a constructor defined?
var defined_init: nullable MMethodDef = null
for mpropdef in mclassdef.mpropdefs do
var initializers = new Array[MProperty]
for npropdef in nclassdef.n_propdefs do
if npropdef isa AMethPropdef then
+ if not npropdef.is_autoinit then continue # Skip non tagged autoinit
if npropdef.mpropdef == null then return # Skip broken method
- var at = npropdef.get_single_annotation("autoinit", self)
- if at == null then continue # Skip non tagged init
-
var sig = npropdef.mpropdef.msignature
if sig == null then continue # Skip broken method
- if not npropdef.mpropdef.is_intro then
- self.error(at, "Error: `autoinit` cannot be set on redefinitions.")
- continue
- end
-
for param in sig.mparameters do
var ret_type = param.mtype
var mparameter = new MParameter(param.name, ret_type, false, ret_type isa MNullableType)
redef class AMethPropdef
redef type MPROPDEF: MMethodDef
+ # Is the method annotated `autoinit`?
+ var is_autoinit = false
# Can self be used as a root init?
private fun look_like_a_root_init(modelbuilder: ModelBuilder, mclassdef: MClassDef): Bool
# Check annotations
var at = self.get_single_annotation("lazy", modelbuilder)
if at != null then modelbuilder.error(at, "Syntax Error: `lazy` must be used on attributes.")
+
+ var atautoinit = self.get_single_annotation("autoinit", modelbuilder)
+ if atautoinit != null then
+ if not mpropdef.is_intro then
+ modelbuilder.error(atautoinit, "Error: `autoinit` cannot be set on redefinitions.")
+ else if not mclassdef.is_intro then
+ modelbuilder.error(atautoinit, "Error: `autoinit` cannot be used in class refinements.")
+ else
+ self.is_autoinit = true
+ end
+ end
end
redef fun check_signature(modelbuilder)
redef class AAttrPropdef
redef type MPROPDEF: MAttributeDef
+ # The static type of the property (declared, inferred or inherited)
+ # This attribute is also used to check if the property was analyzed and is valid.
+ var mtype: nullable MType
+
# Is the node tagged `noinit`?
var noinit = false
return
end
if atabstract != null then
- modelbuilder.error(atnoinit, "Error: `noautoinit` attributes cannot be abstract.")
- return
+ modelbuilder.warning(atnoinit, "useless-noautoinit", "Warning: superfluous `noautoinit` on abstract attribute.")
end
end
modelbuilder.mpropdef2npropdef[mwritepropdef] = self
mwritepropdef.mdoc = mreadpropdef.mdoc
if atabstract != null then mwritepropdef.is_abstract = true
+
+ var atautoinit = self.get_single_annotation("autoinit", modelbuilder)
+ if atautoinit != null then
+ if has_value then
+ modelbuilder.error(atautoinit, "Error: `autoinit` attributes cannot have an initial value.")
+ else if not mwritepropdef.is_intro then
+ modelbuilder.error(atautoinit, "Error: `autoinit` attributes cannot be set on redefinitions.")
+ else if not mclassdef.is_intro then
+ modelbuilder.error(atautoinit, "Error: `autoinit` attributes cannot be used in class refinements.")
+ else if atabstract == null then
+ modelbuilder.warning(atautoinit, "useless-autoinit", "Warning: superfluous `autoinit` on attribute.")
+ end
+ else if atabstract != null then
+ # By default, abstract attribute are not autoinit
+ noinit = true
+ end
end
redef fun build_signature(modelbuilder)
return
end
+ self.mtype = mtype
+
if mpropdef != null then
mpropdef.static_mtype = mtype
end
var mpropdef = self.mpropdef
if mpropdef == null then return # Error thus skipped
var ntype = self.n_type
- var mtype = self.mpropdef.static_mtype
+ var mtype = self.mtype
if mtype == null then return # Error thus skipped
var mclassdef = mpropdef.mclassdef
for npropdef in modelbuilder.collect_attr_propdef(cd) do
if not npropdef.has_value then continue
- var mpropdef = npropdef.mpropdef.as(not null)
+ var mpropdef = npropdef.mreadpropdef.as(not null)
var v = new RapidTypeVisitor(self, bound_mtype, mpropdef)
v.enter_visit(npropdef.n_expr)
v.enter_visit(npropdef.n_block)
do
if not has_value then return
- var mpropdef = self.mpropdef
- if mpropdef == null then return # skip error
+ var mpropdef = self.mreadpropdef
+ if mpropdef == null or mpropdef.msignature == null then return # skip error
var v = new TypeVisitor(modelbuilder, mpropdef.mclassdef.mmodule, mpropdef)
self.selfvariable = v.selfvariable
var nexpr = self.n_expr
if nexpr != null then
- var mtype = self.mpropdef.static_mtype
+ var mtype = self.mtype
v.visit_expr_subtype(nexpr, mtype)
end
var nblock = self.n_block
class C
super B
redef fun foo: Int do return 100
- redef fun bar=(i: Int) do i.output
+ redef fun bar=(i: Int) do
+ super
+ i.output
+ end
redef fun baz: Int do return 400
- redef fun baz=(i: Int) do i.output
+ redef fun baz=(i: Int) do
+ super
+ i.output
+ end
end
var a = new A
import kernel
-interface Foo
+class Foo
var a: Object is abstract
- #alt1#var b = 1 is abstract
- #alt2#var b is abstract, noautoinit
+ var b: Object = 10 is abstract
+ #alt1#var b is abstract, noautoinit
+ #alt1#var c = 1 is abstract, lazy
+ #alt1#var d = 1 is abstract, autoinit
+ #alt1#var e = 1 is abstract, readonly
end
class Bar
super Foo
redef var a
+ redef var b is noinit
end
class Baz
super Foo
- redef fun a do return 100
- redef fun a=(x) do (101).output
-end
-
-class FooBar
- super Foo
+ redef fun a do return 100 #alt2#
+ redef fun a=(x) do (101).output #alt3#
+ redef fun b do return 200 #alt4#
+ redef fun b=(x) do (201).output #alt5#
end
var f: Foo = new Bar(1)
f.a = 2
f.a.output
+'\n'.output
+
+f.b.output
+f.b = 20
+f.b.output
+
+'\n'.output
+
f = new Baz
f.a.output
f.a = 3
f.a.output
-f = new FooBar
-#alt3#f.a.output
-#alt4#f.a = 4
+'\n'.output
+
+f.b.output
+f.b = 30
+f.b.output
abstract class A
var x: Int
- var y: Int is abstract
+ var y: Int is abstract, autoinit
end
class B
--- /dev/null
+# 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 standard::kernel
+
+interface A
+ var i: Int is abstract, autoinit
+ fun j: Int is abstract, autoinit
+ fun j=(o: Int) is abstract, autoinit
+end
+
+class B
+ super A
+ var k: Int is abstract, autoinit
+ fun l: Int is abstract, autoinit
+ fun l=(o: Int) is abstract, autoinit
+end
+
+class C
+ super B
+ redef fun i do
+ 'i'.output
+ return 1
+ end
+ redef fun i=(o) do
+ 'i'.output
+ '='.output
+ o.output
+ end
+ redef fun j do
+ 'j'.output
+ return 2
+ end
+ redef fun j=(o) do
+ 'j'.output
+ '='.output
+ o.output
+ end
+ redef fun k do
+ 'k'.output
+ return 3
+ end
+ redef fun k=(o)
+ do
+ 'k'.output
+ '='.output
+ o.output
+ end
+ redef fun l do
+ 'l'.output
+ return 4
+ end
+ redef fun l=(o) do
+ 'l'.output
+ '='.output
+ o.output
+ end
+end
+
+var c = new C(10,20,30,40)
+'\n'.output
+c.i.output
+c.j.output
+c.k.output
+c.l.output
--- /dev/null
+# 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 standard::kernel
+
+interface A
+ var i: Int is abstract
+ fun j: Int is abstract
+ fun j=(o: Int) is abstract
+end
+
+class B
+ super A
+ var k: Int is abstract
+ fun l: Int is abstract
+ fun l=(o: Int) is abstract
+end
+
+class C
+ super B
+ redef fun i do
+ 'i'.output
+ return 1
+ end
+ redef fun i=(o) do
+ 'i'.output
+ '='.output
+ o.output
+ end
+ redef fun j do
+ 'j'.output
+ return 2
+ end
+ redef fun j=(o) do
+ 'j'.output
+ '='.output
+ o.output
+ end
+ redef fun k do
+ 'k'.output
+ return 3
+ end
+ redef fun k=(o)
+ do
+ 'k'.output
+ '='.output
+ o.output
+ end
+ redef fun l do
+ 'l'.output
+ return 4
+ end
+ redef fun l=(o) do
+ 'l'.output
+ '='.output
+ o.output
+ end
+end
+
+var c = new C
+c.i.output
+c.j.output
+c.k.output
+c.l.output
--- /dev/null
+# 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 standard::kernel
+
+class A
+ var a: Object is
+ #alt2# noautoinit
+ #alt3# autoinit
+ #alt4# lazy
+ #alt5# readonly
+ #alt6# abstract
+ #alt7# lateinit
+ writable
+ end #1alt1# do return 1
+end
+
+class B
+ super A
+end
+
+var b = new B(1) #alt1,2,4,5,6,7# var b = new B
+b.a.output
--- /dev/null
+# 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 standard::kernel
+
+class A
+ var i: Int = 1
+end
+
+class B
+ super A
+ redef fun i=(v)
+ do
+ super
+ 'i'.output
+ v.output
+ end
+end
+
+var a = new A
+a.i.output
+
+'\n'.output
+
+var b = new B
+b.i.output
-alt/base_attr4_alt1.nit:40,3--5: Error: method `foo=` does not exists in `A`.
+alt/base_attr4_alt1.nit:46,3--5: Error: method `foo=` does not exists in `A`.
-alt/base_attr4_alt2.nit:43,3--5: Error: method `bar` does not exists in `A`.
+alt/base_attr4_alt2.nit:49,3--5: Error: method `bar` does not exists in `A`.
-1
-2
-100
-101
-100
+base_attr_abstract.nit:19,24--31: Error: `abstract` attributes cannot have an initial value.
+base_attr_abstract.nit:37,12--13: Error: no property `Baz::b=` is inherited. Remove the `redef` keyword to define a new property.
+base_attr_abstract.nit:37,15: Error: untyped parameter `x'.
--- /dev/null
+i=10
+jj=20
+k=30
+ll=40
+
+i1
+j2
+k3
+l4
--- /dev/null
+i1
+j2
+k3
+l4
-alt/base_attr_abstract_alt1.nit:19,15--22: Error: `abstract` attributes cannot have an initial value.
+alt/base_attr_abstract_alt1.nit:19,24--31: Error: `abstract` attributes cannot have an initial value.
+alt/base_attr_abstract_alt1.nit:20,6: Error: a property `b` is already defined in class `Foo` at line 19.
+alt/base_attr_abstract_alt1.nit:21,15--22: Error: `abstract` attributes cannot have an initial value.
+alt/base_attr_abstract_alt1.nit:22,15--22: Error: `abstract` attributes cannot have an initial value.
+alt/base_attr_abstract_alt1.nit:23,15--22: Error: `abstract` attributes cannot have an initial value.
+alt/base_attr_abstract_alt1.nit:37,12--13: Error: no property `Baz::b=` is inherited. Remove the `redef` keyword to define a new property.
+alt/base_attr_abstract_alt1.nit:37,15: Error: untyped parameter `x'.
-alt/base_attr_abstract_alt2.nit:20,6: Error: untyped attribute `base_attr_abstract_alt2#Foo#b`.
-alt/base_attr_abstract_alt2.nit:20,21--30: Error: `noautoinit` attributes cannot be abstract.
+alt/base_attr_abstract_alt2.nit:19,24--31: Error: `abstract` attributes cannot have an initial value.
+alt/base_attr_abstract_alt2.nit:37,12--13: Error: no property `Baz::b=` is inherited. Remove the `redef` keyword to define a new property.
+alt/base_attr_abstract_alt2.nit:37,15: Error: untyped parameter `x'.
-Runtime error: Abstract method `a` called on `FooBar` (alt/base_attr_abstract_alt3.nit:18)
-1
-2
-100
-101
-100
+alt/base_attr_abstract_alt3.nit:19,24--31: Error: `abstract` attributes cannot have an initial value.
+alt/base_attr_abstract_alt3.nit:37,12--13: Error: no property `Baz::b=` is inherited. Remove the `redef` keyword to define a new property.
+alt/base_attr_abstract_alt3.nit:37,15: Error: untyped parameter `x'.
-Runtime error: Abstract method `a=` called on `FooBar` (alt/base_attr_abstract_alt4.nit:18)
-1
-2
-100
-101
-100
+alt/base_attr_abstract_alt4.nit:19,24--31: Error: `abstract` attributes cannot have an initial value.
+alt/base_attr_abstract_alt4.nit:37,12--13: Error: no property `Baz::b=` is inherited. Remove the `redef` keyword to define a new property.
+alt/base_attr_abstract_alt4.nit:37,15: Error: untyped parameter `x'.
--- /dev/null
+alt/base_attr_abstract_alt5.nit:19,24--31: Error: `abstract` attributes cannot have an initial value.
--- /dev/null
+alt/base_attr_annot_1alt1.nit:33,9--11: Error: expected 0 argument(s) for `init`; got 1. See introduction at `standard::Object::init`.
--- /dev/null
+alt/base_attr_annot_1alt1_alt2.nit:19,3--12: Error: `noautoinit` attributes cannot have an initial value.
--- /dev/null
+alt/base_attr_annot_1alt1_alt3.nit:19,3--20,10: Error: `autoinit` attributes cannot have an initial value.
--- /dev/null
+alt/base_attr_annot_1alt1_alt6.nit:19,3--23,10: Error: `abstract` attributes cannot have an initial value.
--- /dev/null
+alt/base_attr_annot_alt1.nit:33,9--11: Error: expected 1 argument(s) for `init(a: Object)`; got 0. See introduction at `standard::Object::init`.
--- /dev/null
+Runtime error: Uninitialized attribute _a (alt/base_attr_annot_alt2.nit:18)
--- /dev/null
+alt/base_attr_annot_alt3.nit:19,3--20,10: Warning: superfluous `autoinit` on attribute.
+1
--- /dev/null
+alt/base_attr_annot_alt4.nit:19,3--21,6: Error: `lazy` attributes need a value.
--- /dev/null
+alt/base_attr_annot_alt5.nit:19,3--22,10: Error: `readonly` attributes need a value.
--- /dev/null
+Runtime error: Abstract method `a` called on `B` (alt/base_attr_annot_alt6.nit:18)
--- /dev/null
+alt/base_attr_annot_alt7.nit:19,3--24,10: Error: `lateinit` attributes need a value.
+../lib/standard/kernel.nit:24,1--95,3: Error: `kernel#Object` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
../lib/standard/kernel.nit:97,1--111,3: Error: `kernel#Sys` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+../lib/standard/kernel.nit:124,1--182,3: Error: `kernel#Comparable` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+../lib/standard/kernel.nit:184,1--221,3: Error: `kernel#Discrete` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+../lib/standard/kernel.nit:223,1--240,3: Error: `kernel#Cloneable` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+../lib/standard/kernel.nit:242,1--297,3: Error: `kernel#Numeric` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+../lib/standard/kernel.nit:303,1--326,3: Error: `kernel#Bool` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+../lib/standard/kernel.nit:328,1--410,3: Error: `kernel#Float` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+../lib/standard/kernel.nit:412,1--514,3: Error: `kernel#Byte` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+../lib/standard/kernel.nit:516,1--707,3: Error: `kernel#Int` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+../lib/standard/kernel.nit:709,1--849,3: Error: `kernel#Char` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+../lib/standard/kernel.nit:851,1--858,3: Error: `kernel#Pointer` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
--- /dev/null
+Runtime error: Uninitialized attribute _a (alt/base_attr_annot_alt2.nit:34)