Move property selectors from types to local classes
[nit.git] / src / syntax / typing.nit
index 3912ef2..afd0da7 100644 (file)
@@ -58,7 +58,7 @@ special AbsSyntaxVisitor
 
        init(tc, module) do super
 
-       private meth get_default_constructor_for(n: PNode, c: MMLocalClass, prop: MMMethod): MMMethod
+       private meth get_default_constructor_for(n: PNode, c: MMLocalClass, prop: MMSrcMethod): MMMethod
        do
                var v = self
                #var prop = v.local_property
@@ -70,10 +70,10 @@ special AbsSyntaxVisitor
                        if not g.is_init then continue
                        if g.intro.local_class != c then continue
                        var gp = c[g]
-                       assert gp isa MMMethod
-                       var garity = g.intro.signature.arity
+                       assert gp isa MMSrcMethod
+                       var garity = gp.signature.arity
                        if prop != null and g.intro.name == prop.name then
-                               if garity == 0 or garity == parity then
+                               if garity == 0 or prop.signature < gp.signature then
                                        return gp
                                else
                                        false_candidates.add(gp)
@@ -87,12 +87,14 @@ special AbsSyntaxVisitor
                end
                if candidates.length == 1 then
                        return candidates.first
-               else if false_candidates.is_empty then
-                       v.warning(n, "Fatal error: there is no available constrctor in {c}.")
+               else if candidates.length > 0 then
+                       v.error(n, "Error: Conflicting default constructor to call for {c}: {candidates.join(", ")}.")
+                       return null
+               else if false_candidates.length > 0 then
+                       v.error(n, "Error: there is no available compatible constrctor in {c}.")
                        return null
-                       #abort
                else
-                       v.error(n, "Error: Conflicting default constructor to call for {c}: {false_candidates.join(", ")}.")
+                       v.warning(n, "Error: there is no available compatible constrctor in {c}.")
                        return null
                end
        end
@@ -130,13 +132,13 @@ private class VariableContext
        attr _dico: Map[Symbol, Variable]
 
        # Build a new VariableContext
-       meth sub: VariableContext
+       meth sub: SubVariableContext
        do
                return new SubVariableContext.with(self, null, null)
        end
 
        # Build a nested VariableContext with new variable information
-       meth sub_with(v: Variable, t: MMType): VariableContext
+       meth sub_with(v: Variable, t: MMType): SubVariableContext
        do
                return new SubVariableContext.with(self, v, t)
        end
@@ -231,8 +233,8 @@ redef class AConcreteInitPropdef
                else 
                        var i = 0
                        var l = explicit_super_init_calls.length
-                       var cur_m: MMMethod
-                       var cur_c: MMLocalClass
+                       var cur_m: MMMethod = null
+                       var cur_c: MMLocalClass = null
                        if i < l then
                                cur_m = explicit_super_init_calls[i]
                                cur_c = cur_m.global.intro.local_class
@@ -240,7 +242,9 @@ redef class AConcreteInitPropdef
                        var j = 0
                        while j < v.local_class.cshe.direct_greaters.length do
                                var c = v.local_class.cshe.direct_greaters[j]
-                               if cur_c != null and c.cshe <= cur_c then
+                               if c.global.is_interface or c.global.is_universal then
+                                       j += 1
+                               else if cur_c != null and c.cshe <= cur_c then
                                        if c == cur_c then j += 1
                                        super_init_calls.add(cur_m)
                                        i += 1
@@ -297,13 +301,10 @@ redef class PExpr
 end
 
 redef class AVardeclExpr
-       # Assiociated local variable
-        readable attr _variable: Variable
-
        redef meth after_typing(v)
        do
                var va = new Variable(n_id.to_symbol, self)
-               _variable = va
+               variable = va
                v.variable_ctx.add(va)
 
                if n_type != null then
@@ -383,34 +384,31 @@ redef class AForExpr
 end
 
 redef class AForVardeclExpr
-       # Associated automatic local variable
-       readable attr _variable: Variable
-
        redef meth after_typing(v)
        do
                v.variable_ctx = v.variable_ctx.sub
-               var variable = new Variable(n_id.to_symbol, self)
-               _variable = variable
-               v.variable_ctx.add(variable)
+               var va = new Variable(n_id.to_symbol, self)
+               variable = va
+               v.variable_ctx.add(va)
 
                var expr_type = n_expr.stype
                if not v.check_conform(self, expr_type, v.type_collection) then
                        return
                end
-               var prop = expr_type.select_method(once ("iterator".to_symbol))
+               var prop = expr_type.local_class.select_method(once ("iterator".to_symbol))
                if prop == null then
                        v.error(self, "Error: Collection MUST have an iterate method")
                        return
                end
