# The closure parameters
readable var _closures: Array[MMClosure] = new Array[MMClosure]
+ # Return the closure named 'name'. Null if no such a closure exists.
+ fun closure_named(name: Symbol): nullable MMClosure
+ do
+ for c in _closures do
+ if c.name == name then return c
+ end
+ return null
+ end
+
# Number of parameters
fun arity: Int
do
# A closure in a signature
class MMClosure
+ # The name of the closure (without the !)
+ readable var _name: Symbol
+
# The signature of the closure
readable var _signature: MMSignature
# Adapt the signature to a different receiver
fun adaptation_to(r: MMType): MMClosure
do
- return new MMClosure(_signature.adaptation_to(r), _is_break, _is_optional)
+ return new MMClosure(_name, _signature.adaptation_to(r), _is_break, _is_optional)
end
- init(s: MMSignature, is_break: Bool, is_optional: Bool)
+ init(name: Symbol, s: MMSignature, is_break: Bool, is_optional: Bool)
do
+ _name = name
_signature = s
_is_break = is_break
_is_optional = is_optional
do
var sig = _signature.not_for_self
if sig != _signature then
- return new MMClosure(sig, _is_break, _is_optional)
+ return new MMClosure(_name, sig, _is_break, _is_optional)
else
return self
end
closcns = new Array[nullable IClosureDef]
var cdarity = 0
if closure_defs != null then cdarity = closure_defs.length
- for i in [0..cdarity[ do
- closure_defs[i].escapable.break_seq = seq
- closure_defs[i].escapable.break_value = r
- var cn = closure_defs[i].generate_iclosuredef(v)
- closcns.add(cn)
- end
- for i in [cdarity..prop_signature.closures.length[ do
- closcns.add(null)
+ var closure_defs = closure_defs
+ for mmc in prop_signature.closures do
+ var found = false
+ var name = mmc.name
+ if closure_defs != null then
+ for cd in closure_defs do
+ if cd.n_id.to_symbol != name then continue
+ assert found == false
+ found = true
+ cd.escapable.break_seq = seq
+ cd.escapable.break_value = r
+ var cn = cd.generate_iclosuredef(v)
+ closcns.add(cn)
+ end
+ end
+ if not found then
+ closcns.add(null)
+ end
end
end
# Add the finalizer to the closure signature
var finalize_sig = new MMSignature(new Array[MMType], null, v.module.type_any) # FIXME should be no receiver
- var finalizer_clos = new MMClosure(finalize_sig, false, true)
+ var finalizer_clos = new MMClosure(once ("break".to_symbol), finalize_sig, false, true)
sig.closures.add(finalizer_clos)
- var clos = new MMClosure(sig, n_kwbreak != null, n_expr != null)
+ var name = n_id.to_symbol
+ var clos = new MMClosure(name, sig, n_kwbreak != null, n_expr != null)
+ for c in old_signature_builder.closure_decls do
+ if c.n_id.to_symbol == name then
+ v.error(n_id, "A closure '!{name}' already defined at {c.n_id.location.relative_to(n_id.location)}.")
+ return
+ end
+ end
v.signature_builder = old_signature_builder
_position = old_signature_builder.closure_decls.length
old_signature_builder.closure_decls.add(self)
# Process each closure definition
for i in [0..arity[ do
- var csi = cs[i]
var cdi = cd[i]
- var esc = new EscapableClosure(cdi, csi, break_list)
- v.escapable_ctx.push(esc, n_label)
- cdi.accept_typing2(v, esc)
- v.escapable_ctx.pop
+ 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.escapable_ctx.push(esc, n_label)
+ cdi.accept_typing2(v, esc)
+ v.escapable_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
end
end
+redef class AClosureId
+ fun to_symbol: Symbol is abstract
+end
+redef class ASimpleClosureId
+ redef fun to_symbol: Symbol do return n_id.to_symbol
+end
+redef class ABreakClosureId
+ redef fun to_symbol: Symbol do return n_kwbreak.to_symbol
+end
+
redef class AClosureDef
var _closure: nullable MMClosure
redef fun closure do return _closure.as(not null)
# limitations under the License.
import kernel
-
fun a
!a1
!a2 #!alt1#
#alt2# !a3
+#alt6# !a1
do
a1
a2 #!alt1#
--- /dev/null
+alt/base_closure1_alt12.nit:46,10--12: Error: no closure named '!baz' in foo; only closure is !bar.
+++ /dev/null
-0
-[1
-2
-[3
-4
-5
-4
-5
-]3
-6
-2
-[3
-4
-5
-4
-5
-]3
-6
-]1
-7
-8
--- /dev/null
+alt/base_closure8_alt4.nit:29,8--10: Error: no closure named '!baz' in bar; only closure is !break.
+++ /dev/null
-alt/base_closure_continue_assign_alt3.nit:47,10: Error: continue without value required in this block.
--- /dev/null
+alt/base_closure_multi_alt6.nit:22,4--5: A closure '!a1' already defined at 19,3--4.
0.output
var i = 0
while i < 3 do
- foo !each do
+ foo !k do
' '.output
' '.output
'<'.output