# Public clients need to use `mpropdef2node` to access stuff.
private var mpropdef2npropdef = new HashMap[MPropDef, APropdef]
+ # Associate a `npropdef` with its `mpropdef`
+ #
+ # Be careful, this method is unsafe, no checking is done when it's used.
+ # The safe way to add method it's to use the `build_property`
+ #
+ # See `mpropdef2npropdef`
+ fun unsafe_add_mpropdef2npropdef(mpropdef: MPropDef,npropdef: APropdef)
+ do
+ mpropdef2npropdef[mpropdef] = npropdef
+ end
+
# Retrieve the associated AST node of a mpropertydef.
# This method is used to associate model entity with syntactic entities.
#
end
# Build the properties of `nclassdef`.
- # REQUIRE: all superclasses are built.
private fun build_properties(nclassdef: AClassdef)
do
# Force building recursively
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
# 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]
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
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
+ mparameters.add_all sig.mparameters
initializers.add(mpropdef.mproperty)
mpropdef.mproperty.is_autoinit = true
end
mreadpropdef.mproperty.is_autoinit = true
continue
end
- if npropdef.has_value then continue
- 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)
+ 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
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
# 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
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
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
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
# 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)
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
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
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
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
do
var mpropdef = self.mpropdef
if mpropdef == null then return # Error thus skiped
+ var mproperty = mpropdef.mproperty
var mclassdef = mpropdef.mclassdef
var mmodule = mclassdef.mmodule
var nsig = self.n_signature
- if mpropdef.mproperty.is_root_init and not mclassdef.is_intro then
+ if mproperty.is_root_init and not mclassdef.is_intro then
var root_init = mclassdef.mclass.root_init
if root_init != null then
# Inherit the initializers by refinement
# FIXME: do not inherit from the intro, but from the most specific
var msignature: nullable MSignature = null
if not mpropdef.is_intro then
- msignature = mpropdef.mproperty.intro.msignature
+ msignature = mproperty.intro.msignature
if msignature == null then return # Skip error
# The local signature is adapted to use the local formal types, if any.
if param_names.length != msignature.arity then
var node: ANode
if nsig != null then node = nsig else node = self
- modelbuilder.error(node, "Redef Error: expected {msignature.arity} parameter(s) for `{mpropdef.mproperty.name}{msignature}`; got {param_names.length}. See introduction at `{mpropdef.mproperty.full_name}`.")
+ modelbuilder.error(node, "Redef Error: expected {msignature.arity} parameter(s) for `{mproperty.name}{msignature}`; got {param_names.length}. See introduction at `{mproperty.full_name}`.")
return
end
- else if mpropdef.mproperty.is_init and not mpropdef.mproperty.is_new then
+ else if mproperty.is_init and not mproperty.is_new then
# FIXME UGLY: inherit signature from a super-constructor
for msupertype in mclassdef.supertypes do
msupertype = msupertype.anchor_to(mmodule, mclassdef.bound_mtype)
- var candidate = modelbuilder.try_get_mproperty_by_name2(self, mmodule, msupertype, mpropdef.mproperty.name)
+ var candidate = modelbuilder.try_get_mproperty_by_name2(self, mmodule, msupertype, mproperty.name)
if candidate != null then
if msignature == null then
msignature = candidate.intro.as(MMethodDef).msignature
end
# In `new`-factories, the return type is by default the classtype.
- if ret_type == null and mpropdef.mproperty.is_new then ret_type = mclassdef.mclass.mclass_type
+ if ret_type == null and mproperty.is_new then ret_type = mclassdef.mclass.mclass_type
# Special checks for operator methods
if not accept_special_last_parameter and mparameters.not_empty and mparameters.last.is_vararg then
- modelbuilder.error(self.n_signature.n_params.last, "Error: illegal variadic parameter `{mparameters.last}` for `{mpropdef.mproperty.name}`.")
+ modelbuilder.error(self.n_signature.n_params.last, "Error: illegal variadic parameter `{mparameters.last}` for `{mproperty.name}`.")
end
if ret_type == null and return_is_mandatory then
- modelbuilder.error(self.n_methid, "Error: mandatory return type for `{mpropdef.mproperty.name}`.")
+ modelbuilder.error(self.n_methid, "Error: mandatory return type for `{mproperty.name}`.")
end
msignature = new MSignature(mparameters, ret_type)
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
# Is the node tagged lazy?
var is_lazy = false
- # Has the node a default value?
- # Could be through `n_expr` or `n_block`
+ # Is the node tagged optional?
+ var is_optional = false
+
+ # 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.
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
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
mclassdef.mprop2npropdef[mreadprop] = self
+ var attr_mpropdef = mpropdef
+ if attr_mpropdef != null then
+ mreadprop.getter_for = attr_mpropdef.mproperty
+ attr_mpropdef.mproperty.getter = mreadprop
+ end
+
var mreadpropdef = new MMethodDef(mclassdef, mreadprop, self.location)
self.mreadpropdef = mreadpropdef
modelbuilder.mpropdef2npropdef[mreadpropdef] = self
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
# 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)
end
mclassdef.mprop2npropdef[mwriteprop] = self
+ if attr_mpropdef != null then
+ mwriteprop.setter_for = attr_mpropdef.mproperty
+ attr_mpropdef.mproperty.setter = mwriteprop
+ end
+
var mwritepropdef = new MMethodDef(mclassdef, mwriteprop, self.location)
self.mwritepropdef = mwritepropdef
modelbuilder.mpropdef2npropdef[mwritepropdef] = self
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
var nexpr = self.n_expr
if mtype == null then
if nexpr != null then
- if nexpr isa ANewExpr 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
- cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int")
- else if nexpr.value isa Byte then
- cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Byte")
- else if nexpr.value isa Int8 then
- cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int8")
- else if nexpr.value isa Int16 then
- cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int16")
- else if nexpr.value isa UInt16 then
- cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "UInt16")
- else if nexpr.value isa Int32 then
- cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int32")
- else if nexpr.value isa UInt32 then
- cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "UInt32")
- else
- # Should not happen, and should be updated as new types are added
- abort
- end
- if cla != null then mtype = cla.mclass_type
- else if nexpr isa AFloatExpr then
- 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")
- 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")
- if cla != null then mtype = cla.mclass_type
- else if nexpr isa ASuperstringExpr then
- 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")
- if cla != null then mtype = cla.mclass_type
- else
- modelbuilder.error(self, "Error: untyped attribute `{mreadpropdef}`. Implicit typing allowed only for literals and new.")
- end
-
+ mtype = infer_static_type(modelbuilder, nexpr, mclassdef, mmodule, mreadpropdef)
if mtype == null then return
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
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
+ # Detect the static type from the value assigned to the attribute `self`
+ #
+ # Return the static type if it can be safely inferred.
+ private fun infer_static_type(modelbuilder: ModelBuilder, nexpr: AExpr,
+ mclassdef: MClassDef, mmodule: MModule, mreadpropdef: MPropDef): nullable MType
+ do
+ var mtype = null
+ if nexpr isa ANewExpr then
+ mtype = modelbuilder.resolve_mtype_unchecked(mclassdef, nexpr.n_type, true)
+ else if nexpr isa AAsCastExpr then
+ 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
+ cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int")
+ else if nexpr.value isa Byte then
+ cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Byte")
+ else if nexpr.value isa Int8 then
+ cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int8")
+ else if nexpr.value isa Int16 then
+ cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int16")
+ else if nexpr.value isa UInt16 then
+ cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "UInt16")
+ else if nexpr.value isa Int32 then
+ cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int32")
+ else if nexpr.value isa UInt32 then
+ cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "UInt32")
+ else
+ # Should not happen, and should be updated as new types are added
+ abort
+ end
+ if cla != null then mtype = cla.mclass_type
+ else if nexpr isa AFloatExpr then
+ 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: nullable MClass
+ 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")
+ if cla != null then mtype = cla.mclass_type
+ else if nexpr isa ASuperstringExpr then
+ 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: 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 if nexpr isa AArrayExpr and nexpr.n_type == null and nexpr.n_exprs.not_empty then
+ # Non-empty arrays without an explicit type
+
+ var item_mtypes = new Set[MType]
+ var fails = false
+ for node in nexpr.n_exprs do
+ var item_mtype = infer_static_type(modelbuilder, node, mclassdef, mmodule, mreadpropdef)
+ if item_mtype == null then
+ fails = true
+ else
+ item_mtypes.add item_mtype
+ end
+ end
+
+ if fails then return null # Failed to infer some types
+
+ if item_mtypes.length > 1 then
+ modelbuilder.error(self, "Type Error: ambiguous array type {item_mtypes.join(" ")}")
+ end
+
+ mtype = mmodule.array_type(item_mtypes.first)
+ else if nexpr isa AUminusExpr and (nexpr.n_expr isa AIntegerExpr or nexpr.n_expr isa AFloatExpr) then
+ # The Int and Float unary - is defined in `kernel`, so this may
+ # result in an invalid behavior when using a custom kernel.
+ # A workaround is to declare the attribute static type.
+ # This is still very useful, especially to novice programmers.
+ mtype = infer_static_type(modelbuilder, nexpr.n_expr, mclassdef, mmodule, mreadpropdef)
+ else if nexpr isa AOnceExpr then
+ mtype = infer_static_type(modelbuilder, nexpr.n_expr, mclassdef, mmodule, mreadpropdef)
+ else
+ modelbuilder.error(self, "Error: untyped attribute `{mreadpropdef}`. Implicit typing allowed only for literals and new.")
+ end
+ return mtype
+ end
+
redef fun check_signature(modelbuilder)
do
var mpropdef = self.mpropdef
# 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
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)
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
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
# 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
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