Visit the AST and create the MClass objects

Property definitions

nitc :: modelize_class $ ModelBuilder :: build_a_mclass
	# 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

nitc :: actors_injection_phase $ ModelBuilder :: build_a_mclass
	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