-               var iter_type = prop.signature.return_type
-               var prop2 = iter_type.select_method(once ("item".to_symbol))
+               var iter_type = prop.signature_for(expr_type).return_type
+               var prop2 = iter_type.local_class.select_method(once ("item".to_symbol))
                if prop2 == null then
                        v.error(self, "Error: {iter_type} MUST have an item method")
                        return
                end
-               var t = prop2.signature.return_type
+               var t = prop2.signature_for(iter_type).return_type
                if not n_expr.is_self then t = t.not_for_self
-               variable.stype = t
+               va.stype = t
        end
 end
 
@@ -422,11 +420,6 @@ redef class AAssertExpr
        end
 end
 
-redef class AVarFormExpr
-       # Associated local variable
-        readable writable attr _variable: Variable 
-end
-
 redef class AVarExpr
        redef meth is_variable do return true
 
@@ -452,15 +445,15 @@ redef class AReassignFormExpr
                        return
                end
                var name = n_assign_op.method_name
-               var prop = type_lvalue.select_method(name)
+               var prop = type_lvalue.local_class.select_method(name)
                if prop == null then
                        v.error(self, "Error: Method '{name}' doesn't exists in {type_lvalue}.")
                        return
                end
                prop.global.check_visibility(v, self, v.module, false)
-               var psig = prop.signature
+               var psig = prop.signature_for(type_lvalue)
                _assign_method = prop
-               v.check_conform(self, n_value.stype, psig[0].not_for_self)
+               v.check_conform(n_value, n_value.stype, psig[0].not_for_self)
                v.check_conform(self, psig.return_type.not_for_self, n_value.stype)
        end
 
@@ -468,6 +461,14 @@ redef class AReassignFormExpr
        readable attr _assign_method: MMMethod
 end
 
+redef class AVarReassignExpr
+       redef meth after_typing(v)
+       do
+               var t = v.variable_ctx.stype(variable)
+               do_lvalue_typing(v, t)
+       end
+end
+
 redef class PAssignOp
        meth method_name: Symbol is abstract
 end
@@ -478,14 +479,6 @@ redef class AMinusAssignOp
        redef meth method_name do return once "-".to_symbol
 end
 
-redef class AVarReassignExpr
-       redef meth after_typing(v)
-       do
-               var t = v.variable_ctx.stype(variable)
-               do_lvalue_typing(v, t)
-       end
-end
-
 redef class ASelfExpr
        redef meth after_typing(v)
        do
@@ -621,7 +614,7 @@ redef class AArrayExpr
 
        redef meth after_typing(v)
        do
-               var stype: MMType
+               var stype: MMType = null
                for n in n_exprs do
                        var ntype = n.stype
                        if stype == null or (ntype != null and stype < ntype) then
@@ -661,7 +654,7 @@ special ASuperInitCall
        readable attr _init_in_superclass: MMMethod
        redef meth after_typing(v)
        do
-               var precs: Array[MMLocalProperty] = v.local_property.cprhe.direct_greaters
+               var precs: Array[MMLocalProperty] = v.local_property.prhe.direct_greaters
                if not precs.is_empty then
                        v.local_property.need_super = true
                else if v.local_property.global.is_init then
@@ -670,7 +663,7 @@ special ASuperInitCall
                                if not p.global.is_init then
                                        v.error(self, "Error: {p.local_class}::{p} is not a constructor.")
                                else
-                                       precs.add(v.self_type.select_property(p.global))
+                                       precs.add(v.local_class[p.global])
                                end
                        end
                        if precs.is_empty then
@@ -685,19 +678,19 @@ special ASuperInitCall
                        _init_in_superclass = p
                        register_super_init_call(v, p)
                        if n_args.length > 0 then
-                               _arguments = process_signature(v, p, true, n_args.to_a)
+                               _arguments = process_signature(v, v.self_type, p, true, n_args.to_a)
                        end
                else
                        v.error(self, "Error: No super method to call for {v.local_property}.")
                        return
                end
 
-               if precs.first.signature.return_type != null then
+               if precs.first.signature_for(v.self_type).return_type != null then
                        var stypes = new Array[MMType]
-                       var stype: MMType
+                       var stype: MMType = null
                        for prop in precs do
                                assert prop isa MMMethod
-                               var t = prop.signature.return_type.for_module(v.module).adapt_to(v.local_property.signature.recv)
+                               var t = prop.signature_for(v.self_type).return_type.for_module(v.module).adapt_to(v.local_property.signature.recv)
                                stypes.add(t)
                                if stype == null or stype < t then
                                        stype = t
@@ -718,6 +711,9 @@ redef class AAttrFormExpr
        # Attribute accessed
        readable attr _prop: MMAttribute
 
+       # Attribute type of the acceded attribute
+       readable attr _attr_type: MMType
+
        # Compute the attribute accessed
        private meth do_typing(v: TypingVisitor)
        do
