#node.debug("Unsafe typing: expected {sup}, got {sub}")
return sup
end
+ if sup isa MBottomType then return null # Skip error
if sub.need_anchor then
var u = anchor_to(sub)
self.modelbuilder.error(node, "Type Error: expected `{sup}`, got `{sub}: {u}`.")
end
end
- var callsite = new CallSite(node, recvtype, mmodule, anchor, recv_is_self, mproperty, mpropdef, msignature, erasure_cast)
+ var callsite = new CallSite(node.hot_location, recvtype, mmodule, anchor, recv_is_self, mproperty, mpropdef, msignature, erasure_cast)
return callsite
end
continue # skip the vararg
end
- var paramtype = param.mtype
- self.visit_expr_subtype(arg, paramtype)
+ if not param.is_vararg then
+ var paramtype = param.mtype
+ self.visit_expr_subtype(arg, paramtype)
+ else
+ check_one_vararg(arg, param)
+ end
end
if min_arity > 0 then
var paramtype = msignature.mparameters[vararg_rank].mtype
var first = args[vararg_rank]
if vararg_decl == 0 then
- var mclass = get_mclass(node, "Array")
- if mclass == null then return null # Forward error
- var array_mtype = mclass.get_mtype([paramtype])
- if first isa AVarargExpr then
- self.visit_expr_subtype(first.n_expr, array_mtype)
- first.mtype = first.n_expr.mtype
- else
- # only one vararg, maybe `...` was forgot, so be gentle!
- var t = visit_expr(first)
- if t == null then return null # Forward error
- if not is_subtype(t, paramtype) and is_subtype(t, array_mtype) then
- # Not acceptable but could be a `...`
- error(first, "Type Error: expected `{paramtype}`, got `{t}`. Is an ellipsis `...` missing on the argument?")
- return null
- end
- # Standard valid vararg, finish the job
- map.vararg_decl = 1
- self.visit_expr_subtype(first, paramtype)
- end
+ if not check_one_vararg(first, msignature.mparameters[vararg_rank]) then return null
else
- map.vararg_decl = vararg_decl + 1
+ first.vararg_decl = vararg_decl + 1
for i in [vararg_rank..vararg_rank+vararg_decl] do
self.visit_expr_subtype(args[i], paramtype)
end
return map
end
+ # Check an expression as a single vararg.
+ # The main point of the method if to handle the case of reversed vararg (see `AVarargExpr`)
+ fun check_one_vararg(arg: AExpr, param: MParameter): Bool
+ do
+ var paramtype = param.mtype
+ var mclass = get_mclass(arg, "Array")
+ if mclass == null then return false # Forward error
+ var array_mtype = mclass.get_mtype([paramtype])
+ if arg isa AVarargExpr then
+ self.visit_expr_subtype(arg.n_expr, array_mtype)
+ arg.mtype = arg.n_expr.mtype
+ else
+ # only one vararg, maybe `...` was forgot, so be gentle!
+ var t = visit_expr(arg)
+ if t == null then return false # Forward error
+ if not is_subtype(t, paramtype) and is_subtype(t, array_mtype) then
+ # Not acceptable but could be a `...`
+ error(arg, "Type Error: expected `{paramtype}`, got `{t}`. Is an ellipsis `...` missing on the argument?")
+ return false
+ end
+ # Standard valid vararg, finish the job
+ arg.vararg_decl = 1
+ self.visit_expr_subtype(arg, paramtype)
+ end
+ return true
+ end
+
fun error(node: ANode, message: String)
do
- self.modelbuilder.toolcontext.error(node.hot_location, message)
+ self.modelbuilder.error(node, message)
end
fun get_variable(node: AExpr, variable: Variable): nullable MType
class SignatureMap
# Associate a parameter to an argument
var map = new ArrayMap[Int, Int]
-
- # The length of the vararg sequence
- # 0 if no vararg or if reverse vararg (cf `AVarargExpr`)
- var vararg_decl: Int = 0
end
# A specific method call site with its associated informations.
class CallSite
- # The associated node for location
- var node: ANode
+ super MEntity
+
+ # The associated location of the callsite
+ var location: Location
# The static type of the receiver (possibly unresolved)
var recv: MType
# If null then no specific association is required.
var signaturemap: nullable SignatureMap = null
- private fun check_signature(v: TypeVisitor, args: Array[AExpr]): Bool
+ private fun check_signature(v: TypeVisitor, node: ANode, args: Array[AExpr]): Bool
do
- var map = v.check_signature(self.node, args, self.mproperty, self.msignature)
+ var map = v.check_signature(node, args, self.mproperty, self.msignature)
signaturemap = map
+ if map == null then is_broken = true
return map == null
end
end
redef fun visit(n) do
n.visit_all(self)
n.accept_post_typing(type_visitor)
+ if n isa AExpr and n.mtype == null and not n.is_typed then
+ n.is_broken = true
+ end
end
end
# The result of the evaluation of `self` must be
# stored inside the designated array (there is an implicit `push`)
var comprehension: nullable AArrayExpr = null
+
+ # It indicates the number of arguments collected as a vararg.
+ #
+ # When 0, the argument is used as is, without transformation.
+ # When 1, the argument is transformed into an singleton array.
+ # Above 1, the arguments and the next ones are transformed into a common array.
+ #
+ # This attribute is meaning less on expressions not used as attributes.
+ var vararg_decl: Int = 0
end
redef class ABlockExpr
end
redef class AForExpr
+ redef fun accept_typing(v)
+ do
+ v.has_loop = true
+
+ for g in n_groups do
+ var mtype = v.visit_expr(g.n_expr)
+ if mtype == null then return
+ g.do_type_iterator(v, mtype)
+ if g.is_broken then is_broken = true
+ end
+
+ v.visit_stmt(n_block)
+
+ self.mtype = n_block.mtype
+ self.is_typed = true
+ end
+end
+
+redef class AForGroup
var coltype: nullable MClassType
var method_iterator: nullable CallSite
self.method_successor = v.get_method(self, vtype, "successor", false)
end
end
-
- redef fun accept_typing(v)
- do
- v.has_loop = true
- var mtype = v.visit_expr(n_expr)
- if mtype == null then return
-
- self.do_type_iterator(v, mtype)
-
- v.visit_stmt(n_block)
-
- self.mtype = n_block.mtype
- self.is_typed = true
- end
end
redef class AWithExpr
mclass = v.get_mclass(self, "Byte")
else if value isa Int then
mclass = v.get_mclass(self, "Int")
+ else if value isa Int8 then
+ mclass = v.get_mclass(self, "Int8")
+ else if value isa Int16 then
+ mclass = v.get_mclass(self, "Int16")
+ else if value isa UInt16 then
+ mclass = v.get_mclass(self, "UInt16")
+ else if value isa Int32 then
+ mclass = v.get_mclass(self, "Int32")
+ else if value isa UInt32 then
+ mclass = v.get_mclass(self, "UInt32")
end
if mclass == null then return # Forward error
self.mtype = mclass.mclass_type
var args = compute_raw_arguments
- callsite.check_signature(v, args)
+ callsite.check_signature(v, node, args)
if callsite.mproperty.is_init then
var vmpropdef = v.mpropdef
redef class ACallExpr
- redef fun property_name do return n_id.text
- redef fun property_node do return n_id
+ redef fun property_name do return n_qid.n_id.text
+ redef fun property_node do return n_qid
redef fun compute_raw_arguments do return n_args.to_a
end
redef class ACallAssignExpr
- redef fun property_name do return n_id.text + "="
- redef fun property_node do return n_id
+ redef fun property_name do return n_qid.n_id.text + "="
+ redef fun property_node do return n_qid
redef fun compute_raw_arguments
do
var res = n_args.to_a
var args = compute_raw_arguments
- callsite.check_signature(v, args)
+ callsite.check_signature(v, node, args)
var readtype = callsite.msignature.return_mtype
if readtype == null then
args = args.to_a # duplicate so raw_arguments keeps only the getter args
args.add(self.n_value)
- wcallsite.check_signature(v, args)
+ wcallsite.check_signature(v, node, args)
self.is_typed = true
end
end
redef class ACallReassignExpr
- redef fun property_name do return n_id.text
- redef fun property_node do return n_id
+ redef fun property_name do return n_qid.n_id.text
+ redef fun property_node do return n_qid.n_id
redef fun compute_raw_arguments do return n_args.to_a
end
var msignature = superprop.new_msignature or else superprop.msignature.as(not null)
msignature = v.resolve_for(msignature, recvtype, true).as(MSignature)
- var callsite = new CallSite(self, recvtype, v.mmodule, v.anchor, true, superprop.mproperty, superprop, msignature, false)
+ var callsite = new CallSite(hot_location, recvtype, v.mmodule, v.anchor, true, superprop.mproperty, superprop, msignature, false)
self.callsite = callsite
var args = self.n_args.to_a
if args.length > 0 then
- callsite.check_signature(v, args)
+ callsite.check_signature(v, self, args)
else
# Check there is at least enough parameters
if mpropdef.msignature.arity < msignature.arity then
var kind = recvtype.mclass.kind
var name: String
- var nid = self.n_id
+ var nqid = self.n_qid
var node: ANode
- if nid != null then
- name = nid.text
- node = nid
+ if nqid != null then
+ name = nqid.n_id.text
+ node = nqid
else
name = "new"
node = self.n_kwnew
end
var args = n_args.to_a
- callsite.check_signature(v, args)
+ callsite.check_signature(v, node, args)
end
end