Merge: modelize_class: Refactor
[nit.git] / src / modelize / modelize_property.nit
index 573f200..e805d4e 100644 (file)
@@ -80,7 +80,6 @@ redef class ModelBuilder
        end
 
        # Build the properties of `nclassdef`.
-       # REQUIRE: all superclasses are built.
        private fun build_properties(nclassdef: AClassdef)
        do
                # Force building recursively
@@ -111,7 +110,7 @@ redef class ModelBuilder
                                if not check_virtual_types_circularity(npropdef, mpropdef.mproperty, mclassdef.bound_mtype, mclassdef.mmodule) then
                                        # Invalidate the bound
                                        mpropdef.is_broken = true
-                                       mpropdef.bound = new MBottomType(mclassdef.mmodule.model)
+                                       mpropdef.bound = new MErrorType(mclassdef.mmodule.model)
                                end
                        end
                        for npropdef in nclassdef2.n_propdefs do
@@ -145,7 +144,7 @@ redef class ModelBuilder
                # Look for the init in Object, or create it
                if mclassdef.mclass.name == "Object" and the_root_init_mmethod == null then
                        # Create the implicit root-init method
-                       var mprop = new MMethod(mclassdef, "init", mclassdef.mclass.visibility)
+                       var mprop = new MMethod(mclassdef, "init", nclassdef.location, mclassdef.mclass.visibility)
                        mprop.is_root_init = true
                        var mpropdef = new MMethodDef(mclassdef, mprop, nclassdef.location)
                        var mparameters = new Array[MParameter]
@@ -384,6 +383,8 @@ redef class ModelBuilder
                        # nothing to do.
                else if mtype isa MBottomType then
                        # nothing to do.
+               else if mtype isa MErrorType then
+                       # nothing to do.
                else
                        node.debug "Unexpected type {mtype}"
                        abort
@@ -670,14 +671,13 @@ redef class ASignature
        # Visit and fill information about a signature
        private fun visit_signature(modelbuilder: ModelBuilder, mclassdef: MClassDef): Bool
        do
-               var mmodule = mclassdef.mmodule
                var param_names = self.param_names
                var param_types = self.param_types
                for np in self.n_params do
                        param_names.add(np.n_id.text)
                        var ntype = np.n_type
                        if ntype != null then
-                               var mtype = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, ntype, true)
+                               var mtype = modelbuilder.resolve_mtype_unchecked(mclassdef, ntype, true)
                                if mtype == null then return false # Skip error
                                for i in [0..param_names.length-param_types.length[ do
                                        param_types.add(mtype)
@@ -694,7 +694,7 @@ redef class ASignature
                end
                var ntype = self.n_type
                if ntype != null then
-                       self.ret_type = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, ntype, true)
+                       self.ret_type = modelbuilder.resolve_mtype_unchecked(mclassdef, ntype, true)
                        if self.ret_type == null then return false # Skip error
                end
 
@@ -708,14 +708,14 @@ redef class ASignature
                for np in self.n_params do
                        var ntype = np.n_type
                        if ntype != null then
-                               if modelbuilder.resolve_mtype(mclassdef.mmodule, mclassdef, ntype) == null then
+                               if modelbuilder.resolve_mtype(mclassdef, ntype) == null then
                                        res = false
                                end
                        end
                end
                var ntype = self.n_type
                if ntype != null then
-                       if modelbuilder.resolve_mtype(mclassdef.mmodule, mclassdef, ntype) == null then
+                       if modelbuilder.resolve_mtype(mclassdef, ntype) == null then
                                res = false
                        end
                end
@@ -769,22 +769,21 @@ redef class AMethPropdef
        do
                var n_kwinit = n_kwinit
                var n_kwnew = n_kwnew
-               var is_init = n_kwinit != null or n_kwnew != null
+               var is_new = n_kwnew != null
+               var is_init = n_kwinit != null or is_new
                var name: String
                var amethodid = self.n_methid
                var name_node: ANode
                if amethodid == null then
-                       if not is_init then
-                               name = "main"
-                               name_node = self
-                       else if n_kwinit != null then
+                       if n_kwinit != null then
                                name = "init"
                                name_node = n_kwinit
                        else if n_kwnew != null then
                                name = "new"
                                name_node = n_kwnew
                        else
-                               abort
+                               name = "main"
+                               name_node = self
                        end
                else if amethodid isa AIdMethid then
                        name = amethodid.n_id.text
@@ -822,23 +821,21 @@ redef class AMethPropdef
                end
                if mprop == null then
                        var mvisibility = new_property_visibility(modelbuilder, mclassdef, self.n_visibility)
-                       mprop = new MMethod(mclassdef, name, mvisibility)
+                       mprop = new MMethod(mclassdef, name, self.location, mvisibility)
                        if look_like_a_root_init and modelbuilder.the_root_init_mmethod == null then
                                modelbuilder.the_root_init_mmethod = mprop
                                mprop.is_root_init = true
                        end
                        mprop.is_init = is_init
-                       mprop.is_new = n_kwnew != null
-                       if mprop.is_new then mclassdef.mclass.has_new_factory = true
+                       mprop.is_new = is_new
+                       if is_new then mclassdef.mclass.has_new_factory = true
                        if name == "sys" then mprop.is_toplevel = true # special case for sys allowed in `new` factories
                        if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, mprop) then
                                mprop.is_broken = true
                                return
                        end
                else
