summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
d67a692)
Signed-off-by: Jean Privat <jean@pryen.org>
private init make
do
_n_kwdo = new TKwdo
private init make
do
_n_kwdo = new TKwdo
- escapemark = new EscapeMark(null, false)
+ escapemark = new EscapeMark(null)
end
# Make a new break expression of the given do
end
# Make a new break expression of the given do
do
var escapemark = self.escapemark
if escapemark == null then
do
var escapemark = self.escapemark
if escapemark == null then
- escapemark = new EscapeMark(null, false)
+ escapemark = new EscapeMark(null)
self.escapemark = escapemark
end
return new ABreakExpr.make(escapemark)
self.escapemark = escapemark
end
return new ABreakExpr.make(escapemark)
+ # Insert a C label for associated with an escapemark
+ fun add_escape_label(e: nullable EscapeMark)
+ do
+ if e == null then return
+ if e.escapes.is_empty then return
+ add("BREAK_{escapemark_name(e)}: (void)0;")
+ end
+
private var escapemark_names = new HashMap[EscapeMark, String]
# Return a "const char*" variable associated to the classname of the dynamic type of an object
private var escapemark_names = new HashMap[EscapeMark, String]
# Return a "const char*" variable associated to the classname of the dynamic type of an object
redef fun expr(v) do return v.frame.arguments.first
end
redef fun expr(v) do return v.frame.arguments.first
end
-redef class AContinueExpr
- redef fun stmt(v) do v.add("goto CONTINUE_{v.escapemark_name(self.escapemark)};")
-end
-
-redef class ABreakExpr
redef fun stmt(v) do v.add("goto BREAK_{v.escapemark_name(self.escapemark)};")
end
redef fun stmt(v) do v.add("goto BREAK_{v.escapemark_name(self.escapemark)};")
end
redef fun stmt(v)
do
v.stmt(self.n_block)
redef fun stmt(v)
do
v.stmt(self.n_block)
- var escapemark = self.escapemark
- if escapemark != null then
- v.add("BREAK_{v.escapemark_name(escapemark)}: (void)0;")
- end
+ v.add_escape_label(break_mark)
var cond = v.expr_bool(self.n_expr)
v.add("if (!{cond}) break;")
v.stmt(self.n_block)
var cond = v.expr_bool(self.n_expr)
v.add("if (!{cond}) break;")
v.stmt(self.n_block)
- v.add("CONTINUE_{v.escapemark_name(escapemark)}: (void)0;")
+ v.add_escape_label(continue_mark)
- v.add("BREAK_{v.escapemark_name(escapemark)}: (void)0;")
+ v.add_escape_label(break_mark)
do
v.add("for(;;) \{")
v.stmt(self.n_block)
do
v.add("for(;;) \{")
v.stmt(self.n_block)
- v.add("CONTINUE_{v.escapemark_name(escapemark)}: (void)0;")
+ v.add_escape_label(continue_mark)
- v.add("BREAK_{v.escapemark_name(escapemark)}: (void)0;")
+ v.add_escape_label(break_mark)
- v.add("CONTINUE_{v.escapemark_name(escapemark)}: (void)0;")
+ v.add_escape_label(continue_mark)
var succ = v.send(v.get_property("successor", variable.mtype), [variable, one])
assert succ != null
v.assign(variable, succ)
v.add("\}")
var succ = v.send(v.get_property("successor", variable.mtype), [variable, one])
assert succ != null
v.assign(variable, succ)
v.add("\}")
- v.add("BREAK_{v.escapemark_name(escapemark)}: (void)0;")
+ v.add_escape_label(break_mark)
abort
end
v.stmt(self.n_block)
abort
end
v.stmt(self.n_block)
- v.add("CONTINUE_{v.escapemark_name(escapemark)}: (void)0;")
+ v.add_escape_label(continue_mark)
var next_meth = self.method_next
assert next_meth != null
v.compile_callsite(next_meth, [it])
v.add("\}")
var next_meth = self.method_next
assert next_meth != null
v.compile_callsite(next_meth, [it])
v.add("\}")
- v.add("BREAK_{v.escapemark_name(escapemark)}: (void)0;")
+ v.add_escape_label(break_mark)
var method_finish = self.method_finish
if method_finish != null then
var method_finish = self.method_finish
if method_finish != null then
# Set this mark to skip the evaluation until the end of the specified method frame
var returnmark: nullable Frame = null
# Set this mark to skip the evaluation until the end of the specified method frame
var returnmark: nullable Frame = null
- # Is a break executed?
- # Set this mark to skip the evaluation until a labeled statement catch it with `is_break`
- var breakmark: nullable EscapeMark = null
-
- # Is a continue executed?
- # Set this mark to skip the evaluation until a labeled statement catch it with `is_continue`
- var continuemark: nullable EscapeMark = null
+ # Is a break or a continue executed?
+ # Set this mark to skip the evaluation until a labeled statement catch it with `is_escape`
+ var escapemark: nullable EscapeMark = null
# Is a return or a break or a continue executed?
# Use this function to know if you must skip the evaluation of statements
# Is a return or a break or a continue executed?
# Use this function to know if you must skip the evaluation of statements
- fun is_escaping: Bool do return returnmark != null or breakmark != null or continuemark != null
+ fun is_escaping: Bool do return returnmark != null or escapemark != null
# The value associated with the current return/break/continue, if any.
# Set the value when you set a escapemark.
# Read the value when you catch a mark or reach the end of a method
var escapevalue: nullable Instance = null
# The value associated with the current return/break/continue, if any.
# Set the value when you set a escapemark.
# Read the value when you catch a mark or reach the end of a method
var escapevalue: nullable Instance = null
- # If there is a break and is associated with `escapemark`, then return true an clear the mark.
- # If there is no break or if `escapemark` is null then return false.
- # Use this function to catch a potential break.
- fun is_break(escapemark: nullable EscapeMark): Bool
- do
- if escapemark != null and self.breakmark == escapemark then
- self.breakmark = null
- return true
- else
- return false
- end
- end
-
- # If there is a continue and is associated with `escapemark`, then return true an clear the mark.
- # If there is no continue or if `escapemark` is null then return false.
- # Use this function to catch a potential continue.
- fun is_continue(escapemark: nullable EscapeMark): Bool
+ # If there is a break/continue and is associated with `escapemark`, then return true and clear the mark.
+ # If there is no break/continue or if `escapemark` is null then return false.
+ # Use this function to catch a potential break/continue.
+ fun is_escape(escapemark: nullable EscapeMark): Bool
- if escapemark != null and self.continuemark == escapemark then
- self.continuemark = null
+ if escapemark != null and self.escapemark == escapemark then
+ self.escapemark = null
return true
else
return false
return true
else
return false
-redef class AContinueExpr
- redef fun stmt(v)
- do
- var ne = self.n_expr
- if ne != null then
- var i = v.expr(ne)
- if i == null then return
- v.escapevalue = i
- end
- v.continuemark = self.escapemark
- end
-end
-
-redef class ABreakExpr
redef fun stmt(v)
do
var ne = self.n_expr
redef fun stmt(v)
do
var ne = self.n_expr
if i == null then return
v.escapevalue = i
end
if i == null then return
v.escapevalue = i
end
- v.breakmark = self.escapemark
+ v.escapemark = self.escapemark
redef fun stmt(v)
do
v.stmt(self.n_block)
redef fun stmt(v)
do
v.stmt(self.n_block)
- v.is_break(self.escapemark) # Clear the break (if any)
+ v.is_escape(self.break_mark) # Clear the break (if any)
if cond == null then return
if not cond.is_true then return
v.stmt(self.n_block)
if cond == null then return
if not cond.is_true then return
v.stmt(self.n_block)
- if v.is_break(self.escapemark) then return
- v.is_continue(self.escapemark) # Clear the break
+ if v.is_escape(self.break_mark) then return
+ v.is_escape(self.continue_mark) # Clear the break
if v.is_escaping then return
end
end
if v.is_escaping then return
end
end
do
loop
v.stmt(self.n_block)
do
loop
v.stmt(self.n_block)
- if v.is_break(self.escapemark) then return
- v.is_continue(self.escapemark) # Clear the break
+ if v.is_escape(self.break_mark) then return
+ v.is_escape(self.continue_mark) # Clear the break
if v.is_escaping then return
end
end
if v.is_escaping then return
end
end
abort
end
v.stmt(self.n_block)
abort
end
v.stmt(self.n_block)
- if v.is_break(self.escapemark) then break
- v.is_continue(self.escapemark) # Clear the break
+ if v.is_escape(self.break_mark) then break
+ v.is_escape(self.continue_mark) # Clear the break
if v.is_escaping then break
v.callsite(method_next, [iter])
end
if v.is_escaping then break
v.callsite(method_next, [iter])
end
fun merge_continues_to(before_loop: FlowContext, escapemark: nullable EscapeMark)
do
if escapemark == null then return
fun merge_continues_to(before_loop: FlowContext, escapemark: nullable EscapeMark)
do
if escapemark == null then return
- for b in escapemark.continues do
+ for b in escapemark.escapes do
var before = b.before_flow_context
if before == null then continue # Forward error
before_loop.add_loop(before)
var before = b.before_flow_context
if before == null then continue # Forward error
before_loop.add_loop(before)
fun merge_breaks(escapemark: nullable EscapeMark)
do
if escapemark == null then return
fun merge_breaks(escapemark: nullable EscapeMark)
do
if escapemark == null then return
- for b in escapemark.breaks do
+ for b in escapemark.escapes do
var before = b.before_flow_context
if before == null then continue # Forward error
self.make_merge_flow(self.current_flow_context, before)
var before = b.before_flow_context
if before == null then continue # Forward error
self.make_merge_flow(self.current_flow_context, before)
redef fun accept_flow_visitor(v)
do
super
redef fun accept_flow_visitor(v)
do
super
- v.merge_breaks(self.escapemark)
+ v.merge_breaks(self.break_mark)
var after_block = v.current_flow_context
before_loop.add_loop(after_block)
var after_block = v.current_flow_context
before_loop.add_loop(after_block)
- v.merge_continues_to(after_block, self.escapemark)
+ v.merge_continues_to(after_block, self.continue_mark)
v.current_flow_context = after_expr.when_false
v.current_flow_context = after_expr.when_false
- v.merge_breaks(self.escapemark)
+ v.merge_breaks(self.break_mark)
var after_block = v.current_flow_context
before_loop.add_loop(after_block)
var after_block = v.current_flow_context
before_loop.add_loop(after_block)
- v.merge_continues_to(after_block, self.escapemark)
+ v.merge_continues_to(after_block, self.continue_mark)
- v.merge_breaks(self.escapemark)
+ v.merge_breaks(self.break_mark)
var after_block = v.current_flow_context
before_loop.add_loop(after_block)
var after_block = v.current_flow_context
before_loop.add_loop(after_block)
- v.merge_continues_to(after_block, self.escapemark)
+ v.merge_continues_to(after_block, self.continue_mark)
v.make_merge_flow(v.current_flow_context, before_loop)
v.make_merge_flow(v.current_flow_context, before_loop)
- v.merge_breaks(self.escapemark)
+ v.merge_breaks(self.break_mark)
# The name of the label (unless the mark is an anonymous loop mark)
var name: nullable String
# The name of the label (unless the mark is an anonymous loop mark)
var name: nullable String
- # Is the mark attached to a loop (loop, while, for)
- # Such a mark is a candidate to a labelless 'continue' or 'break'
- var for_loop: Bool
+ # The associated `continue` mark, if any.
+ # If the mark attached to a loop (loop, while, for), a distinct mark is used.
+ private var continue_mark: nullable EscapeMark = null
- # Each 'continue' attached to the mark
- var continues = new Array[AContinueExpr]
-
- # Each 'break' attached to the mark
- var breaks = new Array[ABreakExpr]
+ # Each break/continue attached to the mark
+ var escapes = new Array[AEscapeExpr]
end
# Visit a npropdef and:
end
# Visit a npropdef and:
end
# All stacked scope. `scopes.first` is the current scope
end
# All stacked scope. `scopes.first` is the current scope
- private var scopes = new List[Scope]
+ var scopes = new List[Scope]
# Shift and check the last scope
fun shift_scope
# Shift and check the last scope
fun shift_scope
- var res = new EscapeMark(name, for_loop)
+ var res = new EscapeMark(name)
+ if for_loop then res.continue_mark = new EscapeMark(name)
super
var escapemark = v.get_escapemark(self, self.n_label)
if escapemark == null then return # Skip error
super
var escapemark = v.get_escapemark(self, self.n_label)
if escapemark == null then return # Skip error
- if not escapemark.for_loop then
+ escapemark = escapemark.continue_mark
+ if escapemark == null then
v.error(self, "Error: cannot 'continue', only 'break'.")
v.error(self, "Error: cannot 'continue', only 'break'.")
- escapemark.continues.add(self)
+ escapemark.escapes.add(self)
self.escapemark = escapemark
end
end
self.escapemark = escapemark
end
end
super
var escapemark = v.get_escapemark(self, self.n_label)
if escapemark == null then return # Skip error
super
var escapemark = v.get_escapemark(self, self.n_label)
if escapemark == null then return # Skip error
- escapemark.breaks.add(self)
+ escapemark.escapes.add(self)
self.escapemark = escapemark
end
end
redef class ADoExpr
self.escapemark = escapemark
end
end
redef class ADoExpr
- # The escape mark associated with the 'do' block
- var escapemark: nullable EscapeMark
+ # The break escape mark associated with the 'do' block
+ var break_mark: nullable EscapeMark
+
redef fun accept_scope_visitor(v)
do
redef fun accept_scope_visitor(v)
do
- self.escapemark = v.make_escape_mark(n_label, false)
- v.enter_visit_block(n_block, self.escapemark)
+ self.break_mark = v.make_escape_mark(n_label, false)
+ v.enter_visit_block(n_block, self.break_mark)
end
redef class AWhileExpr
end
redef class AWhileExpr
- # The escape mark associated with the 'while'
- var escapemark: nullable EscapeMark
+ # The break escape mark associated with the 'while'
+ var break_mark: nullable EscapeMark
+
+ # The continue escape mark associated with the 'while'
+ var continue_mark: nullable EscapeMark
+
redef fun accept_scope_visitor(v)
do
var escapemark = v.make_escape_mark(n_label, true)
redef fun accept_scope_visitor(v)
do
var escapemark = v.make_escape_mark(n_label, true)
- self.escapemark = escapemark
+ self.break_mark = escapemark
+ self.continue_mark = escapemark.continue_mark
v.enter_visit(n_expr)
v.enter_visit_block(n_block, escapemark)
end
end
redef class ALoopExpr
v.enter_visit(n_expr)
v.enter_visit_block(n_block, escapemark)
end
end
redef class ALoopExpr
- # The escape mark associated with the 'loop'
- var escapemark: nullable EscapeMark
+ # The break escape mark associated with the 'loop'
+ var break_mark: nullable EscapeMark
+
+ # The continue escape mark associated with the 'loop'
+ var continue_mark: nullable EscapeMark
+
redef fun accept_scope_visitor(v)
do
var escapemark = v.make_escape_mark(n_label, true)
redef fun accept_scope_visitor(v)
do
var escapemark = v.make_escape_mark(n_label, true)
- self.escapemark = escapemark
+ self.break_mark = escapemark
+ self.continue_mark = escapemark.continue_mark
v.enter_visit_block(n_block, escapemark)
end
end
v.enter_visit_block(n_block, escapemark)
end
end
# The automatic variables in order
var variables: nullable Array[Variable]
# The automatic variables in order
var variables: nullable Array[Variable]
- # The escape mark associated with the 'for'
- var escapemark: nullable EscapeMark
+ # The break escape mark associated with the 'for'
+ var break_mark: nullable EscapeMark
+
+ # The continue escape mark associated with the 'for'
+ var continue_mark: nullable EscapeMark
redef fun accept_scope_visitor(v)
do
redef fun accept_scope_visitor(v)
do
end
var escapemark = v.make_escape_mark(n_label, true)
end
var escapemark = v.make_escape_mark(n_label, true)
- self.escapemark = escapemark
+ self.break_mark = escapemark
+ self.continue_mark = escapemark.continue_mark
v.enter_visit_block(n_block, escapemark)
v.shift_scope
v.enter_visit_block(n_block, escapemark)
v.shift_scope