# FIXME: better handling of the types
module model
-import poset
-import location
import mmodule
import mdoc
import ordered_tree
private var object_type_cache: nullable MClassType
+ # The type `Pointer`, super class to all extern classes
+ var pointer_type: MClassType = self.get_primitive_class("Pointer").mclass_type is lazy
+
# The primitive type `Bool`
fun bool_type: MClassType
do
return get_primitive_class("Sys").mclass_type
end
+ fun finalizable_type: nullable MClassType
+ do
+ var clas = self.model.get_mclasses_by_name("Finalizable")
+ if clas == null then return null
+ return get_primitive_class("Finalizable").mclass_type
+ end
+
# Force to get the primitive class named `name` or abort
fun get_primitive_class(name: String): MClass
do
var cla = self.model.get_mclasses_by_name(name)
if cla == null then
if name == "Bool" then
- var c = new MClass(self, name, 0, enum_kind, public_visibility)
- var cladef = new MClassDef(self, c.mclass_type, new Location(null, 0,0,0,0), new Array[String])
+ var c = new MClass(self, name, null, enum_kind, public_visibility)
+ var cladef = new MClassDef(self, c.mclass_type, new Location(null, 0,0,0,0))
return c
end
print("Fatal Error: no primitive class {name}")
# 0 if the class is not generic
var arity: Int
+ # Each generic formal parameters in order.
+ # is empty if the class is not generic
+ var mparameters = new Array[MParameterType]
+
# The kind of the class (interface, abstract class, etc.)
# In Nit, the kind of a class cannot evolve in refinements
var kind: MClassKind
# In Nit, the visibility of a class cannot evolve in refinements
var visibility: MVisibility
- init(intro_mmodule: MModule, name: String, arity: Int, kind: MClassKind, visibility: MVisibility)
+ init(intro_mmodule: MModule, name: String, parameter_names: nullable Array[String], kind: MClassKind, visibility: MVisibility)
do
self.intro_mmodule = intro_mmodule
self.name = name
- self.arity = arity
+ if parameter_names == null then
+ self.arity = 0
+ else
+ self.arity = parameter_names.length
+ end
self.kind = kind
self.visibility = visibility
intro_mmodule.intro_mclasses.add(self)
# Create the formal parameter types
if arity > 0 then
+ assert parameter_names != null
var mparametertypes = new Array[MParameterType]
for i in [0..arity[ do
- var mparametertype = new MParameterType(self, i)
+ var mparametertype = new MParameterType(self, i, parameter_names[i])
mparametertypes.add(mparametertype)
end
+ self.mparameters = mparametertypes
var mclass_type = new MGenericType(self, mparametertypes)
self.mclass_type = mclass_type
self.get_mtype_cache.add(mclass_type)
# ENSURE: `bound_mtype.mclass == self.mclass`
var bound_mtype: MClassType
- # Name of each formal generic parameter (in order of declaration)
- var parameter_names: Array[String]
-
# The origin of the definition
var location: Location
# Example: "mymodule#MyClass"
redef var to_s: String
- init(mmodule: MModule, bound_mtype: MClassType, location: Location, parameter_names: Array[String])
+ init(mmodule: MModule, bound_mtype: MClassType, location: Location)
do
- assert bound_mtype.mclass.arity == parameter_names.length
self.bound_mtype = bound_mtype
self.mmodule = mmodule
self.mclass = bound_mtype.mclass
self.location = location
mmodule.mclassdefs.add(self)
mclass.mclassdefs.add(self)
- self.parameter_names = parameter_names
self.to_s = "{mmodule}#{mclass}"
end
return res
end
+ # Return the not nullable version of the type
+ # Is the type is already not nullable, then self is returned.
+ #
+ # Note: this just remove the `nullable` notation, but the result can still contains null.
+ # For instance if `self isa MNullType` or self is a a formal type bounded by a nullable type.
+ fun as_notnullable: MType
+ do
+ return self
+ end
+
private var as_nullable_cache: nullable MType = null
abort
end
+ # Is the virtual type fixed for a given resolved_receiver?
+ fun is_fixed(mmodule: MModule, resolved_receiver: MType): Bool
+ do
+ assert not resolved_receiver.need_anchor
+ var props = self.mproperty.lookup_definitions(mmodule, resolved_receiver)
+ if props.is_empty then
+ abort
+ end
+ for p in props do
+ if p.as(MVirtualTypeDef).is_fixed then return true
+ end
+ return false
+ end
+
redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
do
assert can_resolve_for(mtype, anchor, mmodule)
if resolved_reciever.as(MClassType).mclass.kind == enum_kind then return res
# If the resolved type isa MVirtualType, it means that self was bound to it, and cannot be unbound. self is just fixed. so return the resolution.
if res isa MVirtualType then return res
+ # If we are final, just return the resolution
+ if is_fixed(mmodule, resolved_reciever) then return res
# It the resolved type isa intern class, then there is no possible valid redefinition is any potentiel subclass. self is just fixed. so simply return the resolution
if res isa MClassType and res.mclass.kind == enum_kind then return res
# TODO: Add 'fixed' virtual type in the specification.
# The type associated the a formal parameter generic type of a class
#
# Each parameter type is associated to a specific class.
-# It's mean that all refinements of a same class "share" the parameter type,
-# but that a generic subclass has its on parameter types.
+# It means that all refinements of a same class "share" the parameter type,
+# but that a generic subclass has its own parameter types.
#
# However, in the sense of the meta-model, a parameter type of a class is
# a valid type in a subclass. The "in the sense of the meta-model" is
# FIXME: is `position` a better name?
var rank: Int
- # Internal name of the parameter type
- # Names of parameter types changes in each class definition
- # Therefore, this method return an internal name.
- # Example: return "G#1" for the second parameter of the class G
- # FIXME: add a way to get the real name in a classdef
- redef fun to_s do return "{mclass}#{rank}"
+ redef var name
+
+ redef fun to_s do return name
# Resolve the bound for a given resolved_receiver
# The result may be a other virtual type (or a parameter type)
#print "{class_name}: {self}/{mtype}/{anchor}?"
if mtype isa MGenericType and mtype.mclass == self.mclass then
- return mtype.arguments[self.rank]
+ var res = mtype.arguments[self.rank]
+ if anchor != null and res.need_anchor then
+ # Maybe the result can be resolved more if are bound to a final class
+ var r2 = res.anchor_to(mmodule, anchor)
+ if r2 isa MClassType and r2.mclass.kind == enum_kind then return r2
+ end
+ return res
end
# self is a parameter type of mtype (or of a super-class of mtype)
return mtype.collect_mclassdefs(mmodule).has(mclass.intro)
end
- init(mclass: MClass, rank: Int)
+ init(mclass: MClass, rank: Int, name: String)
do
self.mclass = mclass
self.rank = rank
+ self.name = name
end
end
redef fun need_anchor do return mtype.need_anchor
redef fun as_nullable do return self
+ redef fun as_notnullable do return mtype
redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
do
var res = self.mtype.resolve_for(mtype, anchor, mmodule, cleanup_virtual)
fun lookup_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
do
assert not mtype.need_anchor
- if mtype isa MNullableType then mtype = mtype.mtype
+ mtype = mtype.as_notnullable
var cache = self.lookup_definitions_cache[mmodule, mtype]
if cache != null then return cache
fun lookup_super_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
do
assert not mtype.need_anchor
- if mtype isa MNullableType then mtype = mtype.mtype
+ mtype = mtype.as_notnullable
# First, select all candidates
var candidates = new Array[MPROPDEF]
fun lookup_all_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
do
assert not mtype.need_anchor
- if mtype isa MNullableType then mtype = mtype.mtype
+ mtype = mtype.as_notnullable
var cache = self.lookup_all_definitions_cache[mmodule, mtype]
if cache != null then return cache
# Is the property defined at the top_level of the module?
# Currently such a property are stored in `Object`
- var is_toplevel: Bool writable = false
+ var is_toplevel: Bool = false is writable
# Is the property a constructor?
# Warning, this property can be inherited by subclasses with or without being a constructor
# therefore, you should use `is_init_for` the verify if the property is a legal constructor for a given class
- var is_init: Bool writable = false
+ var is_init: Bool = false is writable
+
+ # The constructor is a (the) root init with empty signature but a set of initializers
+ var is_root_init: Bool = false is writable
# The the property a 'new' contructor?
- var is_new: Bool writable = false
+ var is_new: Bool = false is writable
# Is the property a legal constructor for a given class?
# As usual, visibility is not considered.
end
# The signature attached to the property definition
- var msignature: nullable MSignature writable = null
+ var msignature: nullable MSignature = null is writable
+
+ # The signature attached to the `new` call on a root-init
+ # This is a concatenation of the signatures of the initializers
+ #
+ # REQUIRE `mproperty.is_root_init == (new_msignature != null)`
+ var new_msignature: nullable MSignature = null is writable
+
+ # List of initialisers to call in root-inits
+ #
+ # They could be setters or attributes
+ #
+ # REQUIRE `mproperty.is_root_init == (new_msignature != null)`
+ var initializers = new Array[MProperty]
# Is the method definition abstract?
- var is_abstract: Bool writable = false
+ var is_abstract: Bool = false is writable
# Is the method definition intern?
- var is_intern writable = false
+ var is_intern = false is writable
# Is the method definition extern?
- var is_extern writable = false
+ var is_extern = false is writable
end
# A local definition of an attribute
end
# The static type of the attribute
- var static_mtype: nullable MType writable = null
+ var static_mtype: nullable MType = null is writable
end
# A local definition of a virtual type
end
# The bound of the virtual type
- var bound: nullable MType writable = null
+ var bound: nullable MType = null is writable
# Is the bound fixed?
- var is_fixed writable = false
+ var is_fixed = false is writable
end
# A kind of class.