The problem was a caching of a non-final information.
collect_things visit the mclassdefs of the module but they may not all
be analyzed (ie. their super-types not all identified)
To solve this we build the model in one more pass:
- a pass to assign the super-types to each mclassdef
- a pass to build the mclassdef hierarchy
a test file is added to prevent regressions.
Reported-by: Alexis Laferrière <alexis.laf@xymus.net>
Signed-off-by: Jean Privat <jean@pryen.org>
# FIXME: quite ugly but not better idea yet
var supertypes: Array[MClassType] = new Array[MClassType]
- # Register the super-types for the class (ie "super SomeType")
- # This function can only invoked once by class
+ # Register some super-types for the class (ie "super SomeType")
+ #
+ # The hierarchy must not already be set
+ # REQUIRE: self.in_hierarchy == null
fun set_supertypes(supertypes: Array[MClassType])
do
assert unique_invocation: self.in_hierarchy == null
var mmodule = self.mmodule
var model = mmodule.model
- var res = model.mclassdef_hierarchy.add_node(self)
- self.in_hierarchy = res
var mtype = self.bound_mtype
for supertype in supertypes do
end
end
+ end
+
+ # Collect the super-types (set by set_supertypes) to build the hierarchy
+ #
+ # This function can only invoked once by class
+ # REQUIRE: self.in_hierarchy == null
+ # ENSURE: self.in_hierarchy != null
+ fun add_in_hierarchy
+ do
+ assert unique_invocation: self.in_hierarchy == null
+ var model = mmodule.model
+ var res = model.mclassdef_hierarchy.add_node(self)
+ self.in_hierarchy = res
+ var mtype = self.bound_mtype
+
+ # Here we need to connect the mclassdef to its pairs in the mclassdef_hierarchy
+ # The simpliest way is to attach it to collect_mclassdefs
for mclassdef in mtype.collect_mclassdefs(mmodule) do
res.poset.add_edge(self, mclassdef)
end
end
end
- # Visit the AST and set the super-types of the MClass objects (ie compute the inheritance)
- private fun build_a_mclassdef_inheritance(nmodule: AModule, nclassdef: AClassdef)
+ # Visit the AST and set the super-types of the MClassdef objects
+ private fun collect_a_mclassdef_inheritance(nmodule: AModule, nclassdef: AClassdef)
do
var mmodule = nmodule.mmodule.as(not null)
var objectclass = try_get_mclass_by_name(nmodule, mmodule, "Object")
# Create inheritance on all classdefs
for nclassdef in nmodule.n_classdefs do
- self.build_a_mclassdef_inheritance(nmodule, nclassdef)
+ self.collect_a_mclassdef_inheritance(nmodule, nclassdef)
+ end
+
+ # Create the mclassdef hierarchy
+ for nclassdef in nmodule.n_classdefs do
+ var mclassdef = nclassdef.mclassdef.as(not null)
+ mclassdef.add_in_hierarchy
end
# TODO: Check that the super-class is not intrusive
--- /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 kernel
+
+class C
+ super B
+
+ redef fun foo do 1.output
+ fun baz do foo
+end
+
+class A
+ fun foo do 2.output
+ fun bar do 3.output
+end
+
+class B
+ super A
+end
+
+fun test(a: A)
+do
+ a.foo
+ a.bar
+end
+
+test(new A)
+test(new B)
+test(new C)
--- /dev/null
+2
+3
+2
+3
+1
+3