-                       if mprop.is_broken then
-                               return
-                       end
+                       if mprop.is_broken then return
                        if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, not self isa AMainMethPropdef, mprop) then return
                        check_redef_property_visibility(modelbuilder, self.n_visibility, mprop)
                end
@@ -1159,8 +1156,8 @@ redef class AAttrPropdef
        # Is the node tagged optional?
        var is_optional = false
 
-       # Has the node a default value?
-       # Could be through `n_expr` or `n_block`
+       # Does the node have a default value?
+       # Could be through `n_expr`, `n_block` or `is_lazy`
        var has_value = false
 
        # The guard associated to a lazy attribute.
@@ -1186,7 +1183,7 @@ redef class AAttrPropdef
                                modelbuilder.error(self, "Error: attempt to define attribute `{name}` in the {mclass.kind} `{mclass}`.")
                        end
 
-                       var mprop = new MAttribute(mclassdef, "_" + name, private_visibility)
+                       var mprop = new MAttribute(mclassdef, "_" + name, self.location, private_visibility)
                        var mpropdef = new MAttributeDef(mclassdef, mprop, self.location)
                        self.mpropdef = mpropdef
                        modelbuilder.mpropdef2npropdef[mpropdef] = self
@@ -1196,9 +1193,13 @@ redef class AAttrPropdef
                var mreadprop = modelbuilder.try_get_mproperty_by_name(nid2, mclassdef, readname).as(nullable MMethod)
                if mreadprop == null then
                        var mvisibility = new_property_visibility(modelbuilder, mclassdef, self.n_visibility)
-                       mreadprop = new MMethod(mclassdef, readname, mvisibility)
-                       if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, mreadprop) then return
+                       mreadprop = new MMethod(mclassdef, readname, self.location, mvisibility)
+                       if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, mreadprop) then
+                               mreadprop.is_broken = true
+                               return
+                       end
                else
+                       if mreadprop.is_broken then return
                        if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, true, mreadprop) then return
                        check_redef_property_visibility(modelbuilder, self.n_visibility, mreadprop)
                end
@@ -1248,7 +1249,7 @@ redef class AAttrPropdef
                                return
                        end
                        is_lazy = true
-                       var mlazyprop = new MAttribute(mclassdef, "lazy _" + name, none_visibility)
+                       var mlazyprop = new MAttribute(mclassdef, "lazy _" + name, self.location, none_visibility)
                        mlazyprop.is_fictive = true
                        var mlazypropdef = new MAttributeDef(mclassdef, mlazyprop, self.location)
                        mlazypropdef.is_fictive = true
@@ -1295,10 +1296,14 @@ redef class AAttrPropdef
                                # By default, use protected visibility at most
                                if mvisibility > protected_visibility then mvisibility = protected_visibility
                        end
-                       mwriteprop = new MMethod(mclassdef, writename, mvisibility)
-                       if not self.check_redef_keyword(modelbuilder, mclassdef, nwkwredef, false, mwriteprop) then return
+                       mwriteprop = new MMethod(mclassdef, writename, self.location, mvisibility)
+                       if not self.check_redef_keyword(modelbuilder, mclassdef, nwkwredef, false, mwriteprop) then
+                               mwriteprop.is_broken = true
+                               return
+                       end
                        mwriteprop.deprecation = mreadprop.deprecation
                else
+                       if mwriteprop.is_broken then return
                        if not self.check_redef_keyword(modelbuilder, mclassdef, nwkwredef or else n_kwredef, true, mwriteprop) then return
                        if atwritable != null then
                                check_redef_property_visibility(modelbuilder, atwritable.n_visibility, mwriteprop)
@@ -1341,7 +1346,7 @@ redef class AAttrPropdef
 
                var ntype = self.n_type
                if ntype != null then
-                       mtype = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, ntype, true)
+                       mtype = modelbuilder.resolve_mtype_unchecked(mclassdef, ntype, true)
                        if mtype == null then return
                end
 
@@ -1362,9 +1367,9 @@ redef class AAttrPropdef
                if mtype == null then
                        if nexpr != null then
                                if nexpr isa ANewExpr then
-                                       mtype = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, nexpr.n_type, true)
+                                       mtype = modelbuilder.resolve_mtype_unchecked(mclassdef, nexpr.n_type, true)
                                else if nexpr isa AAsCastExpr then
-                                       mtype = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, nexpr.n_type, true)
+                                       mtype = modelbuilder.resolve_mtype_unchecked(mclassdef, nexpr.n_type, true)
                                else if nexpr isa AIntegerExpr then
                                        var cla: nullable MClass = null
                                        if nexpr.value isa Int then
