import poset
import opts
import toolcontext
+import phase
###
super
option_context.add_option(opt_path, opt_only_parse, opt_only_metamodel)
end
+
+ fun modelbuilder: ModelBuilder do return modelbuilder_real.as(not null)
+ private var modelbuilder_real: nullable ModelBuilder = null
end
# A model builder knows how to load nit source files and build the associated model
# The toolcontext used to control the interaction with the user (getting options and displaying messages)
var toolcontext: ToolContext
+ fun run_phases
+ do
+ var mmodules = model.mmodules.to_a
+ model.mmodule_importation_hierarchy.sort(mmodules)
+ var nmodules = new Array[AModule]
+ for mm in mmodules do
+ nmodules.add(mmodule2nmodule[mm])
+ end
+ toolcontext.run_phases(nmodules)
+ end
+
# Instantiate a modelbuilder for a model and a toolcontext
# Important, the options of the toolcontext must be correctly set (parse_option already called)
init(model: Model, toolcontext: ToolContext)
do
self.model = model
self.toolcontext = toolcontext
+ assert toolcontext.modelbuilder_real == null
+ toolcontext.modelbuilder_real = self
# Setup the paths value
paths.append(toolcontext.opt_path.value)
- var path_env = once ("NIT_PATH".to_symbol).environ
+ var path_env = "NIT_PATH".environ
if not path_env.is_empty then
paths.append(path_env.split_with(':'))
end
- path_env = once ("NIT_DIR".to_symbol).environ
+ path_env = "NIT_DIR".environ
if not path_env.is_empty then
var libname = "{path_env}/lib"
if libname.file_exists then paths.add(libname)
# FIXME: Maybe just let the client do the loop (instead of playing with Sequences)
fun parse_and_build(modules: Sequence[String]): Array[MModule]
do
+ var mmodules = parse(modules)
+
+ if self.toolcontext.opt_only_parse.value then
+ self.toolcontext.info("--only-parse: stop processing", 2)
+ return new Array[MModule]
+ end
+
+ # Build the model
+ var time1 = get_time
+ self.toolcontext.info("*** BUILD MODEL ***", 1)
+ self.build_all_classes
+ var time2 = get_time
+ self.toolcontext.info("*** END BUILD MODEL: {time2-time1} ***", 2)
+
+ self.toolcontext.check_errors
+
+ return mmodules
+ end
+
+ fun parse(modules: Sequence[String]): Array[MModule]
+ do
var time0 = get_time
# Parse and recursively load
self.toolcontext.info("*** PARSE ***", 1)
self.toolcontext.info("*** END PARSE: {time1-time0} ***", 2)
self.toolcontext.check_errors
-
- # Build the model
- self.toolcontext.info("*** BUILD MODEL ***", 1)
- self.build_all_classes
- var time2 = get_time
- self.toolcontext.info("*** END BUILD MODEL: {time2-time1} ***", 2)
-
- self.toolcontext.check_errors
-
return mmodules
end
var origmmodule = mmodule
var modules = model.get_mmodules_by_name(name)
+ var tries = new Array[String]
+
var lastmodule = mmodule
while mmodule != null do
var dirname = mmodule.location.file.filename.dirname
# Second, try the directory to find a file
var try_file = dirname + "/" + name + ".nit"
+ tries.add try_file
if try_file.file_exists then
var res = self.load_module(owner, try_file.simplify_path)
if res == null then return null # Forward error
var candidate: nullable String = null
for dirname in lookpaths do
var try_file = (dirname + "/" + name + ".nit").simplify_path
+ tries.add try_file
if try_file.file_exists then
if candidate == null then
candidate = try_file
end
if candidate == null then
if origmmodule != null then
- error(anode, "Error: cannot find module {name} from {origmmodule}")
+ error(anode, "Error: cannot find module {name} from {origmmodule}. tried {tries.join(", ")}")
else
- error(anode, "Error: cannot find module {name}")
+ error(anode, "Error: cannot find module {name}. tried {tries.join(", ")}")
end
return null
end
private fun build_module_importation(nmodule: AModule)
do
if nmodule.is_importation_done then return
+ nmodule.is_importation_done = true
var mmodule = nmodule.mmodule.as(not null)
var stdimport = true
var imported_modules = new Array[MModule]
end
self.toolcontext.info("{mmodule} imports {imported_modules.join(", ")}", 3)
mmodule.set_imported_mmodules(imported_modules)
- nmodule.is_importation_done = true
end
# All the loaded modules
do
for nmodule in self.nmodules do
build_classes(nmodule)
+ for nclassdef in nmodule.n_classdefs do
+ build_properties(nclassdef)
+ end
end
end
if mclass == null then
mclass = new MClass(mmodule, name, arity, 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}.")
+ 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.")
return
error(nvisibility, "Error: refinement changed the visibility from a {mclass.visibility} to a {mvisibility}")
end
nclassdef.mclass = mclass
+ nmodule.mclass2nclassdef[mclass] = nclassdef
end
# Visit the AST and create the MClassDef objects
do
var mmodule = nmodule.mmodule.as(not null)
var objectclass = try_get_mclass_by_name(nmodule, mmodule, "Object")
- var mclass = nclassdef.mclass.as(not null)
+ var mclass = nclassdef.mclass
+ if mclass == null then return # Skip error
#var mclassdef = nclassdef.mclassdef.as(not null)
var names = new Array[String]
var nfd = nclassdef.n_formaldefs[i]
var nfdt = nfd.n_type
if nfdt != null then
- var bound = resolve_mtype(nclassdef, nfdt)
+ var bound = resolve_mtype_unchecked(nclassdef, nfdt, false)
if bound == null then return # Forward error
if bound.need_anchor then
# No F-bounds!
bounds.add(objectclass.mclass_type.as_nullable)
else
# Inherit the bound
- bounds.add(mclass.mclassdefs.first.bound_mtype.as(MGenericType).arguments[i])
+ bounds.add(mclass.intro.bound_mtype.arguments[i])
end
end
end
end
end
- # Visit the AST and set the super-types of the MClass objects (ie compute the inheritance)
- private fun build_a_mclassdef_inheritance(nmodule: AModule, nclassdef: AClassdef)
+ # 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 objectclass = try_get_mclass_by_name(nmodule, mmodule, "Object")
for nsc in nclassdef.n_superclasses do
specobject = false
var ntype = nsc.n_type
- var mtype = resolve_mtype(nclassdef, ntype)
+ var mtype = resolve_mtype_unchecked(nclassdef, ntype, false)
if mtype == null then continue # Skip because of error
if not mtype isa MClassType then
error(ntype, "Error: supertypes cannot be a formal type")
end
# Check the validity of the specialization heirarchy
- # FIXME Stub implementation
private fun check_supertypes(nmodule: AModule, nclassdef: AClassdef)
do
var mmodule = nmodule.mmodule.as(not null)
var objectclass = try_get_mclass_by_name(nmodule, mmodule, "Object")
var mclass = nclassdef.mclass.as(not null)
var mclassdef = nclassdef.mclassdef.as(not null)
+
+ for s in mclassdef.supertypes do
+ if s.is_subtype(mmodule, mclassdef.bound_mtype, mclassdef.bound_mtype) then
+ error(nclassdef, "Error: Inheritance loop for class {mclass} with type {s}")
+ end
+ end
end
# Build the classes of the module `nmodule'.
do
# Force building recursively
if nmodule.build_classes_is_done then return
+ nmodule.build_classes_is_done = true
var mmodule = nmodule.mmodule.as(not null)
for imp in mmodule.in_importation.direct_greaters do
+
build_classes(mmodule2nmodule[imp])
end
self.build_a_mclassdef(nmodule, nclassdef)
end
+ for nclassdef in nmodule.n_classdefs do
+ if nclassdef.mclassdef == null then return # forward error
+ end
+
# Create inheritance on all classdefs
for nclassdef in nmodule.n_classdefs do
- self.build_a_mclassdef_inheritance(nmodule, nclassdef)
+ self.collect_a_mclassdef_inheritance(nmodule, nclassdef)
end
- # TODO: Check that the super-class is not intrusive
+ # Create the mclassdef hierarchy
+ for nclassdef in nmodule.n_classdefs do
+ var mclassdef = nclassdef.mclassdef.as(not null)
+ mclassdef.add_in_hierarchy
+ end
- # TODO: Check that the super-class is not already known (by transitivity)
+ # Check inheritance
+ for nclassdef in nmodule.n_classdefs do
+ self.check_supertypes(nmodule, nclassdef)
+ end
+ # Check unchecked ntypes
for nclassdef in nmodule.n_classdefs do
- self.build_properties(nclassdef)
+ if nclassdef isa AStdClassdef then
+ # check bound of formal parameter
+ for nfd in nclassdef.n_formaldefs do
+ var nfdt = nfd.n_type
+ if nfdt != null and nfdt.mtype != null then
+ var bound = resolve_mtype(nclassdef, nfdt)
+ if bound == null then return # Forward error
+ end
+ end
+ # check declared super types
+ for nsc in nclassdef.n_superclasses do
+ var ntype = nsc.n_type
+ if ntype.mtype != null then
+ var mtype = resolve_mtype(nclassdef, ntype)
+ if mtype == null then return # Forward error
+ end
+ end
+ end
+
end
- nmodule.build_classes_is_done = true
+ # TODO: Check that the super-class is not intrusive
+
+ # TODO: Check that the super-class is not already known (by transitivity)
end
# Register the nmodule associated to each mmodule
do
# Force building recursively
if nclassdef.build_properties_is_done then return
+ nclassdef.build_properties_is_done = true
var mclassdef = nclassdef.mclassdef.as(not null)
if mclassdef.in_hierarchy == null then return # Skip error
for superclassdef in mclassdef.in_hierarchy.direct_greaters do
npropdef.check_signature(self, nclassdef)
end
process_default_constructors(nclassdef)
- nclassdef.build_properties_is_done = true
end
# Introduce or inherit default constructor
if inhc2 == null then inhc2 = c
if inhc2 == inhc then continue
if inhc != null then
- self.error(nclassdef, "Cannot provide a defaut constructor: conflict for {inhc} and {c}")
+ self.error(nclassdef, "Error: Cannot provide a defaut constructor: conflict for {inhc} and {c}")
else
inhc = inhc2
end
return
end
if not combine.is_empty and inhc != null then
- self.error(nclassdef, "Cannot provide a defaut constructor: conflict for {combine.join(", ")} and {inhc}")
+ self.error(nclassdef, "Error: Cannot provide a defaut constructor: conflict for {combine.join(", ")} and {inhc}")
return
end
nclassdef.super_inits = combine
var mprop = new MMethod(mclassdef, "init", mclassdef.mclass.visibility)
var mpropdef = new MMethodDef(mclassdef, mprop, nclassdef.location)
- var param_names = new Array[String]
- var param_types = new Array[MType]
- var msignature = new MSignature(param_names, param_types, null, -1)
+ var mparameters = new Array[MParameter]
+ var msignature = new MSignature(mparameters, null)
mpropdef.msignature = msignature
mprop.is_init = true
nclassdef.mfree_init = mpropdef
end
# Collect undefined attributes
- var param_names = new Array[String]
- var param_types = new Array[MType]
+ var mparameters = new Array[MParameter]
for npropdef in nclassdef.n_propdefs do
if npropdef isa AAttrPropdef and npropdef.n_expr == null then
- param_names.add(npropdef.mpropdef.mproperty.name.substring_from(1))
+ if npropdef.mpropdef == null then return # Skip broken attribute
+ var paramname = npropdef.mpropdef.mproperty.name.substring_from(1)
var ret_type = npropdef.mpropdef.static_mtype
if ret_type == null then return
- param_types.add(ret_type)
+ var mparameter = new MParameter(paramname, ret_type, false)
+ mparameters.add(mparameter)
end
end
var mprop = new MMethod(mclassdef, "init", mclassdef.mclass.visibility)
var mpropdef = new MMethodDef(mclassdef, mprop, nclassdef.location)
- var msignature = new MSignature(param_names, param_types, null, -1)
+ var msignature = new MSignature(mparameters, null)
mpropdef.msignature = msignature
mprop.is_init = true
nclassdef.mfree_init = mpropdef
# The mmodule used as context is `nclassdef.mmodule'
# In case of problem, an error is displayed on `ntype' and null is returned.
# FIXME: the name "resolve_mtype" is awful
- fun resolve_mtype(nclassdef: AClassdef, ntype: AType): nullable MType
+ fun resolve_mtype_unchecked(nclassdef: AClassdef, ntype: AType, with_virtual: Bool): nullable MType
do
var name = ntype.n_id.text
var mclassdef = nclassdef.mclassdef
var res: MType
# Check virtual type
- if mclassdef != null then
+ if mclassdef != null and with_virtual then
var prop = try_get_mproperty_by_name(ntype, mclassdef, name).as(nullable MVirtualTypeProp)
if prop != null then
if not ntype.n_types.is_empty then
end
res = prop.mvirtualtype
if ntype.n_kwnullable != null then res = res.as_nullable
+ ntype.mtype = res
return res
end
end
end
for i in [0..mclassdef.parameter_names.length[ do
if mclassdef.parameter_names[i] == name then
- res = mclassdef.mclass.mclass_type.as(MGenericType).arguments[i]
+ res = mclassdef.mclass.mclass_type.arguments[i]
if ntype.n_kwnullable != null then res = res.as_nullable
+ ntype.mtype = res
return res
end
end
if arity == 0 then
res = mclass.mclass_type
if ntype.n_kwnullable != null then res = res.as_nullable
+ ntype.mtype = res
return res
else
var mtypes = new Array[MType]
for nt in ntype.n_types do
- var mt = resolve_mtype(nclassdef, nt)
+ var mt = resolve_mtype_unchecked(nclassdef, nt, with_virtual)
if mt == null then return null # Forward error
mtypes.add(mt)
end
res = mclass.get_mtype(mtypes)
if ntype.n_kwnullable != null then res = res.as_nullable
+ ntype.mtype = res
return res
end
end
return null
end
+ # Return the static type associated to the node `ntype'.
+ # `classdef' is the context where the call is made (used to understand formal types)
+ # The mmodule used as context is `nclassdef.mmodule'
+ # In case of problem, an error is displayed on `ntype' and null is returned.
+ # FIXME: the name "resolve_mtype" is awful
+ fun resolve_mtype(nclassdef: AClassdef, ntype: AType): nullable MType
+ do
+ var mtype = ntype.mtype
+ if mtype == null then mtype = resolve_mtype_unchecked(nclassdef, ntype, true)
+ if mtype == null then return null # Forward error
+
+ if ntype.checked_mtype then return mtype
+ if mtype isa MGenericType then
+ var mmodule = nclassdef.parent.as(AModule).mmodule.as(not null)
+ var mclassdef = nclassdef.mclassdef
+ var mclass = mtype.mclass
+ for i in [0..mclass.arity[ do
+ var bound = mclass.intro.bound_mtype.arguments[i]
+ var nt = ntype.n_types[i]
+ var mt = resolve_mtype(nclassdef, nt)
+ if mt == null then return null # forward error
+ if not mt.is_subtype(mmodule, mclassdef.bound_mtype, bound) then
+ error(nt, "Type error: expected {bound}, got {mt}")
+ return null
+ end
+ end
+ end
+ ntype.checked_mtype = true
+ return mtype
+ end
+
# Helper function to display an error on a node.
# Alias for `self.toolcontext.error(n.hot_location, text)'
fun error(n: ANode, text: String)
do
self.toolcontext.warning(n.hot_location, text)
end
+
+ # Force to get the primitive method named `name' on the type `recv' or do a fatal error on `n'
+ fun force_get_primitive_method(n: ANode, name: String, recv: MType, mmodule: MModule): MMethod
+ do
+ var res = mmodule.try_get_primitive_method(name, recv)
+ if res == null then
+ self.toolcontext.fatal_error(n.hot_location, "Fatal Error: {recv} must have a property named {name}.")
+ abort
+ end
+ return res
+ end
end
redef class AModule
var is_importation_done: Bool = false
# Flag that indicate if the class and prop building is already completed
var build_classes_is_done: Bool = false
+ # What is the AClassdef associated to a MClass?
+ # Used to check multiple definition of a class.
+ var mclass2nclassdef: Map[MClass, AClassdef] = new HashMap[MClass, AClassdef]
+
end
redef class MClass
# The free init (implicitely constructed by the class if required)
var mfree_init: nullable MMethodDef = null
+
+ # What is the APropdef associated to a MProperty?
+ # Used to check multiple definition of a property.
+ var mprop2npropdef: Map[MProperty, APropdef] = new HashMap[MProperty, APropdef]
end
redef class AClasskind
redef fun mvisibility do return private_visibility
end
+redef class AType
+ # The mtype associated to the node
+ var mtype: nullable MType = null
+
+ # Is the mtype a valid one?
+ var checked_mtype: Bool = false
+end
#
end
end
- private fun check_redef_keyword(modelbuilder: ModelBuilder, nclassdef: AClassdef, kwredef: nullable Token, need_redef: Bool, mprop: MProperty)
+ private fun check_redef_keyword(modelbuilder: ModelBuilder, nclassdef: AClassdef, kwredef: nullable Token, need_redef: Bool, mprop: MProperty): Bool
do
+ if nclassdef.mprop2npropdef.has_key(mprop) then
+ modelbuilder.error(self, "Error: A property {mprop} is already defined in class {nclassdef.mclassdef.mclass}.")
+ return false
+ end
if kwredef == null then
if need_redef then
modelbuilder.error(self, "Redef error: {nclassdef.mclassdef.mclass}::{mprop.name} is an inherited property. To redefine it, add the redef keyword.")
+ return false
end
else
if not need_redef then
modelbuilder.error(self, "Error: No property {nclassdef.mclassdef.mclass}::{mprop.name} is inherited. Remove the redef keyword to define a new property.")
+ return false
end
end
+ return true
+ end
+
+end
+
+redef class ASignature
+ # Is the model builder has correctly visited the signature
+ var is_visited = false
+ # Names of parameters from the AST
+ # REQUIRE: is_visited
+ var param_names = new Array[String]
+ # Types of parameters from the AST
+ # REQUIRE: is_visited
+ var param_types = new Array[MType]
+ # Rank of the vararg (of -1 if none)
+ # REQUIRE: is_visited
+ var vararg_rank: Int = -1
+ # Return type
+ var ret_type: nullable MType = null
+
+ # Visit and fill information about a signature
+ private fun visit_signature(modelbuilder: ModelBuilder, nclassdef: AClassdef): Bool
+ do
+ var param_names = self.param_names
+ var param_types = self.param_types
+ for np in self.n_params do
+ param_names.add(np.n_id.text)
+ var ntype = np.n_type
+ if ntype != null then
+ var mtype = modelbuilder.resolve_mtype(nclassdef, ntype)
+ if mtype == null then return false # Skip error
+ for i in [0..param_names.length-param_types.length[ do
+ param_types.add(mtype)
+ end
+ if np.n_dotdotdot != null then
+ if self.vararg_rank != -1 then
+ modelbuilder.error(np, "Error: {param_names[self.vararg_rank]} is already a vararg")
+ return false
+ else
+ self.vararg_rank = param_names.length - 1
+ end
+ end
+ end
+ end
+ var ntype = self.n_type
+ if ntype != null then
+ self.ret_type = modelbuilder.resolve_mtype(nclassdef, ntype)
+ if self.ret_type == null then return false # Skip errir
+ end
+
+ for nclosure in self.n_closure_decls do
+ if not nclosure.n_signature.visit_signature(modelbuilder, nclassdef) then return false
+ end
+
+ self.is_visited = true
+ return true
+ end
+
+ # Build a visited signature
+ fun build_signature(modelbuilder: ModelBuilder, nclassdef: AClassdef): nullable MSignature
+ do
+ if param_names.length != param_types.length then
+ # Some parameters are typed, other parameters are not typed.
+ modelbuilder.error(self.n_params[param_types.length], "Error: Untyped parameter `{param_names[param_types.length]}'.")
+ return null
+ end
+
+ var mparameters = new Array[MParameter]
+ for i in [0..param_names.length[ do
+ var mparameter = new MParameter(param_names[i], param_types[i], i == vararg_rank)
+ mparameters.add(mparameter)
+ end
+
+ var msignature = new MSignature(mparameters, ret_type)
+ return msignature
end
end
name = "init"
name_node = self.n_kwinit
else if self isa AExternInitPropdef then
- name = "new"
+ name = "init"
name_node = self.n_kwnew
else
abort
var mvisibility = new_property_visibility(modelbuilder, nclassdef, self.n_visibility)
mprop = new MMethod(mclassdef, name, mvisibility)
mprop.is_init = is_init
- self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, false, mprop)
+ mprop.is_new = self isa AExternInitPropdef
+ if not self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, false, mprop) then return
else
if n_kwredef == null then
if self isa AMainMethPropdef then
# no warning
else
- self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, true, mprop)
+ if not self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, true, mprop) then return
end
end
check_redef_property_visibility(modelbuilder, nclassdef, self.n_visibility, mprop)
end
+ nclassdef.mprop2npropdef[mprop] = self
var mpropdef = new MMethodDef(mclassdef, mprop, self.location)
var vararg_rank = -1
var ret_type: nullable MType = null # Return type from the AST
if nsig != null then
- for np in nsig.n_params do
- param_names.add(np.n_id.text)
- var ntype = np.n_type
- if ntype != null then
- var mtype = modelbuilder.resolve_mtype(nclassdef, ntype)
- if mtype == null then return # Skip error
- for i in [0..param_names.length-param_types.length[ do
- param_types.add(mtype)
- end
- if np.n_dotdotdot != null then
- if vararg_rank != -1 then
- modelbuilder.error(np, "Error: {param_names[vararg_rank]} is already a vararg")
- else
- vararg_rank = param_names.length - 1
- end
- end
- end
- end
- var ntype = nsig.n_type
- if ntype != null then
- ret_type = modelbuilder.resolve_mtype(nclassdef, ntype)
- if ret_type == null then return # Skip errir
- end
+ if not nsig.visit_signature(modelbuilder, nclassdef) then return
+ param_names = nsig.param_names
+ param_types = nsig.param_types
+ vararg_rank = nsig.vararg_rank
+ ret_type = nsig.ret_type
end
# Look for some signature to inherit
if not mpropdef.is_intro then
msignature = mpropdef.mproperty.intro.msignature
if msignature == null then return # Skip error
+
+ # Check inherited signature arity
+ if param_names.length != msignature.arity then
+ var node: ANode
+ if nsig != null then node = nsig else node = self
+ modelbuilder.error(node, "Redef error: {mpropdef} redefines {mpropdef.mproperty.intro} with {param_names.length} parameter(s), {msignature.arity} expected. Signature is {mpropdef}{msignature}")
+ return
+ end
else if mpropdef.mproperty.is_init then
# FIXME UGLY: inherit signature from a super-constructor
for msupertype in nclassdef.mclassdef.supertypes do
end
end
+
# Inherit the signature
if msignature != null and param_names.length != param_types.length and param_names.length == msignature.arity and param_types.length == 0 then
# Parameters are untyped, thus inherit them
- param_types = msignature.parameter_mtypes
+ param_types = new Array[MType]
+ for mparameter in msignature.mparameters do
+ param_types.add(mparameter.mtype)
+ end
vararg_rank = msignature.vararg_rank
end
if msignature != null and ret_type == null then
if param_names.length != param_types.length then
# Some parameters are typed, other parameters are not typed.
- modelbuilder.warning(nsig.n_params[param_types.length], "Error: Untyped parameter `{param_names[param_types.length]}'.")
+ modelbuilder.error(nsig.n_params[param_types.length], "Error: Untyped parameter `{param_names[param_types.length]}'.")
return
end
- msignature = new MSignature(param_names, param_types, ret_type, vararg_rank)
+ var mparameters = new Array[MParameter]
+ for i in [0..param_names.length[ do
+ var mparameter = new MParameter(param_names[i], param_types[i], i == vararg_rank)
+ mparameters.add(mparameter)
+ end
+
+ msignature = new MSignature(mparameters, ret_type)
mpropdef.msignature = msignature
+
+ if nsig != null then
+ for nclosure in nsig.n_closure_decls do
+ var clos_signature = nclosure.n_signature.build_signature(modelbuilder, nclassdef)
+ if clos_signature == null then return
+ var mparameter = new MParameter(nclosure.n_id.text, clos_signature, false)
+ msignature.mclosures.add(mparameter)
+ end
+ end
+
end
redef fun check_signature(modelbuilder, nclassdef)
var msignature = mpropdef.mproperty.intro.msignature
if msignature == null then return
- if mysignature.arity != msignature.arity then
- var node: ANode
- if nsig != null then node = nsig else node = self
- modelbuilder.error(node, "Redef Error: {mysignature.arity} parameters found, {msignature.arity} expected. Signature is {mpropdef}{msignature}")
- return
- end
var precursor_ret_type = msignature.return_mtype
var ret_type = mysignature.return_mtype
if ret_type != null and precursor_ret_type == null then
if mysignature.arity > 0 then
# Check parameters types
for i in [0..mysignature.arity[ do
- var myt = mysignature.parameter_mtypes[i]
- var prt = msignature.parameter_mtypes[i]
+ var myt = mysignature.mparameters[i].mtype
+ var prt = msignature.mparameters[i].mtype
if not myt.is_subtype(mmodule, nclassdef.mclassdef.bound_mtype, prt) and
not prt.is_subtype(mmodule, nclassdef.mclassdef.bound_mtype, myt) then
- modelbuilder.error(nsig.n_params[i], "Redef Error: Wrong type for parameter `{mysignature.parameter_names[i]}'. found {myt}, expected {prt}.")
+ modelbuilder.error(nsig.n_params[i], "Redef Error: Wrong type for parameter `{mysignature.mparameters[i].name}'. found {myt}, expected {prt}.")
end
end
end
modelbuilder.error(self, "Error: Attempt to define attribute {name} in the interface {mclass}.")
else if mclass.kind == enum_kind then
modelbuilder.error(self, "Error: Attempt to define attribute {name} in the enum class {mclass}.")
+ else if mclass.kind == extern_kind then
+ modelbuilder.error(self, "Error: Attempt to define attribute {name} in the extern class {mclass}.")
end
var nid = self.n_id
if mprop == null then
var mvisibility = new_property_visibility(modelbuilder, nclassdef, self.n_visibility)
mprop = new MAttribute(mclassdef, name, mvisibility)
- self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, false, mprop)
+ if not self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, false, mprop) then return
else
assert mprop isa MAttribute
check_redef_property_visibility(modelbuilder, nclassdef, self.n_visibility, mprop)
- self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, true, mprop)
+ if not self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, true, mprop) then return
end
+ nclassdef.mprop2npropdef[mprop] = self
+
var mpropdef = new MAttributeDef(mclassdef, mprop, self.location)
self.mpropdef = mpropdef
modelbuilder.mpropdef2npropdef[mpropdef] = self
if mreadprop == null then
var mvisibility = new_property_visibility(modelbuilder, nclassdef, nreadable.n_visibility)
mreadprop = new MMethod(mclassdef, readname, mvisibility)
- self.check_redef_keyword(modelbuilder, nclassdef, nreadable.n_kwredef, false, mreadprop)
+ if not self.check_redef_keyword(modelbuilder, nclassdef, nreadable.n_kwredef, false, mreadprop) then return
else
- self.check_redef_keyword(modelbuilder, nclassdef, nreadable.n_kwredef, true, mreadprop)
+ if not self.check_redef_keyword(modelbuilder, nclassdef, nreadable.n_kwredef, true, mreadprop) then return
check_redef_property_visibility(modelbuilder, nclassdef, nreadable.n_visibility, mreadprop)
end
+ nclassdef.mprop2npropdef[mreadprop] = self
+
var mreadpropdef = new MMethodDef(mclassdef, mreadprop, self.location)
self.mreadpropdef = mreadpropdef
modelbuilder.mpropdef2npropdef[mreadpropdef] = self
if mwriteprop == null then
var mvisibility = new_property_visibility(modelbuilder, nclassdef, nwritable.n_visibility)
mwriteprop = new MMethod(mclassdef, writename, mvisibility)
- self.check_redef_keyword(modelbuilder, nclassdef, nwritable.n_kwredef, false, mwriteprop)
+ if not self.check_redef_keyword(modelbuilder, nclassdef, nwritable.n_kwredef, false, mwriteprop) then return
else
- self.check_redef_keyword(modelbuilder, nclassdef, nwritable.n_kwredef, true, mwriteprop)
+ if not self.check_redef_keyword(modelbuilder, nclassdef, nwritable.n_kwredef, true, mwriteprop) then return
check_redef_property_visibility(modelbuilder, nclassdef, nwritable.n_visibility, mwriteprop)
end
+ nclassdef.mprop2npropdef[mwriteprop] = self
+
var mwritepropdef = new MMethodDef(mclassdef, mwriteprop, self.location)
self.mwritepropdef = mwritepropdef
modelbuilder.mpropdef2npropdef[mwritepropdef] = self
if mreadprop == null then
var mvisibility = new_property_visibility(modelbuilder, nclassdef, self.n_visibility)
mreadprop = new MMethod(mclassdef, readname, mvisibility)
- self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, false, mreadprop)
+ if not self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, false, mreadprop) then return
else
- self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, true, mreadprop)
+ if not self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, true, mreadprop) then return
check_redef_property_visibility(modelbuilder, nclassdef, self.n_visibility, mreadprop)
end
+ nclassdef.mprop2npropdef[mreadprop] = self
+
var mreadpropdef = new MMethodDef(mclassdef, mreadprop, self.location)
self.mreadpropdef = mreadpropdef
modelbuilder.mpropdef2npropdef[mreadpropdef] = self
mvisibility = private_visibility
end
mwriteprop = new MMethod(mclassdef, writename, mvisibility)
- self.check_redef_keyword(modelbuilder, nclassdef, nwkwredef, false, mwriteprop)
+ if not self.check_redef_keyword(modelbuilder, nclassdef, nwkwredef, false, mwriteprop) then return
else
- self.check_redef_keyword(modelbuilder, nclassdef, nwkwredef, true, mwriteprop)
+ if not self.check_redef_keyword(modelbuilder, nclassdef, nwkwredef, true, mwriteprop) then return
if nwritable != null then
check_redef_property_visibility(modelbuilder, nclassdef, nwritable.n_visibility, mwriteprop)
end
end
+ nclassdef.mprop2npropdef[mwriteprop] = self
+
var mwritepropdef = new MMethodDef(mclassdef, mwriteprop, self.location)
self.mwritepropdef = mwritepropdef
modelbuilder.mpropdef2npropdef[mwritepropdef] = self
end
if mtype == null then
- modelbuilder.warning(self, "Error: Untyped attribute {mpropdef}")
- return
+ var nexpr = self.n_expr
+ if nexpr != null then
+ if nexpr isa ANewExpr then
+ mtype = modelbuilder.resolve_mtype(nclassdef, nexpr.n_type)
+ else if nexpr isa AIntExpr then
+ var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int")
+ if cla != null then mtype = cla.mclass_type
+ else if nexpr isa AFloatExpr then
+ var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Float")
+ if cla != null then mtype = cla.mclass_type
+ else if nexpr isa ACharExpr then
+ var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Char")
+ if cla != null then mtype = cla.mclass_type
+ else if nexpr isa ABoolExpr then
+ var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Bool")
+ if cla != null then mtype = cla.mclass_type
+ else if nexpr isa ASuperstringExpr then
+ var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "String")
+ if cla != null then mtype = cla.mclass_type
+ else if nexpr isa AStringFormExpr then
+ var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "String")
+ if cla != null then mtype = cla.mclass_type
+ else
+ modelbuilder.error(self, "Error: Untyped attribute {mpropdef}. Implicit typing allowed only for literals and new.")
+ end
+
+ else
+ modelbuilder.error(self, "Error: Untyped attribute {mpropdef}")
+ end
end
+ if mtype == null then return
+
mpropdef.static_mtype = mtype
var mreadpropdef = self.mreadpropdef
if mreadpropdef != null then
- var msignature = new MSignature(new Array[String], new Array[MType], mtype, -1)
+ var msignature = new MSignature(new Array[MParameter], mtype)
mreadpropdef.msignature = msignature
end
else
name = n_id2.text
end
- var msignature = new MSignature([name], [mtype], null, -1)
+ var mparameter = new MParameter(name, mtype, false)
+ var msignature = new MSignature([mparameter], null)
mwritepropdef.msignature = msignature
end
end
end
end
- # FIXME: Check getter ans setter
+ # Check getter and setter
+ var meth = self.mreadpropdef
+ if meth != null then self.check_method_signature(modelbuilder, nclassdef, meth)
+ meth = self.mwritepropdef
+ if meth != null then self.check_method_signature(modelbuilder, nclassdef, meth)
+ end
+
+ private fun check_method_signature(modelbuilder: ModelBuilder, nclassdef: AClassdef, mpropdef: MMethodDef)
+ do
+ var mmodule = mpropdef.mclassdef.mmodule
+ var nsig = self.n_type
+ var mysignature = mpropdef.msignature
+ if mysignature == null then return # Error thus skiped
+
+ # Lookup for signature in the precursor
+ # FIXME all precursors should be considered
+ if not mpropdef.is_intro then
+ var msignature = mpropdef.mproperty.intro.msignature
+ if msignature == null then return
+
+ if mysignature.arity != msignature.arity then
+ var node: ANode
+ if nsig != null then node = nsig else node = self
+ modelbuilder.error(node, "Redef Error: {mysignature.arity} parameters found, {msignature.arity} expected. Signature is {mpropdef}{msignature}")
+ return
+ end
+ var precursor_ret_type = msignature.return_mtype
+ var ret_type = mysignature.return_mtype
+ if ret_type != null and precursor_ret_type == null then
+ var node: ANode
+ if nsig != null then node = nsig else node = self
+ modelbuilder.error(node, "Redef Error: {mpropdef.mproperty} is a procedure, not a function.")
+ return
+ end
+
+ if mysignature.arity > 0 then
+ # Check parameters types
+ for i in [0..mysignature.arity[ do
+ var myt = mysignature.mparameters[i].mtype
+ var prt = msignature.mparameters[i].mtype
+ if not myt.is_subtype(mmodule, nclassdef.mclassdef.bound_mtype, prt) and
+ not prt.is_subtype(mmodule, nclassdef.mclassdef.bound_mtype, myt) then
+ var node: ANode
+ if nsig != null then node = nsig else node = self
+ modelbuilder.error(node, "Redef Error: Wrong type for parameter `{mysignature.mparameters[i].name}'. found {myt}, expected {prt}.")
+ end
+ end
+ end
+ if precursor_ret_type != null then
+ if ret_type == null then
+ # Inherit the return type
+ ret_type = precursor_ret_type
+ else if not ret_type.is_subtype(mmodule, nclassdef.mclassdef.bound_mtype, precursor_ret_type) then
+ var node: ANode
+ if nsig != null then node = nsig else node = self
+ modelbuilder.error(node, "Redef Error: Wrong return type. found {ret_type}, expected {precursor_ret_type}.")
+ end
+ end
+ end
end
end
if mprop == null then
var mvisibility = new_property_visibility(modelbuilder, nclassdef, self.n_visibility)
mprop = new MVirtualTypeProp(mclassdef, name, mvisibility)
- self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, false, mprop)
+ if not self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, false, mprop) then return
else
- self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, true, mprop)
+ if not self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, true, mprop) then return
assert mprop isa MVirtualTypeProp
check_redef_property_visibility(modelbuilder, nclassdef, self.n_visibility, mprop)
end
+ nclassdef.mprop2npropdef[mprop] = self
+
var mpropdef = new MVirtualTypeDef(mclassdef, mprop, self.location)
self.mpropdef = mpropdef
end