From 392e3b119dddc0ed9c4c7d43f0975e5ac40d7c50 Mon Sep 17 00:00:00 2001 From: Jean Privat Date: Fri, 31 Jul 2009 22:44:33 -0400 Subject: [PATCH] syntax: closure are designed by their names, not their ranks Signed-off-by: Jean Privat --- src/metamodel/static_type.nit | 19 ++++++++++-- src/syntax/icode_generation.nit | 26 +++++++++++----- src/syntax/mmbuilder.nit | 11 +++++-- src/syntax/typing.nit | 31 ++++++++++++++++---- tests/base_closure_multi.nit | 2 +- tests/sav/base_closure1_alt12.sav | 1 + tests/sav/base_closure8_alt4.fail | 21 ------------- tests/sav/base_closure8_alt4.sav | 1 + tests/sav/base_closure_continue_assign_alt3.fail | 1 - ....fail => base_closure_continue_assign_alt3.sav} | 4 --- tests/sav/base_closure_multi_alt6.sav | 1 + tests/test_closure_inlined_return.nit | 2 +- 12 files changed, 74 insertions(+), 46 deletions(-) create mode 100644 tests/sav/base_closure1_alt12.sav delete mode 100644 tests/sav/base_closure8_alt4.fail create mode 100644 tests/sav/base_closure8_alt4.sav delete mode 100644 tests/sav/base_closure_continue_assign_alt3.fail rename tests/sav/{base_closure1_alt12.fail => base_closure_continue_assign_alt3.sav} (57%) create mode 100644 tests/sav/base_closure_multi_alt6.sav diff --git a/src/metamodel/static_type.nit b/src/metamodel/static_type.nit index 541e3e5..3c34a9b 100644 --- a/src/metamodel/static_type.nit +++ b/src/metamodel/static_type.nit @@ -81,6 +81,15 @@ class MMSignature # 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 @@ -214,6 +223,9 @@ end # 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 @@ -228,11 +240,12 @@ class MMClosure # 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 @@ -242,7 +255,7 @@ class MMClosure 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 diff --git a/src/syntax/icode_generation.nit b/src/syntax/icode_generation.nit index f002863..b87f91c 100644 --- a/src/syntax/icode_generation.nit +++ b/src/syntax/icode_generation.nit @@ -1244,14 +1244,24 @@ redef class ASendExpr 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 diff --git a/src/syntax/mmbuilder.nit b/src/syntax/mmbuilder.nit index 60deaf2..52855c8 100644 --- a/src/syntax/mmbuilder.nit +++ b/src/syntax/mmbuilder.nit @@ -1228,10 +1228,17 @@ redef class AClosureDecl # 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) diff --git a/src/syntax/typing.nit b/src/syntax/typing.nit index 0f19f7f..78a9498 100644 --- a/src/syntax/typing.nit +++ b/src/syntax/typing.nit @@ -1124,12 +1124,23 @@ redef class AAbsAbsSendExpr # 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 @@ -1567,6 +1578,16 @@ redef class AClosureCallExpr 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) diff --git a/tests/base_closure_multi.nit b/tests/base_closure_multi.nit index f533838..65df401 100644 --- a/tests/base_closure_multi.nit +++ b/tests/base_closure_multi.nit @@ -15,11 +15,11 @@ # limitations under the License. import kernel - fun a !a1 !a2 #!alt1# #alt2# !a3 +#alt6# !a1 do a1 a2 #!alt1# diff --git a/tests/sav/base_closure1_alt12.sav b/tests/sav/base_closure1_alt12.sav new file mode 100644 index 0000000..672b85a --- /dev/null +++ b/tests/sav/base_closure1_alt12.sav @@ -0,0 +1 @@ +alt/base_closure1_alt12.nit:46,10--12: Error: no closure named '!baz' in foo; only closure is !bar. diff --git a/tests/sav/base_closure8_alt4.fail b/tests/sav/base_closure8_alt4.fail deleted file mode 100644 index 6948f2d..0000000 --- a/tests/sav/base_closure8_alt4.fail +++ /dev/null @@ -1,21 +0,0 @@ -0 -[1 -2 -[3 -4 -5 -4 -5 -]3 -6 -2 -[3 -4 -5 -4 -5 -]3 -6 -]1 -7 -8 diff --git a/tests/sav/base_closure8_alt4.sav b/tests/sav/base_closure8_alt4.sav new file mode 100644 index 0000000..338aa5f --- /dev/null +++ b/tests/sav/base_closure8_alt4.sav @@ -0,0 +1 @@ +alt/base_closure8_alt4.nit:29,8--10: Error: no closure named '!baz' in bar; only closure is !break. diff --git a/tests/sav/base_closure_continue_assign_alt3.fail b/tests/sav/base_closure_continue_assign_alt3.fail deleted file mode 100644 index 3a76f19..0000000 --- a/tests/sav/base_closure_continue_assign_alt3.fail +++ /dev/null @@ -1 +0,0 @@ -alt/base_closure_continue_assign_alt3.nit:47,10: Error: continue without value required in this block. diff --git a/tests/sav/base_closure1_alt12.fail b/tests/sav/base_closure_continue_assign_alt3.sav similarity index 57% rename from tests/sav/base_closure1_alt12.fail rename to tests/sav/base_closure_continue_assign_alt3.sav index d4bc414..b414108 100644 --- a/tests/sav/base_closure1_alt12.fail +++ b/tests/sav/base_closure_continue_assign_alt3.sav @@ -1,10 +1,6 @@ -0 1 2 3 4 -1 --1 -4 5 6 diff --git a/tests/sav/base_closure_multi_alt6.sav b/tests/sav/base_closure_multi_alt6.sav new file mode 100644 index 0000000..1c9b3cb --- /dev/null +++ b/tests/sav/base_closure_multi_alt6.sav @@ -0,0 +1 @@ +alt/base_closure_multi_alt6.nit:22,4--5: A closure '!a1' already defined at 19,3--4. diff --git a/tests/test_closure_inlined_return.nit b/tests/test_closure_inlined_return.nit index 3a7f3d6..cf5f034 100644 --- a/tests/test_closure_inlined_return.nit +++ b/tests/test_closure_inlined_return.nit @@ -16,7 +16,7 @@ do 0.output var i = 0 while i < 3 do - foo !each do + foo !k do ' '.output ' '.output '<'.output -- 1.7.9.5