An IRoutine knows all its local escape marks.
This fix some bugs with nesting and escapes since only marks of the
current iroutine needs to be duplicated (like what is done for registers).
Signed-off-by: Jean Privat <jean@pryen.org>
var _last_label: Int = 0
# Return the name of e
# If e is unknown, a new name is gived
- fun lab(e: ISeq): String
+ fun lab(e: IEscapeMark): String
do
if _ids.has_key(e) then
return _ids[e]
end
# Is the label e known? (because we goto to it)
- fun has_lab(e: ISeq): Bool
+ fun has_lab(e: IEscapeMark): Bool
do
return _ids.has_key(e)
end
for ic in icodes do
ic.dump(icd)
end
- if icd.has_lab(self) then icd.write("{icd.lab(self)}:")
+ var mark = iescape_mark
+ if mark != null and icd.has_lab(mark) then icd.write("{icd.lab(mark)}:")
end
end
end
icd.unindent
icd.write "}"
- if icd.has_lab(self) then icd.write("{icd.lab(self)}:")
+ var mark = iescape_mark
+ if mark != null and icd.has_lab(mark) then icd.write("{icd.lab(mark)}:")
end
end
redef class IEscape
redef fun dump_intern(icd)
do
- return "ESCAPE {icd.lab(seq)}"
+ return "ESCAPE {icd.lab(iescape_mark)}"
end
end
end
end
+ # Association between IEscapeMarks and visited ISeq
+ readable var _marks_to_seq: Map[IEscapeMark, ISeq] = new HashMap[IEscapeMark, ISeq]
+
# Are we in a closure ?
readable writable var _closure: Bool = false
redef fun inner_compile_to_c(v)
do
v.local_labels.add(self)
+ var mark = iescape_mark
+ if mark != null then v.marks_to_seq[mark] = self
for ic in icodes do
ic.compile_to_c(v)
end
redef fun inner_compile_to_c(v)
do
v.local_labels.add(self)
+ var mark = iescape_mark
+ if mark != null then v.marks_to_seq[mark] = self
v.add_instr("while(1) \{")
v.indent
for ic in icodes do
redef class IEscape
redef fun inner_compile_to_c(v)
do
- v.add_goto(seq)
+ v.add_goto(v.marks_to_seq[iescape_mark])
return null
end
end
end
end
+# A mark used to associate IEscapes to ISeqs
+class IEscapeMark
+end
+
# A Closure declaration
class IClosureDecl
# The associated closure definition
# The result of the routine
readable var _result: nullable IRegister
+ # The local escapes marks of the routine
+ readable var _escape_marks: Set[IEscapeMark] = new ArraySet[IEscapeMark]
+
# The sequence of icode
readable var _body: ISeq = new ISeq
special ICode0
# The sequence of icode
readable var _icodes: List[ICode] = new List[ICode]
+
+ # The associated iescape_mark (if any)
+ readable writable var _iescape_mark: nullable IEscapeMark
+
init do end
end
class IEscape
special ICode0
# The seqeuence to escape
- # The control flow continues at the next icode after the sequence
- readable var _seq: ISeq
- init(seq: ISeq) do _seq = seq
+ # The control flow continues at the next icode after the associated sequence
+ readable var _iescape_mark: IEscapeMark
+ init(mark: IEscapeMark) do _iescape_mark = mark
end
# An abort statement
end
# Add an escape to a given sequence
+ # Create a new IEscapeMark if required
fun add_escape(seq: ISeq)
do
- stmt(new IEscape(seq))
+ var mark = seq.iescape_mark
+ if mark == null then
+ mark = new IEscapeMark
+ iroutine.escape_marks.add(mark)
+ seq.iescape_mark = mark
+ end
+ stmt(new IEscape(mark))
end
# Return a literal "null" value
#seq.icodes.add(new IMove(dico[routine.params[i]]), args[i]))
end
+ # Fill escape mark association
+ for m in routine.escape_marks do
+ var m2 = new IEscapeMark
+ iroutine.escape_marks.add(m2)
+ d._marks[m] = m2
+ end
+
# Fill closure association
if closdecls != null then
var cdico = d._closures
return a
end
- # The associoation between old_seq and new_seq
- # Directly used by the IEscape
- var _seqs: Map[ISeq, ISeq] = new HashMap[ISeq, ISeq]
-
# The assocation between old_ireg and new_ireg
# Used by dup_ireg
var _registers: Map[IRegister, IRegister] = new HashMap[IRegister, IRegister]
+ # Return the correct escape mark
+ # * a duplicate of the local escape mark 'm' of the inlined iroutine
+ # * 'r' else (it is a escape mark of the caller iroutine)
+ fun dup_mark(m: IEscapeMark): IEscapeMark
+ do
+ var ms = _marks
+ if ms.has_key(m) then
+ return ms[m]
+ else
+ return m
+ end
+ end
+
+ # The associoation between old_seq and new_seq
+ # Used by dup_mark
+ var _marks: Map[IEscapeMark, IEscapeMark] = new HashMap[IEscapeMark, IEscapeMark]
+
# The association between a closure_decl and its closure_def (if any)
var _closures: Map[IClosureDecl, nullable IClosureDef] = new ArrayMap[IClosureDecl, nullable IClosureDef]
do
var old_seq = d._icb.seq
d._icb.seq = dest
- d._seqs[self] = dest
for c in icodes do
c.dup_with(d)
end
d._icb.seq = old_seq
+ assert dest.iescape_mark == null
+ var mark = iescape_mark
+ if mark != null then
+ dest.iescape_mark = d.dup_mark(mark)
+ end
end
end
redef class IEscape
redef fun inner_dup_with(d)
do
- if d._seqs.has_key(seq) then
- # Jump to a duplicated sequence
- return new IEscape(d._seqs[seq])
- else
- # Jump to an englobing unduplicated sequence
- return new IEscape(seq)
- end
+ # Get the associated mark (duplicated of not)
+ var mark = d.dup_mark(iescape_mark)
+ # Jump to the mark
+ return new IEscape(mark)
end
end
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2008 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
+
+class Inline__
+ fun foo1
+ !f
+ do
+ f
+ 5.output
+ end
+
+ fun foo2
+ !f
+ do
+ f
+ 2.output
+ end
+end
+
+var a = new Inline__
+a.foo1 !f do
+ do
+ a.foo2 !f do
+ #alt1#break label l1
+ #alt2#break label l2
+ #alt3#break label l3
+ #alt4#continue label l1
+ #alt5#continue label l2
+ 1.output
+ end label l1
+ 3.output
+ end label l3
+ 4.output
+end label l2
+6.output
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2008 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
+
+class Inline__
+ fun foo1: Int
+ !f: Int
+ do
+ f.output
+ return 5
+ end
+
+ fun foo2: Int
+ !f: Int
+ do
+ f.output
+ return 2
+ end
+end
+
+var a = new Inline__
+var x = a.foo1 !f do
+ do
+ var y = a.foo2 !f do
+ #alt1#break label l1 20
+ #alt2#break label l2 50
+ #alt3#break label l3
+ #alt4#continue label l1 10
+ #alt5#continue label l2 40
+ continue 1
+ end label l1
+ y.output
+ 3.output
+ end label l3
+ continue 4
+end label l2
+x.output
+6.output
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2008 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
+
+class Inline__
+ fun foo
+ !f
+ do
+ do
+ if true then
+ f
+ break label l0
+ end
+ 0.output
+ end label l0
+ 5.output
+ end
+end
+
+var a = new Inline__
+a.foo !f do
+ do
+ a.foo !f do
+ #alt1#break label l1
+ #alt2#break label l2
+ #alt3#break label l3
+ #alt4#continue label l1
+ #alt5#continue label l2
+ 1.output
+ end label l1
+ 3.output
+ end label l3
+ 4.output
+end label l2
+6.output
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2008 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
+
+class Inline__
+ fun foo1
+ !f
+ do
+ f
+ f
+ end
+ fun foo2
+ !f
+ do
+ f
+ f
+ end
+end
+
+class B
+ var _b: Int
+ redef fun output do _b.output
+end
+
+var a = new Inline__
+a.foo1 !f do
+ var x = new B(1)
+ var y = 2
+ a.foo2 !f do
+ x.output
+ y.output
+ x = new B(3)
+ y = 4
+ #alt1#break label l1
+ #alt2#break label l2
+ #alt3#continue label l1
+ #alt4#continue label l2
+ end label l1
+ x.output
+ y.output
+end label l2
+5.output
--- /dev/null
+1
+2
+3
+4
+5
+6
--- /dev/null
+1
+2
+3
+4
+5
+6
--- /dev/null
+20
+3
+4
+5
+6
--- /dev/null
+10
+2
+3
+4
+5
+6
--- /dev/null
+1
+5
+3
+4
+5
+6
--- /dev/null
+3
+4
+5
+6
--- /dev/null
+5
+3
+4
+5
+6
--- /dev/null
+3
+4
+5
+6
--- /dev/null
+2
+3
+4
+5
+6
--- /dev/null
+1
+2
+3
+4
+3
+4
+1
+2
+3
+4
+3
+4
+5
--- /dev/null
+1
+2
+3
+4
+1
+2
+3
+4
+5
--- /dev/null
+1
+2
+3
+4
+3
+4
+1
+2
+3
+4
+3
+4
+5
--- /dev/null
+1
+2
+1
+2
+5