end
end
+redef class Variable
+ # Is the variable must be set before being used ?
+ meth must_be_set: Bool do return false
+end
+
+redef class VarVariable
+ redef meth must_be_set do return true
+end
+
+
+
# Control flow visitor
# * Check reachability in methods
# * Associate breaks and continues
end
# Number of nested once
- readable writable attr _once_count: Int
+ readable writable attr _once_count: Int = 0
# Current knowledge about variables types
readable writable attr _control_flow_ctx: ControlFlowContext
meth check_is_set(n: PNode, v: Variable)
do
- if not control_flow_ctx.is_set(v) then
+ if v.must_be_set and not control_flow_ctx.is_set(v) then
error(n, "Error: variable '{v}' is possibly unset.")
var cfc = control_flow_ctx
while cfc != null do
# Previous control flow context if any
readable attr _prev: ControlFlowContext
- # Is a return met?
- readable writable attr _has_return: Bool
-
# Is a control flow break met? (return, break, continue)
- readable writable attr _unreash: Bool
+ readable writable attr _unreash: Bool = false
# Is a control flow already broken?
# Used to avoid repeating the same error message
- readable writable attr _already_unreash: Bool
+ readable writable attr _already_unreash: Bool = false
# Current controlable block (for or while)
readable writable attr _base_block: AControlableBlock
meth sub: ControlFlowContext
do
- return new ControlFlowContext.with(self)
+ return new ControlFlowContext.with_prev(self)
end
init
do
end
- init with(p: ControlFlowContext)
+ init with_prev(p: ControlFlowContext)
do
_prev = p
- _has_return = p.has_return
_unreash = p.unreash
_already_unreash = p.already_unreash
_base_block = p.base_block
redef meth accept_control_flow(v)
do
super
- if v.control_flow_ctx.has_return == false and method.signature.return_type != null then
- v.error(self, "Control error: Reached end of function.")
+ if v.control_flow_ctx.unreash == false and method.signature.return_type != null then
+ v.error(self, "Control error: Reached end of function (a 'return' with a value was expected).")
end
end
end
-redef class PParam
- redef meth accept_control_flow(v)
- do
- super
- v.mark_is_set(variable)
- end
-end
-
redef class AVardeclExpr
redef meth accept_control_flow(v)
do
redef meth accept_control_flow(v)
do
super
- v.control_flow_ctx.has_return = true
v.control_flow_ctx.unreash = true
end
end
redef meth accept_control_flow(v)
do
super
- v.control_flow_ctx.has_return = true
v.control_flow_ctx.unreash = true
end
end
v.visit(n_else)
# Merge then and else in the old control_flow
- old_control_flow_ctx.has_return = v.control_flow_ctx.has_return and then_control_flow_ctx.has_return
old_control_flow_ctx.unreash = v.control_flow_ctx.unreash and then_control_flow_ctx.unreash
if v.control_flow_ctx.unreash then v.control_flow_ctx = then_control_flow_ctx
special AControlableBlock
end
-redef class AForVardeclExpr
- redef meth accept_control_flow(v)
- do
- super
- v.mark_is_set(variable)
- end
-end
-
-
redef class AVarExpr
redef meth accept_control_flow(v)
do