@@ -726,7 +722,7 @@ redef class AAttrFormExpr
                        return
                end
                var name = n_id.to_symbol
-               var prop = type_recv.select_attribute(name)
+               var prop = type_recv.local_class.select_attribute(name)
                if prop == null then
                        v.error(self, "Error: Attribute {name} doesn't exists in {type_recv}.")
                        return
@@ -734,6 +730,9 @@ redef class AAttrFormExpr
                        v.error(self, "Error: Attribute {name} from {prop.global.local_class.module} is invisible in {v.module}")
                end
                _prop = prop
+               var at = prop.signature_for(type_recv).return_type 
+               if not n_expr.is_self then at = at.not_for_self
+               _attr_type = at
        end
 end
 
@@ -744,8 +743,6 @@ redef class AAttrExpr
                if prop == null then
                        return
                end
-               var attr_type = prop.signature.return_type
-               if not n_expr.is_self then attr_type = attr_type.not_for_self
                _stype = attr_type
        end
 end
@@ -757,8 +754,6 @@ redef class AAttrAssignExpr
                if prop == null then
                        return
                end
-               var attr_type = prop.signature.return_type
-               if not n_expr.is_self then attr_type = attr_type.not_for_self
                v.check_conform(self, n_value.stype, attr_type)
        end
 end
@@ -770,8 +765,6 @@ redef class AAttrReassignExpr
                if prop == null then
                        return
                end
-               var attr_type = prop.signature.return_type
-               if not n_expr.is_self then attr_type = attr_type.not_for_self
                do_lvalue_typing(v, attr_type)
        end
 end
@@ -783,7 +776,7 @@ special PExpr
        do
                var prop = get_property(v, type_recv, is_implicit_self, name)
                if prop == null then return
-               var args = process_signature(v, prop, recv_is_self, raw_args)
+               var args = process_signature(v, type_recv, prop, recv_is_self, raw_args)
                if args == null then return
                _prop = prop
                _arguments = args
@@ -792,14 +785,14 @@ special PExpr
        private meth get_property(v: TypingVisitor, type_recv: MMType, is_implicit_self: Bool, name: Symbol): MMMethod
        do
                if type_recv == null then return null
-               var prop = type_recv.select_method(name)
+               var prop = type_recv.local_class.select_method(name)
                if prop == null and v.local_property.global.is_init then
                        var props = type_recv.local_class.super_methods_named(name)
                        if props.length > 1 then
                                v.error(self, "Error: Ambigous method name '{name}' for {props.join(", ")}. Use explicit designation.")
                                return null
                        else if props.length == 1 then 
-                               var p = type_recv.select_property(props.first.global)
+                               var p = type_recv.local_class[props.first.global]
                                assert p isa MMMethod
                                prop = p
                        end
@@ -816,10 +809,10 @@ special PExpr
                return prop
        end
 
-       private meth process_signature(v: TypingVisitor, prop: MMMethod, recv_is_self: Bool, raw_args: Array[PExpr]): Array[PExpr]
+       private meth process_signature(v: TypingVisitor, type_recv: MMType, prop: MMMethod, recv_is_self: Bool, raw_args: Array[PExpr]): Array[PExpr]
        do
                prop.global.check_visibility(v, self, v.module, recv_is_self)
-               var psig = prop.signature
+               var psig = prop.signature_for(type_recv)
                var par_vararg = psig.vararg_rank
                var par_arity = psig.arity
                var raw_arity: Int
@@ -872,7 +865,7 @@ special AAbsSendExpr
                        v.error(self, "Error: Constructor invocation {property} must not be in nested block.")
                end
                var cla = v.module[property.global.intro.local_class.global]
-               var prev_class: MMLocalClass
+               var prev_class: MMLocalClass = null
                if not v.explicit_super_init_calls.is_empty then
                        prev_class = v.explicit_super_init_calls.last.global.intro.local_class
                end
@@ -953,7 +946,7 @@ special ASuperInitCall
                                register_super_init_call(v, prop)
                        end
                end
-               var t = prop.signature.return_type
+               var t = prop.signature_for(n_expr.stype).return_type
                if t != null and not n_expr.is_self then t = t.not_for_self
                _stype = t
        end
@@ -975,7 +968,7 @@ special AReassignFormExpr
                                v.error(self, "Error: constructor {prop} is not invoken on 'self'.")
                        end
                end
-               var t = prop.signature.return_type
+               var t = prop.signature_for(n_expr.stype).return_type
                if not n_expr.is_self then t = t.not_for_self
 
                do_lvalue_typing(v, t)
@@ -1139,6 +1132,14 @@ redef class AIsaExpr
        end
 end
 
+redef class AAsCastExpr
+       redef meth after_typing(v)
+       do
+               _stype = n_type.stype
+               var et = n_expr.stype
+       end
+end
+
 redef class AProxyExpr
        redef meth after_typing(v)
        do