fun get_primitive_class(name: String): MClass
do
var cla = self.model.get_mclasses_by_name(name)
- if cla == null then
+ # Filter classes by introducing module
+ if cla != null then cla = [for c in cla do if self.in_importation <= c.intro_mmodule then c]
+ if cla == null or cla.is_empty then
if name == "Bool" and self.model.get_mclasses_by_name("Object") != null then
# Bool is injected because it is needed by engine to code the result
# of the implicit casts.
cladef.add_in_hierarchy
return c
end
- print("Fatal Error: no primitive class {name}")
+ print("Fatal Error: no primitive class {name} in {self}")
exit(1)
end
if cla.length != 1 then
- var msg = "Fatal Error: more than one primitive class {name}:"
+ var msg = "Fatal Error: more than one primitive class {name} in {self}:"
for c in cla do msg += " {c.full_name}"
print msg
#exit(1)
# is empty if the class is not generic
var mparameters = new Array[MParameterType]
+ # A string version of the signature a generic class.
+ #
+ # eg. `Map[K: nullable Object, V: nullable Object]`
+ #
+ # If the class in non generic the name is just given.
+ #
+ # eg. `Object`
+ fun signature_to_s: String
+ do
+ if arity == 0 then return name
+ var res = new FlatBuffer
+ res.append name
+ res.append "["
+ for i in [0..arity[ do
+ if i > 0 then res.append ", "
+ res.append mparameters[i].name
+ res.append ": "
+ res.append intro.bound_mtype.arguments[i].to_s
+ end
+ res.append "]"
+ return res.to_s
+ end
+
# Initialize `mparameters` from their names.
protected fun setup_parameter_names(parameter_names: nullable Array[String]) is
autoinit
#
# Warning: such a definition may not exist in the early life of the object.
# In this case, the method will abort.
+ #
+ # Use `try_intro` instead
var intro: MClassDef is noinit
+ # The definition that introduces the class or null if not yet known.
+ #
+ # See `intro`
+ fun try_intro: nullable MClassDef do
+ if isset _intro then return _intro else return null
+ end
+
# Return the class `self` in the class hierarchy of the module `mmodule`.
#
# SEE: `MModule::flatten_mclass_hierarchy`
var in_hierarchy: nullable POSetElement[MClassDef] = null
# Is the definition the one that introduced `mclass`?
- fun is_intro: Bool do return mclass.intro == self
+ fun is_intro: Bool do return isset mclass._intro and mclass.intro == self
# All properties introduced by the classdef
var intro_mproperties = new Array[MProperty]
redef fun c_name do return "null"
redef fun as_nullable do return self
- # Aborts on `null`
- redef fun as_notnull do abort # sorry...
+ redef var as_notnull = new MBottomType(model) is lazy
+ redef fun need_anchor do return false
+ redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual) do return self
+ redef fun can_resolve_for(mtype, anchor, mmodule) do return true
+
+ redef fun collect_mclassdefs(mmodule) do return new HashSet[MClassDef]
+
+ redef fun collect_mclasses(mmodule) do return new HashSet[MClass]
+
+ redef fun collect_mtypes(mmodule) do return new HashSet[MClassType]
+end
+
+# The special universal most specific type.
+#
+# This type is intended to be only used internally for type computation or analysis and should not be exposed to the user.
+# The bottom type can de used to denote things that are absurd, dead, or the absence of knowledge.
+#
+# Semantically it is the singleton `null.as_notnull`.
+class MBottomType
+ super MType
+ redef var model: Model
+ redef fun to_s do return "bottom"
+ redef fun full_name do return "bottom"
+ redef fun c_name do return "bottom"
+ redef fun as_nullable do return model.null_type
+ redef fun as_notnull do return self
redef fun need_anchor do return false
redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual) do return self
redef fun can_resolve_for(mtype, anchor, mmodule) do return true
# The each parameter (in order)
var mparameters: Array[MParameter]
+ # Returns a parameter named `name`, if any.
+ fun mparameter_by_name(name: String): nullable MParameter
+ do
+ for p in mparameters do
+ if p.name == name then return p
+ end
+ return null
+ end
+
# The return type (null for a procedure)
var return_mtype: nullable MType
# Example: for "(a: Int, b: Bool..., c: Char)" #-> vararg_rank=1
var vararg_rank: Int is noinit
- # The number or parameters
+ # The number of parameters
fun arity: Int do return mparameters.length
+ # The number of non-default parameters
+ #
+ # The number of default parameters is then `arity-min_arity`.
+ #
+ # Note that there cannot be both varargs and default prameters, thus
+ # if `vararg_rank != -1` then `min_arity` == `arity`
+ fun min_arity: Int
+ do
+ if vararg_rank != -1 then return arity
+ var res = 0
+ for p in mparameters do
+ if not p.is_default then res += 1
+ end
+ return res
+ end
+
redef fun to_s
do
var b = new FlatBuffer
# Is the parameter a vararg?
var is_vararg: Bool
+ # Is the parameter a default one?
+ var is_default: Bool
+
redef fun to_s
do
if is_vararg then
do
if not self.mtype.need_anchor then return self
var newtype = self.mtype.resolve_for(mtype, anchor, mmodule, cleanup_virtual)
- var res = new MParameter(self.name, newtype, self.is_vararg)
+ var res = new MParameter(self.name, newtype, self.is_vararg, self.is_default)
return res
end