return res
end
- fun resolve_signature_for(msignature: MSignature, recv: MType, for_self: Bool): MSignature
+ # Retrieve the signature of a MMethodDef resolved for a specific call.
+ # This method is an helper to symplify the query on the model.
+ #
+ # Note: `for_self` indicates if the reciever is self or not.
+ # If yes, virtual types are not resolved.
+ fun resolve_signature_for(mmethoddef: MMethodDef, recv: MType, for_self: Bool): MSignature
do
- return self.resolve_for(msignature, recv, for_self).as(MSignature)
+ return self.resolve_for(mmethoddef.msignature.as(not null), recv, for_self).as(MSignature)
end
fun check_subtype(node: ANode, sub, sup: MType): Bool
return self.modelbuilder.resolve_mtype(self.nclassdef, node)
end
+ fun try_get_mclass(node: ANode, name: String): nullable MClass
+ do
+ var mmodule = self.nclassdef.mclassdef.mmodule
+ var mclass = modelbuilder.try_get_mclass_by_name(node, mmodule, name)
+ return mclass
+ end
+
fun get_mclass(node: ANode, name: String): nullable MClass
do
var mmodule = self.nclassdef.mclassdef.mmodule
return null
end
+ if mproperty.visibility == protected_visibility and not recv_is_self and self.mmodule.visibility_for(mproperty.intro_mclassdef.mmodule) < intrude_visibility then
+ self.modelbuilder.error(node, "Error: Method '{name}' is protected and can only acceded by self. {mproperty.intro_mclassdef.mmodule.visibility_for(self.mmodule)}")
+ return null
+ end
+
var propdefs = mproperty.lookup_definitions(self.mmodule, unsafe_type)
if propdefs.length == 0 then
self.modelbuilder.error(node, "Type error: no definition found for property {name} in {unsafe_type}")
if i > vararg_rank then
j = i + vararg_decl
end
- var paramtype = msignature.parameter_mtypes[i]
+ var paramtype = msignature.mparameters[i].mtype
self.visit_expr_subtype(args[j], paramtype)
end
if vararg_rank >= 0 then
var varargs = new Array[AExpr]
- var paramtype = msignature.parameter_mtypes[vararg_rank]
+ var paramtype = msignature.mparameters[vararg_rank].mtype
for j in [vararg_rank..vararg_rank+vararg_decl] do
varargs.add(args[j])
self.visit_expr_subtype(args[j], paramtype)
fun do_typing(modelbuilder: ModelBuilder)
do
end
+
+ # The variable associated to the reciever (if any)
+ var selfvariable: nullable Variable
end
redef class AConcreteMethPropdef
var nclassdef = self.parent.as(AClassdef)
var mpropdef = self.mpropdef.as(not null)
var v = new TypeVisitor(modelbuilder, nclassdef, mpropdef)
+ self.selfvariable = v.selfvariable
var nblock = self.n_block
if nblock == null then return
var mmethoddef = self.mpropdef.as(not null)
for i in [0..mmethoddef.msignature.arity[ do
- var mtype = mmethoddef.msignature.parameter_mtypes[i]
+ var mtype = mmethoddef.msignature.mparameters[i].mtype
if mmethoddef.msignature.vararg_rank == i then
var arrayclass = v.get_mclass(self.n_signature.n_params[i], "Array")
if arrayclass == null then return # Skip error
assert variable != null
variable.declared_type = mtype
end
+ for i in [0..mmethoddef.msignature.mclosures.length[ do
+ var mclosure = mmethoddef.msignature.mclosures[i]
+ var variable = self.n_signature.n_closure_decls[i].variable
+ assert variable != null
+ variable.declared_type = mclosure.mtype
+ end
v.visit_stmt(nblock)
if not nblock.after_flow_context.is_unreachable and mmethoddef.msignature.return_mtype != null then
do
var nclassdef = self.parent.as(AClassdef)
var v = new TypeVisitor(modelbuilder, nclassdef, self.mpropdef.as(not null))
+ self.selfvariable = v.selfvariable
var nexpr = self.n_expr
if nexpr != null then
end
if mtype == null then
- mtype = v.get_mclass(self, "Object").mclass_type
+ mtype = v.get_mclass(self, "Object").mclass_type.as_nullable
end
variable.declared_type = mtype
self.reassign_property = mpropdef
- var msignature = mpropdef.msignature
- assert msignature!= null
- msignature = v.resolve_signature_for(msignature, readtype, false)
+ var msignature = v.resolve_signature_for(mpropdef, readtype, false)
var rettype = msignature.return_mtype
assert msignature.arity == 1 and rettype != null
- var value_type = v.visit_expr_subtype(self.n_value, msignature.parameter_mtypes.first)
+ var value_type = v.visit_expr_subtype(self.n_value, msignature.mparameters.first.mtype)
if value_type == null then return null # Skip error
v.check_subtype(self, rettype, writetype)
end
redef class AForExpr
- redef fun accept_typing(v)
- do
- var mtype = v.visit_expr(n_expr)
- if mtype == null then return
+ var coltype: nullable MClassType
+
+ var method_iterator: nullable MMethod
+ var method_is_ok: nullable MMethod
+ var method_item: nullable MMethod
+ var method_next: nullable MMethod
+ var method_key: nullable MMethod
- var colcla = v.get_mclass(self, "Collection")
- if colcla == null then return
+ private fun do_type_iterator(v: TypeVisitor, mtype: MType)
+ do
var objcla = v.get_mclass(self, "Object")
if objcla == null then return
- if v.is_subtype(mtype, colcla.get_mtype([objcla.mclass_type.as_nullable])) then
+
+ var is_col = false
+ var is_map = false
+
+ var colcla = v.try_get_mclass(self, "Collection")
+ if colcla != null and v.is_subtype(mtype, colcla.get_mtype([objcla.mclass_type.as_nullable])) then
var coltype = mtype.supertype_to(v.mmodule, v.anchor, colcla)
- assert coltype isa MGenericType
+ self.coltype = coltype
var variables = self.variables
if variables.length != 1 then
v.error(self, "Type Error: Expected one variable")
else
variables.first.declared_type = coltype.arguments.first
end
- else
- v.modelbuilder.error(self, "TODO: Do 'for' on {mtype}")
+ is_col = true
+ end
+
+ var mapcla = v.try_get_mclass(self, "Map")
+ if mapcla != null and v.is_subtype(mtype, mapcla.get_mtype([objcla.mclass_type.as_nullable, objcla.mclass_type.as_nullable])) then
+ var coltype = mtype.supertype_to(v.mmodule, v.anchor, mapcla)
+ self.coltype = coltype
+ var variables = self.variables
+ if variables.length != 2 then
+ v.error(self, "Type Error: Expected two variables")
+ else
+ variables[0].declared_type = coltype.arguments[0]
+ variables[1].declared_type = coltype.arguments[1]
+ end
+ is_map = true
+ end
+
+ if is_col or is_map then
+ # get iterator method
+ var coltype = self.coltype.as(not null)
+ var itdef = v.get_method(self, coltype, "iterator", true)
+ if itdef == null then
+ v.error(self, "Type Error: Expected method 'iterator' in type {coltype}")
+ return
+ end
+ self.method_iterator = itdef.mproperty
+
+ # get iterator type
+ var ittype = v.resolve_signature_for(itdef, mtype, false).return_mtype
+ if ittype == null then
+ v.error(self, "Type Error: Expected method 'iterator' to return an Iterator type")
+ return
+ end
+
+ # get methods is_ok, next, item
+ var ikdef = v.get_method(self, ittype, "is_ok", false)
+ if ikdef == null then
+ v.error(self, "Type Error: Expected method 'is_ok' in Iterator type {ittype}")
+ return
+ end
+ self.method_is_ok = ikdef.mproperty
+
+ var itemdef = v.get_method(self, ittype, "item", false)
+ if itemdef == null then
+ v.error(self, "Type Error: Expected method 'item' in Iterator type {ittype}")
+ return
+ end
+ self.method_item = itemdef.mproperty
+
+ var nextdef = v.get_method(self, ittype, "next", false)
+ if nextdef == null then
+ v.error(self, "Type Error: Expected method 'next' in Iterator type {ittype}")
+ return
+ end
+ self.method_next = nextdef.mproperty
+
+ if is_map then
+ var keydef = v.get_method(self, ittype, "key", false)
+ if keydef == null then
+ v.error(self, "Type Error: Expected method 'key' in Iterator type {ittype}")
+ return
+ end
+ self.method_key = keydef.mproperty
+ end
+ return
end
+ v.modelbuilder.error(self, "NOT YET IMPLEMENTED: Do 'for' on {mtype}")
+ end
+
+ redef fun accept_typing(v)
+ do
+ var mtype = v.visit_expr(n_expr)
+ if mtype == null then return
+
+ self.do_type_iterator(v, mtype)
+
v.visit_stmt(n_block)
self.is_typed = true
end
redef class ARangeExpr
redef fun accept_typing(v)
do
- var t1 = v.visit_expr(self.n_expr)
- var t2 = v.visit_expr(self.n_expr2)
+ var discrete_class = v.get_mclass(self, "Discrete")
+ if discrete_class == null then return # Forward error
+ var discrete_type = discrete_class.intro.bound_mtype
+ var t1 = v.visit_expr_subtype(self.n_expr, discrete_type)
+ var t2 = v.visit_expr_subtype(self.n_expr2, discrete_type)
if t1 == null or t2 == null then return
var mclass = v.get_mclass(self, "Range")
if mclass == null then return # Forward error
return
end
- var propdef = v.get_method(self, recvtype, name, self.n_expr isa ASelfExpr)
- if propdef == null then return
- var mproperty = propdef.mproperty
+ var mpropdef = v.get_method(self, recvtype, name, self.n_expr isa ASelfExpr)
+ if mpropdef == null then return
+ var mproperty = mpropdef.mproperty
self.mproperty = mproperty
- var msignature = propdef.msignature
- if msignature == null then abort # Forward error
-
- var for_self = self.n_expr isa ASelfExpr
- msignature = v.resolve_signature_for(msignature, recvtype, for_self)
+ var msignature = v.resolve_signature_for(mpropdef, recvtype, self.n_expr isa ASelfExpr)
var args = compute_raw_arguments
+ self.raw_arguments = args
v.check_signature(self, args, name, msignature)
else
self.is_typed = true
end
+
+ if self.n_closure_defs.length == msignature.mclosures.length then
+ for i in [0..self.n_closure_defs.length[ do
+ self.n_closure_defs[i].accept_typing(v, msignature.mclosures[i])
+ end
+ else
+ debug("closure: got {self.n_closure_defs.length}, want {msignature.mclosures.length}")
+ end
end
# The name of the property
private fun property_name: String is abstract
# An array of all arguments (excluding self)
- fun compute_raw_arguments: Array[AExpr] is abstract
+ var raw_arguments: nullable Array[AExpr]
+
+ private fun compute_raw_arguments: Array[AExpr] is abstract
end
redef class ABinopExpr
return
end
- var propdef = v.get_method(self, recvtype, name, self.n_expr isa ASelfExpr)
- if propdef == null then return
- var mproperty = propdef.mproperty
- self.mproperty = mproperty
- var msignature = propdef.msignature
- if msignature == null then abort # Forward error
var for_self = self.n_expr isa ASelfExpr
- msignature = v.resolve_signature_for(msignature, recvtype, for_self)
+ var mpropdef = v.get_method(self, recvtype, name, for_self)
+
+ if mpropdef == null then return
+ var mproperty = mpropdef.mproperty
+ self.mproperty = mproperty
+ var msignature = v.resolve_signature_for(mpropdef, recvtype, for_self)
var args = compute_raw_arguments
+ self.raw_arguments = args
v.check_signature(self, args, name, msignature)
if wpropdef == null then return
var wmproperty = wpropdef.mproperty
self.write_mproperty = wmproperty
- var wmsignature = wpropdef.msignature
- if wmsignature == null then abort # Forward error
- wmsignature = v.resolve_signature_for(wmsignature, recvtype, for_self)
+ var wmsignature = v.resolve_signature_for(wpropdef, recvtype, for_self)
- var wtype = self.resolve_reassignment(v, readtype, wmsignature.parameter_mtypes.last)
+ var wtype = self.resolve_reassignment(v, readtype, wmsignature.mparameters.last.mtype)
if wtype == null then return
+ args = args.to_a # duplicate so raw_arguments keeps only the getter args
args.add(self.n_value)
v.check_signature(self, args, name + "=", wmsignature)
v.error(self, "Error: No super method to call for {mproperty}.")
return
else if superprops.length > 1 then
- v.modelbuilder.warning(self, "Error: Conflicting super method to call for {mproperty}: {superprops.join(", ")}.")
+ v.modelbuilder.warning(self, "Warning: NOT YET IMPLEMENTED: Conflicting super method to call for {mproperty}: {superprops.join(", ")}.")
return
end
var superprop = superprops.first
assert superprop isa MMethodDef
- var msignature = superprop.msignature.as(not null)
- msignature = v.resolve_signature_for(msignature, recvtype, true)
+ var msignature = v.resolve_signature_for(superprop, recvtype, true)
var args = self.n_args.to_a
if args.length > 0 then
v.check_signature(self, args, mproperty.name, msignature)
self.mproperty = superprop.mproperty
var args = self.n_args.to_a
- var msignature = superprop.msignature.as(not null)
- msignature = v.resolve_signature_for(msignature, recvtype, true)
+ var msignature = v.resolve_signature_for(superprop, recvtype, true)
if args.length > 0 then
v.check_signature(self, args, mproperty.name, msignature)
else
return
end
- var msignature = propdef.msignature.as(not null)
- msignature = v.resolve_signature_for(msignature, recvtype, false)
+ var msignature = v.resolve_signature_for(propdef, recvtype, false)
var args = n_args.to_a
v.check_signature(self, args, name, msignature)
redef class AClosureCallExpr
redef fun accept_typing(v)
do
- #TODO
+ var variable = self.variable
+ if variable == null then return # Skip error
+
+ var recvtype = v.nclassdef.mclassdef.bound_mtype
+ var msignature = variable.declared_type.as(not null)
+ msignature = v.resolve_for(msignature, recvtype, false).as(MSignature)
+
+ var args = n_args.to_a
+ v.check_signature(self, args, variable.name, msignature)
+
+ self.is_typed = true
+ self.mtype = msignature.return_mtype
+ end
+end
+
+redef class AClosureDef
+ var mclosure: nullable MParameter
+
+ private fun accept_typing(v: TypeVisitor, mparameter: MParameter)
+ do
+ var variables = self.variables
+ if variables == null then return
+
+ self.mclosure = mparameter
+ var msignature = mparameter.mtype.as(MSignature)
+
+ if msignature.arity != variables.length then
+ v.error(self, "Type error: closure {mparameter.name} expects {msignature.arity} parameters, {variables.length} given")
+ return
+ end
+
+ for i in [0..variables.length[ do
+ variables[i].declared_type = msignature.mparameters[i].mtype
+ end
+
+ v.visit_stmt(self.n_expr)
end
end