nitc :: ModelBuilder :: build_a_mclass
MClass
objects
# Visit the AST and create the `MClass` objects
private fun build_a_mclass(nmodule: AModule, nclassdef: AClassdef)
do
var mmodule = nmodule.mmodule.as(not null)
var name: String
var nkind: nullable AClasskind
var mkind: MClassKind
var nvisibility: nullable AVisibility
var mvisibility: nullable MVisibility
var arity = 0
var names = new Array[String]
var mclass
if nclassdef isa AStdClassdef then
var qid = nclassdef.n_qid
assert qid != null
name = qid.n_id.text
nkind = nclassdef.n_classkind
mkind = nkind.mkind
nvisibility = nclassdef.n_visibility
mvisibility = nvisibility.mvisibility
arity = nclassdef.n_formaldefs.length
if mvisibility == protected_visibility then
error(nvisibility, "Error: only properties can be protected.")
return
else if mvisibility == intrude_visibility then
error(nvisibility, "Error: intrude is not a legal visibility for classes.")
return
end
# Collect formal parameter names
for i in [0..arity[ do
var nfd = nclassdef.n_formaldefs[i]
var ptname = nfd.n_id.text
if names.has(ptname) then
error(nfd, "Error: a formal parameter type `{ptname}` already exists.")
return
end
for c in ptname.chars do if c >= 'a' and c<= 'z' then
warning(nfd, "formal-type-name", "Warning: lowercase in the formal parameter type `{ptname}`.")
break
end
names.add(ptname)
end
mclass = try_get_mclass_by_qid(qid, mmodule)
if mclass == null and (qid.n_qualified != null or nclassdef.n_kwredef != null) then
class_not_found(qid, mmodule)
nclassdef.is_broken = true
return
end
else if nclassdef isa ATopClassdef and nclassdef.n_propdefs.first.as(AMethPropdef).n_methid.collect_text == "sys" then
# Special case to keep `sys` in object.
# Needed to keep working bootstrap and a working java FFI together.
# TODO: remove once safe to remove
name = "Object"
nkind = null
mkind = interface_kind
nvisibility = null
mvisibility = public_visibility
mclass = try_get_mclass_by_name(nclassdef, mmodule, name)
else
name = "Sys"
nkind = null
mkind = concrete_kind
nvisibility = null
mvisibility = public_visibility
mclass = try_get_mclass_by_name(nclassdef, mmodule, name)
end
if mclass == null then
# Check for conflicting class full-names in the package
if mmodule.mgroup != null and mvisibility >= protected_visibility then
var mclasses = model.get_mclasses_by_name(name)
if mclasses != null then for other in mclasses do
if other.intro_mmodule.mgroup != null and other.intro_mmodule.mgroup.mpackage == mmodule.mgroup.mpackage then
# Skip classes that are buggy
if other.try_intro == null then continue
warning(nclassdef, "full-name-conflict", "Error: a class named `{other.full_name}` is already defined in module `{other.intro_mmodule}` at {other.intro.location}.")
break
end
end
end
mclass = new MClass(mmodule, name, nclassdef.location, names, mkind, mvisibility)
#print "new class {mclass}"
else if nclassdef isa AStdClassdef and nmodule.mclass2nclassdef.has_key(mclass) then
error(nclassdef, "Error: a class `{name}` is already defined at line {nmodule.mclass2nclassdef[mclass].location.line_start}.")
mclass.is_broken = true
return
else if nclassdef isa AStdClassdef and nclassdef.n_kwredef == null then
error(nclassdef, "Redef Error: `{name}` is an imported class. Add the `redef` keyword to refine it.")
mclass.is_broken = true
return
else if arity != 0 and mclass.arity != arity then
error(nclassdef, "Redef Error: expected {mclass.arity} formal parameter(s) for {mclass.signature_to_s}; got {arity}.")
mclass.is_broken = true
return
else if nkind != null and mkind != concrete_kind and mclass.kind != mkind then
error(nkind, "Redef Error: refinement changed the kind from `{mclass.kind}` to `{mkind}`.")
else if nvisibility != null and mvisibility != public_visibility and mclass.visibility != mvisibility then
error(nvisibility, "Redef Error: refinement changed the visibility from `{mclass.visibility}` to `{mvisibility}`")
end
nclassdef.mclass = mclass
if not nmodule.mclass2nclassdef.has_key(mclass) then
nmodule.mclass2nclassdef[mclass] = nclassdef
nclassdef.all_defs = [nclassdef]
else
nmodule.mclass2nclassdef[mclass].all_defs.add(nclassdef)
end
end
src/modelize/modelize_class.nit:37,2--146,4
redef fun build_a_mclass(nmodule, nclassdef)
do
super
# Catch the wanted annotation
var at = nclassdef.get_single_annotation("actor", self)
if at == null then return
# Get context information
var mod = nmodule.mmodule
if mod == null then return
var mclass = nclassdef.mclass
if mclass == null then return
if mclass.intro_mmodule != mod then
error(at, "`actor` can only be used at introductions.")
return
end
var l = at.location
var injected_name = "Proxy"
# Create the actor class
var actor_class = new MClass(mod, injected_name + mclass.name, l, null, concrete_kind, public_visibility)
var actor_class_definition = new MClassDef(mod, actor_class.mclass_type, l)
actor_class_definition.set_supertypes([mod.object_type])
var proxy_classes = mclass.model.get_mclasses_by_name("Proxy")
assert proxy_classes != null
var proxy_class = proxy_classes.first
actor_class_definition.supertypes.add(proxy_class.mclass_type)
# Register it
mclass.actor = actor_class
end
src/frontend/actors_injection_phase.nit:23,2--56,4