+ # Raw arguments used (without vararg transformation)
+ redef fun raw_arguments: Array[AExpr]
+ do
+ var res = _raw_arguments_cache
+ if res != null then
+ return res
+ else
+ res = compute_raw_arguments
+ if res == null then res = new Array[AExpr]
+ _raw_arguments_cache = res
+ return res
+ end
+ end
+
+ var _raw_arguments_cache: nullable Array[AExpr] = null
+
+ fun compute_raw_arguments: nullable Array[AExpr]
+ do
+ print "{location} no compute_raw_arguments"
+ return null
+ end
+
+ # Check the conformity of a set of arguments `raw_args' to a signature.
+ private fun process_signature(v: TypingVisitor, psig: MMSignature, name: Symbol, raw_args: nullable Array[AExpr]): Bool
+ do
+ var par_vararg = psig.vararg_rank
+ var par_arity = psig.arity
+ var raw_arity: Int
+ if raw_args == null then raw_arity = 0 else raw_arity = raw_args.length
+ if par_arity > raw_arity or (par_arity != raw_arity and par_vararg == -1) then
+ v.error(self, "Error: arity missmatch; prototype is '{name}{psig}'.")
+ return false
+ end
+ var arg_idx = 0
+ for par_idx in [0..par_arity[ do
+ var a: AExpr
+ var par_type = psig[par_idx]
+ if par_idx == par_vararg then
+ for i in [0..(raw_arity-par_arity)] do
+ a = raw_args[arg_idx]
+ v.check_conform_expr(a, par_type)
+ arg_idx = arg_idx + 1
+ end
+ else
+ a = raw_args[arg_idx]
+ v.check_conform_expr(a, par_type)
+ arg_idx = arg_idx + 1
+ end
+ end
+ return true
+ end
+
+ # Check the conformity of a set of defined closures
+ private fun process_closures(v: TypingVisitor, psig: MMSignature, name: Symbol, cd: nullable Array[AClosureDef]): nullable MMType
+ do
+ var t = psig.return_type
+ var cs = psig.closures # Declared closures
+ var min_arity = 0
+ for c in cs do
+ if not c.is_optional then min_arity += 1
+ end
+ var arity = 0
+ if cd != null then arity = cd.length
+ if cs.length > 0 then
+ if arity == 0 and min_arity > 0 then
+ v.error(self, "Error: {name} requires {cs.length} blocks.")
+ else if arity > cs.length or arity < min_arity then
+ v.error(self, "Error: {name} requires {cs.length} blocks, {cd.length} found.")
+ else
+ # Initialize the break list if a value is required for breaks (ie. if the method is a function)
+ var break_list: nullable Array[ABreakExpr] = null
+ if t != null then break_list = new Array[ABreakExpr]
+
+ # The n_label, is any in only set on the last decl
+ var n_label = if arity > 0 then cd[arity-1].n_label else null
+
+ # Process each closure definition
+ for i in [0..arity[ do
+ var cdi = cd[i]
+ var cni = cdi.n_id.to_symbol
+ var csi = psig.closure_named(cni)
+ if csi != null then
+ var esc = new EscapableClosure(cdi, csi, break_list)
+ v.scope_ctx.push_escapable(esc, n_label)
+ cdi.accept_typing2(v, esc)
+ v.scope_ctx.pop
+ else if cs.length == 1 then
+ v.error(cdi.n_id, "Error: no closure named '!{cni}' in {name}; only closure is !{cs.first.name}.")
+ else
+ var a = new Array[String]
+ for c in cs do
+ a.add("!{c.name}")
+ end
+ v.error(cdi.n_id, "Error: no closure named '!{cni}' in {name}; only closures are {a.join(",")}.")
+ end
+ end
+
+ # Check break type conformity
+ if break_list != null then
+ t = v.check_conform_multiexpr(t, break_list)
+ end
+ end
+ else if arity != 0 then
+ v.error(self, "Error: {name} does not require blocks.")
+ end
+ return t
+ end
+end
+
+redef class AAbsSendExpr