- var res: nullable Array[nullable MType] = null
- if vars.has_key(variable) then
- var mtype = vars[variable]
- res = [mtype]
- else if self.previous.is_empty then
- # Root flow
- res = [variable.declared_type]
- else
- for flow in self.previous do
- if flow.is_unreachable then continue
- var r2 = flow.collect_types(variable)
- if r2 == null then continue
- if res == null then
- res = r2.to_a
- else
- for t in r2 do
- if not res.has(t) then res.add(t)
- end
+ #node.debug "flow for {variable}"
+ var res = new Array[nullable MType]
+
+ var todo = [self]
+ var seen = new HashSet[FlowContext]
+ while not todo.is_empty do
+ var f = todo.pop
+ if f.is_unreachable then continue
+ if seen.has(f) then continue
+ seen.add f
+
+ if f.vars.has_key(variable) then
+ # Found something. Collect it and do not process further on this path
+ res.add f.vars[variable]
+ #f.node.debug "process {variable}: got {f.vars[variable] or else "X"}"
+ else
+ todo.add_all f.previous
+ todo.add_all f.loops
+ if f.previous.is_empty then
+ # Root flowcontext mean a parameter or something related
+ res.add variable.declared_type
+ #f.node.debug "root process {variable}: got {variable.declared_type or else "X"}"