if not nclassdef isa AStdClassdef then return
var mclassdef = nclassdef.mclassdef
- var mclass = nclassdef.mclass
+ if mclassdef == null then return
+ var mclass = mclassdef.mclass
# We only need to do this once per class
- if mclass.intro != mclassdef then return
+ if not mclassdef.is_intro then return
if mclass.kind != extern_kind then return
do
# Get the mmodule
var mmodule = nmodule.mmodule
- assert mmodule != null
+ if mmodule == null then return
self.mmodule = mmodule
# If no decl block then quit
if primtives_annotations.has(name) then return
var mmodule = self.mmodule
- assert mmodule != null
+ if mmodule == null then return
# Lazily build the full user-list
var annots = user_annotations.get_or_null(mmodule)
redef fun process_nmodule(nmodule)
do
# The AST node is not enough, we need also the associated model element
- var mmodule = nmodule.mmodule.as(not null)
+ var mmodule = nmodule.mmodule
+ if mmodule == null then return
# For the specific job we have, the simpler it to launch a visitor on
# all elements of the AST.
var visitor = new DivByZeroVisitor(toolcontext, mmodule)
do
# Get the mmodule
var mmodule = nmodule.mmodule
- assert mmodule != null
+ if mmodule == null then return
var source = nmodule.location.file
redef fun process_nmodule(nmodule)
do
for npropdef in nmodule.inits_to_retype do
- var v = new PreciseTypeVisitor(npropdef, npropdef.mpropdef.mclassdef, toolcontext)
+ var mpropdef = npropdef.mpropdef
+ if mpropdef == null then continue # skip error
+ var v = new PreciseTypeVisitor(npropdef, mpropdef.mclassdef, toolcontext)
npropdef.accept_precise_type_visitor v
end
end
if nmodule == null then continue # Skip error
# Load imported module
build_module_importation(nmodule)
-
- mmodules.add(nmodule.mmodule.as(not null))
+ var mmodule = nmodule.mmodule
+ if mmodule == null then continue # skip error
+ mmodules.add mmodule
end
var time1 = get_time
self.toolcontext.info("*** END PARSE: {time1-time0} ***", 2)
if nmodule == null then continue # Skip error
# Load imported module
build_module_importation(nmodule)
-
- res.add(nmodule.mmodule.as(not null))
+ var mmodule = nmodule.mmodule
+ if mmodule == null then continue # Skip error
+ res.add mmodule
end
end
return res
var nmodule = self.load_module(af)
if nmodule == null then continue # Skip error
build_module_importation(nmodule)
- mmodules.add(nmodule.mmodule.as(not null))
+ var mmodule = nmodule.mmodule
+ if mmodule == null then continue # Skip error
+ mmodules.add mmodule
else
self.toolcontext.info("ignore file {af}", 2)
end
if nmodule == null then continue # Skip error
# Load imported module
build_module_importation(nmodule)
-
- mmodules.add(nmodule.mmodule.as(not null))
+ var mmodule = nmodule.mmodule
+ if mmodule == null then continue # Skip error
+ mmodules.add mmodule
end
var time1 = get_time
self.toolcontext.info("*** END PARSE: {time1-time0} ***", 2)
if res == null then return null # Forward error
# Load imported module
build_module_importation(res)
- return res.mmodule.as(not null)
+ return res.mmodule
end
# Search a module `name` from path `lookpaths`.
if aimport.n_name.n_quad != null then mgroup = null # Start from top level
for grp in aimport.n_name.n_path do
var path = search_mmodule_by_name(grp, mgroup, grp.text)
- if path == null then return # Skip error
+ if path == null then
+ nmodule.mmodule = null # invalidate the module
+ return # Skip error
+ end
mgroup = path.mgroup
end
var mod_name = aimport.n_name.n_id.text
var sup = self.get_mmodule_by_name(aimport.n_name, mgroup, mod_name)
- if sup == null then continue # Skip error
+ if sup == null then
+ nmodule.mmodule = null # invalidate the module
+ continue # Skip error
+ end
aimport.mmodule = sup
imported_modules.add(sup)
var mvisibility = aimport.n_visibility.mvisibility
if mvisibility == protected_visibility then
error(aimport.n_visibility, "Error: only properties can be protected.")
+ nmodule.mmodule = null # invalidate the module
return
end
if sup == mmodule then
error(aimport.n_name, "Error: Dependency loop in module {mmodule}.")
+ nmodule.mmodule = null # invalidate the module
end
if sup.in_importation < mmodule then
error(aimport.n_name, "Error: Dependency loop between modules {mmodule} and {sup}.")
+ nmodule.mmodule = null # invalidate the module
return
end
mmodule.set_visibility_for(sup, mvisibility)
if stdimport then
var mod_name = "standard"
var sup = self.get_mmodule_by_name(nmodule, null, mod_name)
- if sup != null then # Skip error
+ if sup == null then
+ nmodule.mmodule = null # invalidate the module
+ else # Skip error
imported_modules.add(sup)
mmodule.set_visibility_for(sup, public_visibility)
end
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)
#
# 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]
# Run `process_mainmodule` on all phases
fun run_global_phases(mmodules: Array[MModule])
do
- var mainmodule = make_main_module(mmodules)
- for phase in phases_list do
- if phase.disabled then continue
- phase.process_mainmodule(mainmodule, mmodules)
+ if not mmodules.is_empty then
+ var mainmodule = make_main_module(mmodules)
+ for phase in phases_list do
+ if phase.disabled then continue
+ phase.process_mainmodule(mainmodule, mmodules)
+ end
end
+
+ check_errors
+ errors_info
end
end
return res
end
+ # Like `try_get_mclass_by_name` but display an error message when the class is not found
+ fun get_mclass_by_name(node: ANode, mmodule: MModule, name: String): nullable MClass
+ do
+ var mclass = try_get_mclass_by_name(node, mmodule, name)
+ if mclass == null then
+ error(node, "Type Error: missing primitive class `{name}'.")
+ end
+ return mclass
+ end
+
# Return a property named `name` on the type `mtype` visible in the module `mmodule`.
# Visibility in modules is correctly handled.
# Protected properties are returned (it is up to the caller to check and reject protected properties).
if mtype isa MGenericType then
var mclass = mtype.mclass
for i in [0..mclass.arity[ do
- var bound = mclass.intro.bound_mtype.arguments[i]
+ var intro = mclass.try_intro
+ if intro == null then return null # skip error
+ var bound = intro.bound_mtype.arguments[i]
var nt = ntype.n_types[i]
var mt = resolve_mtype(mmodule, mclassdef, nt)
if mt == null then return null # forward error
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.mproject == mmodule.mgroup.mproject then
- error(nclassdef, "Error: A class named `{other.full_name}` is already defined in module `{other.intro_mmodule}` at {other.intro.location}.")
+ # 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
# Visit the AST and set the super-types of the `MClassDef` objects
private fun collect_a_mclassdef_inheritance(nmodule: AModule, nclassdef: AClassdef)
do
- var mmodule = nmodule.mmodule.as(not null)
+ var mmodule = nmodule.mmodule
+ if mmodule == null then return
var objectclass = try_get_mclass_by_name(nmodule, mmodule, "Object")
var pointerclass = try_get_mclass_by_name(nmodule, mmodule, "Pointer")
- var mclass = nclassdef.mclass.as(not null)
- var mclassdef = nclassdef.mclassdef.as(not null)
+ var mclass = nclassdef.mclass
+ if mclass == null then return
+ var mclassdef = nclassdef.mclassdef
+ if mclassdef == null then return
# Do we need to specify Object as a super class?
var specobject = true
# Check the validity of the specialization heirarchy
private fun check_supertypes(nmodule: AModule, nclassdef: AClassdef)
do
- var mmodule = nmodule.mmodule.as(not null)
- var mclass = nclassdef.mclass.as(not null)
- var mclassdef = nclassdef.mclassdef.as(not null)
+ var mmodule = nmodule.mmodule
+ if mmodule == null then return
+ var mclass = nclassdef.mclass
+ if mclass == null then return
+ var mclassdef = nclassdef.mclassdef
+ if mclassdef == null then return
for s in mclassdef.supertypes do
if s.is_subtype(mmodule, mclassdef.bound_mtype, mclassdef.bound_mtype) then
# Force building recursively
if nmodule.build_classes_is_done then return
nmodule.build_classes_is_done = true
- var mmodule = nmodule.mmodule.as(not null)
+ var mmodule = nmodule.mmodule
+ if mmodule == null then return
for imp in mmodule.in_importation.direct_greaters do
var nimp = mmodule2node(imp)
if nimp != null then build_classes(nimp)
# Check clash of ancestors
for nclassdef in nmodule.n_classdefs do
- var mclassdef = nclassdef.mclassdef.as(not null)
+ var mclassdef = nclassdef.mclassdef
+ if mclassdef == null then continue
var superclasses = new HashMap[MClass, MClassType]
for scd in mclassdef.in_hierarchy.greaters do
for st in scd.supertypes do
# Check that the superclasses are not already known (by transitivity)
for nclassdef in nmodule.n_classdefs do
if not nclassdef isa AStdClassdef then continue
- var mclassdef = nclassdef.mclassdef.as(not null)
+ var mclassdef = nclassdef.mclassdef
+ if mclassdef == null then continue
# Get the direct superclasses
# Since we are a mclassdef, just look at the mclassdef hierarchy
# Force building recursively
if nclassdef.build_properties_is_done then return
nclassdef.build_properties_is_done = true
- var mclassdef = nclassdef.mclassdef.as(not null)
+ var mclassdef = nclassdef.mclassdef
+ if mclassdef == null then return # skip error
if mclassdef.in_hierarchy == null then return # Skip error
for superclassdef in mclassdef.in_hierarchy.direct_greaters do
if not mclassdef2nclassdef.has_key(superclassdef) then continue
for p in spd.initializers do
if p != longest.initializers[i] then
self.error(nclassdef, "Error: conflict for inherited inits {spd}({spd.initializers.join(", ")}) and {longest}({longest.initializers.join(", ")})")
+ # TODO: invalidate the initializer to avoid more errors
return
end
i += 1
var ret_type = mysignature.return_mtype
if ret_type != null and precursor_ret_type == null then
modelbuilder.error(nsig.n_type.as(not null), "Redef Error: {mpropdef.mproperty} is a procedure, not a function.")
+ self.mpropdef.msignature = null
return
end
var node = nsig.n_params[i]
if not modelbuilder.check_sametype(node, mmodule, mclassdef.bound_mtype, myt, prt) then
modelbuilder.error(node, "Redef Error: Wrong type for parameter `{mysignature.mparameters[i].name}'. found {myt}, expected {prt} as in {mpropdef.mproperty.intro}.")
+ self.mpropdef.msignature = null
end
end
end
ret_type = precursor_ret_type
else if not modelbuilder.check_subtype(node, mmodule, mclassdef.bound_mtype, ret_type, precursor_ret_type) then
modelbuilder.error(node, "Redef Error: Wrong return type. found {ret_type}, expected {precursor_ret_type} as in {mpropdef.mproperty.intro}.")
+ self.mpropdef.msignature = null
end
end
end
else if atautoinit != null then
modelbuilder.error(atautoinit, "Error: a autoinit attribute needs a value")
end
+ has_value = true
return
end
is_lazy = true
var time1 = get_time
self.info("*** END SEMANTIC ANALYSIS: {time1-time0} ***", 2)
- errors_info
+ self.check_errors
end
# Process the given `phase` on the `npropdef`
# Collect initializers and build the auto-init
fun do_auto_super_init(modelbuilder: ModelBuilder)
do
- var mclassdef = self.parent.as(AClassdef).mclassdef.as(not null)
- var mpropdef = self.mpropdef.as(not null)
+ var mclassdef = self.parent.as(AClassdef).mclassdef
+ if mclassdef == null then return # skip error
+ var mpropdef = self.mpropdef
+ if mpropdef == null then return # skip error
var mmodule = mpropdef.mclassdef.mmodule
var anchor = mclassdef.bound_mtype
var recvtype = mclassdef.mclass.mclass_type
fun get_mclass(node: ANode, name: String): nullable MClass
do
- var mclass = modelbuilder.try_get_mclass_by_name(node, mmodule, name)
- if mclass == null then
- self.modelbuilder.error(node, "Type Error: missing primitive class `{name}'.")
- end
+ var mclass = modelbuilder.get_mclass_by_name(node, mmodule, name)
return mclass
end
if recvtype isa MNullType then
# `null` only accepts some methods of object.
if name == "==" or name == "!=" or name == "is_same_instance" then
- unsafe_type = mmodule.object_type.as_nullable
+ var objclass = get_mclass(node, "Object")
+ if objclass == null then return null # Forward error
+ unsafe_type = objclass.mclass_type
else
self.error(node, "Error: Method '{name}' call on 'null'.")
return null
end
- var msignature = mpropdef.new_msignature or else mpropdef.msignature.as(not null)
+ var msignature = mpropdef.new_msignature or else mpropdef.msignature
+ if msignature == null then return null # skip error
msignature = resolve_for(msignature, recvtype, recv_is_self).as(MSignature)
var erasure_cast = false
var nblock = self.n_block
if nblock == null then return
- var mpropdef = self.mpropdef.as(not null)
+ var mpropdef = self.mpropdef
+ if mpropdef == null then return # skip error
+
var v = new TypeVisitor(modelbuilder, mpropdef.mclassdef.mmodule, mpropdef)
self.selfvariable = v.selfvariable
var mmethoddef = self.mpropdef.as(not null)
- for i in [0..mmethoddef.msignature.arity[ do
- var mtype = mmethoddef.msignature.mparameters[i].mtype
- if mmethoddef.msignature.vararg_rank == i then
+ var msignature = mmethoddef.msignature
+ if msignature == null then return # skip error
+ for i in [0..msignature.arity[ do
+ var mtype = msignature.mparameters[i].mtype
+ if msignature.vararg_rank == i then
var arrayclass = v.get_mclass(self.n_signature.n_params[i], "Array")
if arrayclass == null then return # Skip error
mtype = arrayclass.get_mtype([mtype])
end
v.visit_stmt(nblock)
- if not nblock.after_flow_context.is_unreachable and mmethoddef.msignature.return_mtype != null then
+ if not nblock.after_flow_context.is_unreachable and msignature.return_mtype != null then
# We reach the end of the function without having a return, it is bad
v.error(self, "Control error: Reached end of function (a 'return' with a value was expected).")
end
do
if not has_value then return
- var mpropdef = self.mpropdef.as(not null)
+ var mpropdef = self.mpropdef
+ if mpropdef == null then return # skip error
+
var v = new TypeVisitor(modelbuilder, mpropdef.mclassdef.mmodule, mpropdef)
self.selfvariable = v.selfvariable
var decltype = mtype
if mtype == null or mtype isa MNullType then
- decltype = v.get_mclass(self, "Object").mclass_type.as_nullable
+ var objclass = v.get_mclass(self, "Object")
+ if objclass == null then return # skip error
+ decltype = objclass.mclass_type.as_nullable
if mtype == null then mtype = decltype
end
var t = v.merge_types(self, [t1, t2])
if t == null then
- t = v.mmodule.object_type
+ var c = v.get_mclass(self, "Object")
+ if c == null then return # forward error
+ t = c.mclass_type
if t2 isa MNullableType then
t = t.as_nullable
end
var mclass = v.get_mclass(self, "String")
if mclass == null then return # Forward error
self.mtype = mclass.mclass_type
+ var objclass = v.get_mclass(self, "Object")
+ if objclass == null then return # Forward error
+ var objtype = objclass.mclass_type
for nexpr in self.n_exprs do
- v.visit_expr_subtype(nexpr, v.mmodule.object_type)
+ v.visit_expr_subtype(nexpr, objtype)
end
end
end
var mpropdefs = mproperty.lookup_definitions(v.mmodule, unsafe_type)
assert mpropdefs.length == 1
var mpropdef = mpropdefs.first
- var attr_type = mpropdef.static_mtype.as(not null)
+ var attr_type = mpropdef.static_mtype
+ if attr_type == null then return # skip error
attr_type = v.resolve_for(attr_type, recvtype, self.n_expr isa ASelfExpr)
self.attr_type = attr_type
end
return tags.has("all") or tags.has(tag)
end
- # Output all current stacked messages and display total error informations
+ # Output all current stacked messages
#
# Return true if no errors occurred.
#
# If some errors occurred, the behavior depends on the value of `keep_going`.
- # If `keep_going` is false, then the program exits.
- # Else, the error count and the warning count are reset and false is returned.
+ # If `keep_going` is false, then the total error informations is displayed and the program exits.
+ # Else, false is returned.
fun check_errors: Bool
do
if messages.length > 0 then
end
if error_count > 0 then
- errors_info
- if not keep_going then exit(1)
+ if not keep_going then
+ errors_info
+ exit(1)
+ end
return false
end
return true
end
- # Display (and reset) total error informations
+ # Display total error informations
fun errors_info
do
if error_count == 0 and warning_count == 0 then return
if opt_no_color.value then return
sys.stderr.write "Errors: {error_count}. Warnings: {warning_count}.\n"
- error_count = 0
- warning_count = 0
end
# Display an error
-Fatal Error: no primitive class NativeArray
+Fatal Error: no primitive class NativeArray in error_needed_method_alt4
-Fatal Error: no primitive class NativeArray
+Fatal Error: no primitive class NativeArray in error_needed_method_alt7