X-Git-Url: http://nitlanguage.org diff --git a/src/modelize/modelize_property.nit b/src/modelize/modelize_property.nit index 25502fd..5ba3196 100644 --- a/src/modelize/modelize_property.nit +++ b/src/modelize/modelize_property.nit @@ -111,7 +111,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 = mclassdef.mmodule.model.null_type + mpropdef.bound = new MErrorType(mclassdef.mmodule.model) end end for npropdef in nclassdef2.n_propdefs do @@ -145,7 +145,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] @@ -153,7 +153,6 @@ redef class ModelBuilder mpropdef.msignature = msignature mpropdef.new_msignature = msignature mprop.is_init = true - nclassdef.mfree_init = mpropdef self.toolcontext.info("{mclassdef} gets a free empty constructor {mpropdef}{msignature}", 3) the_root_init_mmethod = mprop return @@ -181,21 +180,20 @@ redef class ModelBuilder 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 sig = npropdef.mpropdef.msignature + var mpropdef = npropdef.mpropdef + if mpropdef == null then return # Skip broken method + var sig = mpropdef.msignature if sig == null then continue # Skip broken method - for param in sig.mparameters do - var ret_type = param.mtype - var mparameter = new MParameter(param.name, ret_type, false) - mparameters.add(mparameter) - end - initializers.add(npropdef.mpropdef.mproperty) - npropdef.mpropdef.mproperty.is_autoinit = true + mparameters.add_all sig.mparameters + initializers.add(mpropdef.mproperty) + mpropdef.mproperty.is_autoinit = true end if npropdef isa AAttrPropdef then var mreadpropdef = npropdef.mreadpropdef - if mreadpropdef == null or mreadpropdef.msignature == null then return # Skip broken attribute + if mreadpropdef == null then return # Skip broken attribute + var msignature = mreadpropdef.msignature + if msignature == null then return # Skip broken attribute if npropdef.noinit then continue # Skip noinit attribute var atlateinit = npropdef.get_single_annotation("lateinit", self) if atlateinit != null then @@ -205,25 +203,28 @@ redef class ModelBuilder mreadpropdef.mproperty.is_autoinit = true continue end - if npropdef.has_value then continue - var paramname = mreadpropdef.mproperty.name - var ret_type = mreadpropdef.msignature.return_mtype - if ret_type == null then return - var mparameter = new MParameter(paramname, ret_type, false) - mparameters.add(mparameter) + if npropdef.has_value and not npropdef.is_optional then continue var msetter = npropdef.mwritepropdef if msetter == null then # No setter, it is a readonly attribute, so just add it + var paramname = mreadpropdef.mproperty.name + var ret_type = msignature.return_mtype + if ret_type == null then return + var mparameter = new MParameter(paramname, ret_type, false) + mparameters.add(mparameter) + initializers.add(npropdef.mpropdef.mproperty) npropdef.mpropdef.mproperty.is_autoinit = true else # Add the setter to the list + mparameters.add_all msetter.msignature.mparameters initializers.add(msetter.mproperty) msetter.mproperty.is_autoinit = true end end end + var the_root_init_mmethod = self.the_root_init_mmethod if the_root_init_mmethod == null then return # Look for most-specific new-stype init definitions @@ -349,14 +350,13 @@ redef class ModelBuilder end # Else create the local implicit basic init definition - var mprop = the_root_init_mmethod.as(not null) + var mprop = the_root_init_mmethod var mpropdef = new MMethodDef(mclassdef, mprop, nclassdef.location) mpropdef.has_supercall = true mpropdef.initializers.add_all(initializers) var msignature = new MSignature(mparameters, null) mpropdef.new_msignature = msignature mpropdef.msignature = new MSignature(new Array[MParameter], null) # always an empty real signature - nclassdef.mfree_init = mpropdef self.toolcontext.info("{mclassdef} gets a free constructor for attributes {mpropdef}{msignature}", 3) mclassdef.mclass.root_init = mpropdef end @@ -382,6 +382,10 @@ redef class ModelBuilder # nothing, always visible else if mtype isa MNullType then # 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 @@ -441,8 +445,7 @@ redef class ModelBuilder var vt = t.mproperty # Because `vt` is possibly unchecked, we have to do the bound-lookup manually var defs = vt.lookup_definitions(mmodule, recv) - # TODO something to manage correctly bound conflicts - assert not defs.is_empty + if defs.is_empty then return false nexts = new Array[MType] for d in defs do var next = defs.first.bound @@ -487,9 +490,6 @@ end redef class AClassdef # Marker used in `ModelBuilder::build_properties` private var build_properties_is_done = false - - # The free init (implicitely constructed by the class if required) - var mfree_init: nullable MMethodDef = null end redef class MClass @@ -591,7 +591,7 @@ redef class APropdef var mdoc = ndoc.to_mdoc mpropdef.mdoc = mdoc mdoc.original_mentity = mpropdef - else if mpropdef.is_intro and mpropdef.mproperty.visibility >= protected_visibility then + else if mpropdef.is_intro and mpropdef.mproperty.visibility >= protected_visibility and mpropdef.name != "new" then modelbuilder.advice(self, "missing-doc", "Documentation warning: Undocumented property `{mpropdef.mproperty}`") end @@ -824,7 +824,7 @@ 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 @@ -838,9 +838,7 @@ redef class AMethPropdef 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 @@ -1025,7 +1023,7 @@ redef class AMethPropdef var precursor_ret_type = msignature.return_mtype var ret_type = mysignature.return_mtype if ret_type != null and precursor_ret_type == null then - modelbuilder.error(nsig.n_type.as(not null), "Redef Error: `{mpropdef.mproperty}` is a procedure, not a function.") + modelbuilder.error(nsig.n_type, "Redef Error: `{mpropdef.mproperty}` is a procedure, not a function.") mpropdef.msignature = null mpropdef.is_broken = true return @@ -1059,7 +1057,7 @@ redef class AMethPropdef end end - if mysignature.arity > 0 then + if nsig != null then # Check parameters visibility for i in [0..mysignature.arity[ do var nt = nsig.n_params[i].n_type @@ -1074,6 +1072,8 @@ redef class AMethPropdef # For parameters, type is always useless in a redef. # For return type, type is useless if not covariant with introduction. redef fun check_repeated_types(modelbuilder) do + var mpropdef = self.mpropdef + if mpropdef == null then return if mpropdef.is_intro or n_signature == null then return # check params for param in n_signature.n_params do @@ -1156,6 +1156,9 @@ redef class AAttrPropdef # Is the node tagged lazy? var is_lazy = false + # Is the node tagged optional? + var is_optional = false + # Has the node a default value? # Could be through `n_expr` or `n_block` var has_value = false @@ -1183,7 +1186,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 @@ -1193,9 +1196,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 @@ -1245,11 +1252,21 @@ 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 self.mlazypropdef = mlazypropdef end + var atoptional = self.get_single_annotation("optional", modelbuilder) + if atoptional != null then + if not has_value then + modelbuilder.error(atoptional, "Error: `optional` attributes need a default value.") + end + is_optional = true + end + var atreadonly = self.get_single_annotation("readonly", modelbuilder) if atreadonly != null then if not has_value then @@ -1282,10 +1299,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) @@ -1350,6 +1371,8 @@ redef class AAttrPropdef if nexpr != null then if nexpr isa ANewExpr then mtype = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, nexpr.n_type, true) + else if nexpr isa AAsCastExpr then + mtype = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, nexpr.n_type, true) else if nexpr isa AIntegerExpr then var cla: nullable MClass = null if nexpr.value isa Int then @@ -1375,7 +1398,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") @@ -1384,7 +1414,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.") @@ -1419,16 +1458,20 @@ redef class AAttrPropdef var mwritepropdef = self.mwritepropdef if mwritepropdef != null then + var mwritetype = mtype + if is_optional then + mwritetype = mwritetype.as_nullable + end var name: String name = n_id2.text - var mparameter = new MParameter(name, mtype, false) + var mparameter = new MParameter(name, mwritetype, false) var msignature = new MSignature([mparameter], null) mwritepropdef.msignature = msignature end 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 @@ -1538,6 +1581,8 @@ redef class AAttrPropdef # Type is useless if the attribute type is the same thant the intro. redef fun check_repeated_types(modelbuilder) do + var mreadpropdef = self.mreadpropdef + if mreadpropdef == null then return if mreadpropdef.is_intro or n_type == null then return # get intro var intro = mreadpropdef.mproperty.intro @@ -1561,31 +1606,33 @@ redef class ATypePropdef redef fun build_property(modelbuilder, mclassdef) do - var name = self.n_id.text - var mprop = modelbuilder.try_get_mproperty_by_name(self.n_id, mclassdef, name) + var name = self.n_qid.n_id.text + 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_id, "bad-type-name", "Warning: lowercase in the virtual type `{name}`.") + modelbuilder.warning(n_qid, "bad-type-name", "Warning: lowercase in the virtual type `{name}`.") break end - if not self.check_redef_keyword(modelbuilder, mclassdef, self.n_kwredef, false, mprop) then return else - if not self.check_redef_keyword(modelbuilder, mclassdef, self.n_kwredef, true, mprop) then return + if mprop.is_broken then return assert mprop isa MVirtualTypeProp check_redef_property_visibility(modelbuilder, self.n_visibility, mprop) end - mclassdef.mprop2npropdef[mprop] = self var mpropdef = new MVirtualTypeDef(mclassdef, mprop, self.location) self.mpropdef = mpropdef - modelbuilder.mpropdef2npropdef[mpropdef] = self if mpropdef.is_intro then modelbuilder.toolcontext.info("{mpropdef} introduces new type {mprop.full_name}", 4) else modelbuilder.toolcontext.info("{mpropdef} redefines type {mprop.full_name}", 4) end + if not self.check_redef_keyword(modelbuilder, mclassdef, self.n_kwredef, not mpropdef.is_intro, mprop) then + mpropdef.is_broken =true + end + mclassdef.mprop2npropdef[mprop] = self + modelbuilder.mpropdef2npropdef[mpropdef] = self set_doc(mpropdef, modelbuilder) var atfixed = get_single_annotation("fixed", modelbuilder) @@ -1633,7 +1680,7 @@ redef class ATypePropdef # Check redefinitions for p in mpropdef.mproperty.lookup_super_definitions(mmodule, anchor) do var supbound = p.bound - if supbound == null then break # broken super bound, skip error + if supbound == null or supbound isa MBottomType or p.is_broken then break # broken super bound, skip error if p.is_fixed then modelbuilder.error(self, "Redef Error: virtual type `{mpropdef.mproperty}` is fixed in super-class `{p.mclassdef.mclass}`.") break