# Stack of blocks
var _stack: Array[EscapableBlock] = new Array[EscapableBlock]
+ # Known labels
+ # (all labels, even out of scopes ones)
+ # Used to find duplicates
+ var _labels: Array[ALabel] = new Array[ALabel]
+
# Push a new escapable block
- fun push(block: EscapableBlock)
+ # Display error message if tere is a problem with the label
+ fun push(block: EscapableBlock, n_label: nullable ALabel)
do
_stack.push(block)
+ if n_label != null then
+ var lab = n_label.n_id.to_symbol
+ for nl in _labels do
+ if n_label != nl and lab == nl.n_id.to_symbol then
+ visitor.error(n_label, "Syntax error: label {lab} already defined at {nl.location.relative_to(n_label.location)}.")
+ return
+ end
+ end
+ _labels.add(n_label)
+ block._lab = lab
+ end
end
# Is there no block in the stack?
return _stack.last
end
+ # Return the block associed to a label
+ # Output an error end return null if the label is not known
+ fun get_by_label(nl: ALabel): nullable EscapableBlock
+ do
+ var i = _stack.length - 1
+ var block: nullable EscapableBlock = null
+ var lab = nl.n_id.to_symbol
+ while i >= 0 do
+ var b = _stack[i]
+ if b.lab == lab then return b
+ i -= 1
+ end
+ visitor.error(nl, "Syntax error: invalid label {lab}.")
+ return null
+ end
+
# Remove the last block (the last stacked)
fun pop
do
# The syntax node of the block
readable var _node: ANode
+ # The label of the block (if any)
+ # Set by the push in EscapableContext
+ readable var _lab: nullable Symbol
+
# Is self a break closure ?
fun is_break_block: Bool do return false
###############################################################################
class AEscapeExpr
-special ANode
+special ALabelable
# The associated escapable block
readable var _escapable: nullable EscapableBlock
# Compute, set and return the associated escapable block
fun compute_escapable_block(lctx: EscapableContext): nullable EscapableBlock
do
- var block: EscapableBlock
- if lctx.is_empty then
+ var block: nullable EscapableBlock
+ var nl = n_label
+ if nl != null then
+ block = lctx.get_by_label(nl)
+ else if lctx.is_empty then
lctx.visitor.error(self, "Syntax Error: '{kwname}' statment outside block.")
return null
+ else
+ block = lctx.head
end
- block = lctx.head
_escapable = block
return block
end
var escapable = new EscapableClosure(self, variable.closure, null)
_escapable = escapable
- v.escapable_ctx.push(escapable)
+ v.escapable_ctx.push(escapable, null)
super
do
var escapable = new EscapableBlock(self)
_escapable = escapable
- v.escapable_ctx.push(escapable)
+ v.escapable_ctx.push(escapable, n_label)
var old_var_ctx = v.variable_ctx
var old_base_var_ctx = v.base_variable_ctx
v.base_variable_ctx = v.variable_ctx
do
var escapable = new EscapableBlock(self)
_escapable = escapable
- v.escapable_ctx.push(escapable)
+ v.escapable_ctx.push(escapable, n_label)
var old_var_ctx = v.variable_ctx
var old_base_var_ctx = v.base_variable_ctx
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 csi = cs[i]
var cdi = cd[i]
var esc = new EscapableClosure(cdi, csi, break_list)
- v.escapable_ctx.push(esc)
+ v.escapable_ctx.push(esc, n_label)
cdi.accept_typing2(v, esc)
v.escapable_ctx.pop
end
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2009 Jean Privat <jean@pryen.org>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+fun foo
+ with bar
+do
+ bar with do 'X'.output
+end
+
+1.output
+foo with do
+ 2.output
+ foo with do
+ 3.output
+ foo with do end label l3
+ #alt1#break label l2
+ #alt2#break label l3
+ #alt3#break label l4
+ #alt4#break
+ #alt5#continue label l1
+ break label l1
+ 4.output
+ end label l2#!alt6#
+ #alt6#end label l1
+ 5.output
+end label l1
+6.output
+
+#alt7#foo with do end label l1
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2009 Jean Privat <jean@pryen.org>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+fun foo: Int
+ with bar: Int
+do
+ var i = bar with do 'X'.output
+ return i * 10
+end
+
+1.output
+var i = foo with do
+ 2.output
+ var j = foo with do
+ 3.output
+ foo with do
+ continue 0
+ end label l3
+ #alt1#break label l2 10
+ #alt2#break label l3 10
+ #alt3#break label l4 10
+ #alt4#break 10
+ #alt5#continue label l1 10
+ break label l1 10
+ 4.output
+ end label l2#!alt6#
+ #alt6#end label l1
+ j.output
+ 5.output
+ continue 20
+end label l1
+i.output
+6.output
+
+#alt7#foo with do
+#alt7# continue 0
+#alt7#end label l1
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2009 Jean Privat <jean@pryen.org>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+fun foo
+ with bar do end
+ with baz do end
+do
+ bar
+ baz
+end
+
+1.output
+foo with do
+ 2.output
+ foo with do
+ 3.output
+ foo with do end label l3
+ #alt1#break label l2
+ #alt2#break label l3
+ #alt3#break label l4
+ #alt4#break
+ #alt5#continue label l1
+ break label l1
+ 4.output
+ with do
+ 40.output
+ end label l2#!alt6#
+ #alt6#end label l1
+ 5.output
+with do
+ 50.output
+end label l1
+6.output
+
+#alt7#foo with do end label l1
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2009 Jean Privat <jean@pryen.org>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import abstract_collection
+
+var a = new Container[Int](1)
+1.output
+for i in a do
+ 2.output
+ for j in a do
+ 3.output
+ for k in a do end label l3
+ #alt1#break label l2
+ #alt2#break label l3
+ #alt3#break label l4
+ #alt4#break
+ #alt5#continue label l1
+ break label l1
+ 4.output
+ end label l2#!alt6#
+ #alt6#end label l1
+ 5.output
+end label l1
+6.output
+
+#alt7#for k in a do end label l1
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2009 Jean Privat <jean@pryen.org>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+var a = 1
+1.output
+while a == 1 do
+ a = 2
+ 2.output
+ while a == 2 do
+ a = 3
+ 3.output
+ while false do end label l3
+ #alt1#break label l2
+ #alt2#break label l3
+ #alt3#break label l4
+ #alt4#break
+ #alt5#continue label l1
+ break label l1
+ 4.output
+ end label l2#!alt6#
+ #alt6#end label l1
+ 5.output
+end label l1
+6.output
+
+#alt7#while false do end label l1
--- /dev/null
+1
+2
+3
+XX6
--- /dev/null
+1
+2
+3
+XX10
+6
--- /dev/null
+1
+2
+3
+X10
+5
+200
+6
--- /dev/null
+alt/base_label_closure2_alt2.nit:35,9--16: Syntax error: invalid label l3.
--- /dev/null
+alt/base_label_closure2_alt3.nit:36,9--16: Syntax error: invalid label l4.
--- /dev/null
+1
+2
+3
+X10
+5
+200
+6
--- /dev/null
+1
+2
+3
+X100
+6
--- /dev/null
+alt/base_label_closure2_alt6.nit:41,6--13: Syntax error: label l1 already defined at 45,5--12.
--- /dev/null
+alt/base_label_closure2_alt7.nit:52,5--12: Syntax error: label l1 already defined at 46,5--12.
--- /dev/null
+1
+2
+3
+6
--- /dev/null
+1
+2
+3
+5
+50
+6
--- /dev/null
+alt/base_label_closure3_alt2.nit:34,9--16: Syntax error: invalid label l3.
--- /dev/null
+alt/base_label_closure3_alt3.nit:35,9--16: Syntax error: invalid label l4.
--- /dev/null
+1
+2
+3
+5
+50
+6
--- /dev/null
+1
+2
+3
+50
+6
--- /dev/null
+alt/base_label_closure3_alt6.nit:42,6--13: Syntax error: label l1 already defined at 46,5--12.
+alt/base_label_closure3_alt6.nit:42,6--13: Syntax error: label l1 already defined at 46,5--12.
--- /dev/null
+alt/base_label_closure3_alt7.nit:50,17--24: Syntax error: label l1 already defined at 47,5--12.
--- /dev/null
+1
+2
+3
+X5
+6
--- /dev/null
+alt/base_label_closure_alt2.nit:32,9--16: Syntax error: invalid label l3.
--- /dev/null
+alt/base_label_closure_alt3.nit:33,9--16: Syntax error: invalid label l4.
--- /dev/null
+1
+2
+3
+X5
+6
--- /dev/null
+1
+2
+3
+X6
--- /dev/null
+alt/base_label_closure_alt6.nit:38,6--13: Syntax error: label l1 already defined at 40,5--12.
--- /dev/null
+alt/base_label_closure_alt7.nit:44,17--24: Syntax error: label l1 already defined at 41,5--12.
--- /dev/null
+1
+2
+3
+6
--- /dev/null
+1
+2
+3
+5
+6
--- /dev/null
+alt/base_label_for_alt2.nit:27,9--16: Syntax error: invalid label l3.
--- /dev/null
+alt/base_label_for_alt3.nit:28,9--16: Syntax error: invalid label l4.
--- /dev/null
+1
+2
+3
+5
+6
--- /dev/null
+1
+2
+3
+6
--- /dev/null
+alt/base_label_for_alt6.nit:33,6--13: Syntax error: label l1 already defined at 35,5--12.
--- /dev/null
+alt/base_label_for_alt7.nit:39,19--26: Syntax error: label l1 already defined at 36,5--12.
--- /dev/null
+1
+2
+3
+6
--- /dev/null
+1
+2
+3
+5
+6
--- /dev/null
+alt/base_label_while_alt2.nit:29,9--16: Syntax error: invalid label l3.
--- /dev/null
+alt/base_label_while_alt3.nit:30,9--16: Syntax error: invalid label l4.
--- /dev/null
+1
+2
+3
+5
+6
--- /dev/null
+1
+2
+3
+6
--- /dev/null
+alt/base_label_while_alt6.nit:35,6--13: Syntax error: label l1 already defined at 37,5--12.
--- /dev/null
+alt/base_label_while_alt7.nit:41,20--27: Syntax error: label l1 already defined at 38,5--12.