@@ -1390,7 +1395,14 @@ redef class AAttrPropdef
                                        var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Float")
                                        if cla != null then mtype = cla.mclass_type
                                else if nexpr isa ACharExpr then
-                                       var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Char")
+                                       var cla: nullable MClass
+                                       if nexpr.is_ascii then
+                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Byte")
+                                       else if nexpr.is_code_point then
+                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int")
+                                       else
+                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Char")
+                                       end
                                        if cla != null then mtype = cla.mclass_type
                                else if nexpr isa ABoolExpr then
                                        var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Bool")
@@ -1399,7 +1411,16 @@ redef class AAttrPropdef
                                        var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "String")
                                        if cla != null then mtype = cla.mclass_type
                                else if nexpr isa AStringFormExpr then
-                                       var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "String")
+                                       var cla: nullable MClass
+                                       if nexpr.is_bytestring then
+                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Bytes")
+                                       else if nexpr.is_re then
+                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Regex")
+                                       else if nexpr.is_string then
+                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "String")
+                                       else
+                                               abort
+                                       end
                                        if cla != null then mtype = cla.mclass_type
                                else
                                        modelbuilder.error(self, "Error: untyped attribute `{mreadpropdef}`. Implicit typing allowed only for literals and new.")
@@ -1409,7 +1430,7 @@ redef class AAttrPropdef
                        end
                else if ntype != null and inherited_type == mtype then
                        if nexpr isa ANewExpr then
-                               var xmtype = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, nexpr.n_type, true)
+                               var xmtype = modelbuilder.resolve_mtype_unchecked(mclassdef, nexpr.n_type, true)
                                if xmtype == mtype then
                                        modelbuilder.advice(ntype, "useless-type", "Warning: useless type definition")
                                end
@@ -1447,7 +1468,7 @@ redef class AAttrPropdef
 
                var mlazypropdef = self.mlazypropdef
                if mlazypropdef != null then
-                       mlazypropdef.static_mtype = modelbuilder.model.get_mclasses_by_name("Bool").first.mclass_type
+                       mlazypropdef.static_mtype = mmodule.bool_type
                end
                check_repeated_types(modelbuilder)
        end
@@ -1465,11 +1486,11 @@ redef class AAttrPropdef
 
                # Check types
                if ntype != null then
-                       if modelbuilder.resolve_mtype(mmodule, mclassdef, ntype) == null then return
+                       if modelbuilder.resolve_mtype(mclassdef, ntype) == null then return
                end
                var nexpr = n_expr
                if nexpr isa ANewExpr then
-                       if modelbuilder.resolve_mtype(mmodule, mclassdef, nexpr.n_type) == null then return
+                       if modelbuilder.resolve_mtype(mclassdef, nexpr.n_type) == null then return
                end
 
                # Lookup for signature in the precursor
@@ -1586,12 +1607,13 @@ redef class ATypePropdef
                var mprop = modelbuilder.try_get_mproperty_by_name(self.n_qid, mclassdef, name)
                if mprop == null then
                        var mvisibility = new_property_visibility(modelbuilder, mclassdef, self.n_visibility)
-                       mprop = new MVirtualTypeProp(mclassdef, name, mvisibility)
+                       mprop = new MVirtualTypeProp(mclassdef, name, self.location, mvisibility)
                        for c in name.chars do if c >= 'a' and c<= 'z' then
                                modelbuilder.warning(n_qid, "bad-type-name", "Warning: lowercase in the virtual type `{name}`.")
                                break
                        end
                else
+                       if mprop.is_broken then return
                        assert mprop isa MVirtualTypeProp
                        check_redef_property_visibility(modelbuilder, self.n_visibility, mprop)
                end
@@ -1621,11 +1643,10 @@ redef class ATypePropdef
                var mpropdef = self.mpropdef
                if mpropdef == null then return # Error thus skipped
                var mclassdef = mpropdef.mclassdef
-               var mmodule = mclassdef.mmodule
                var mtype: nullable MType = null
 
                var ntype = self.n_type
-               mtype = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, ntype, true)
+               mtype = modelbuilder.resolve_mtype_unchecked(mclassdef, ntype, true)
                if mtype == null then return
 
                mpropdef.bound = mtype
@@ -1647,7 +1668,7 @@ redef class ATypePropdef
                var anchor = mclassdef.bound_mtype
 
                var ntype = self.n_type
-               if modelbuilder.resolve_mtype(mmodule, mclassdef, ntype) == null then
+               if modelbuilder.resolve_mtype(mclassdef, ntype) == null then
                        mpropdef.bound = null
                        return
                end
@@ -1661,8 +1682,7 @@ redef class ATypePropdef
                                break
                        end
                        if p.mclassdef.mclass == mclassdef.mclass then
-                               # Still a warning to pass existing bad code
-                               modelbuilder.warning(n_type, "refine-type", "Redef Error: a virtual type cannot be refined.")
+                               modelbuilder.error(n_type, "Redef Error: a virtual type cannot be refined.")
                                break
                        end
                        if not modelbuilder.check_subtype(n_type, mmodule, anchor, bound, supbound) then