X-Git-Url: http://nitlanguage.org diff --git a/src/syntax/typing.nit b/src/syntax/typing.nit index f9d5eba..5525907 100644 --- a/src/syntax/typing.nit +++ b/src/syntax/typing.nit @@ -46,6 +46,9 @@ special AbsSyntaxVisitor # Current knowledge about variables names and types readable writable attr _variable_ctx: VariableContext + # Non-bypassable knowledge about variables names and types + readable writable attr _base_variable_ctx: VariableContext + # Current knowledge about escapable blocks readable writable attr _escapable_ctx: EscapableContext = new EscapableContext(self) @@ -166,6 +169,7 @@ redef class AMethPropdef redef meth accept_typing(v) do v.variable_ctx = new RootVariableContext(v, self) + v.base_variable_ctx = v.variable_ctx _self_var = v.self_var super end @@ -249,6 +253,8 @@ redef class AClosureDecl v.variable_ctx.add(variable) var old_var_ctx = v.variable_ctx + var old_base_var_ctx = v.base_variable_ctx + v.base_variable_ctx = v.variable_ctx v.variable_ctx = v.variable_ctx.sub(self) _escapable = new EscapableClosure(self, variable.closure, null) @@ -268,6 +274,7 @@ redef class AClosureDecl old_var_ctx.merge(v.variable_ctx) v.variable_ctx = old_var_ctx + v.base_variable_ctx = old_base_var_ctx v.escapable_ctx.pop end end @@ -451,7 +458,7 @@ redef class AIfExpr end # Merge 'then' and 'else' contexts - old_var_ctx.merge2(then_var_ctx, v.variable_ctx) + old_var_ctx.merge2(then_var_ctx, v.variable_ctx, v.base_variable_ctx) v.variable_ctx = old_var_ctx _is_typed = true end @@ -466,12 +473,25 @@ redef class AWhileExpr _escapable = new EscapableBlock(self) v.escapable_ctx.push(_escapable) var old_var_ctx = v.variable_ctx + var old_base_var_ctx = v.base_variable_ctx + v.base_variable_ctx = v.variable_ctx v.variable_ctx = v.variable_ctx.sub(self) - super - + # Process condition + v.visit(n_expr) v.check_conform_expr(n_expr, v.type_bool) + + # Prepare inside context (assert cond) + v.use_if_true_variable_ctx(n_expr) + + # Process inside + if n_block != null then + v.variable_ctx = v.variable_ctx.sub(n_block) + v.visit(n_block) + end + v.variable_ctx = old_var_ctx + v.base_variable_ctx = old_base_var_ctx v.escapable_ctx.pop _is_typed = true end @@ -491,6 +511,8 @@ redef class AForExpr v.escapable_ctx.push(_escapable) var old_var_ctx = v.variable_ctx + var old_base_var_ctx = v.base_variable_ctx + v.base_variable_ctx = v.variable_ctx v.variable_ctx = v.variable_ctx.sub(self) var va = new AutoVariable(n_id.to_symbol, self) variable = va @@ -529,6 +551,7 @@ redef class AForExpr # pop context v.variable_ctx = old_var_ctx + v.base_variable_ctx = old_base_var_ctx v.escapable_ctx.pop _is_typed = true end @@ -559,12 +582,14 @@ redef class AVarAssignExpr do v.variable_ctx.mark_is_set(variable) var t = v.variable_ctx.stype(variable) - if v.check_conform_expr(n_value, variable.stype) then - # Fall back to base type if current type does not match - if not n_value.stype < t then - v.variable_ctx.stype(variable) = variable.stype - end - end + + # Check the base type + var btype = v.base_variable_ctx.stype(variable) + if not v.check_conform_expr(n_value, btype) then return + + # Always cast + v.variable_ctx.stype(variable) = n_value.stype + _is_typed = true end end @@ -604,12 +629,14 @@ redef class AVarReassignExpr var t = v.variable_ctx.stype(variable) var t2 = do_rvalue_typing(v, t) if t2 == null then return - if v.check_conform(self, t2, variable.stype) then - # Fall back to base type if current type does not match - if not t2 < t then - v.variable_ctx.stype(variable) = variable.stype - end - end + + # Check the base type + var btype = v.base_variable_ctx.stype(variable) + if not v.check_conform(n_value, t2, btype) then return + + # Always cast + v.variable_ctx.stype(variable) = t2 + _is_typed = true end end @@ -1468,6 +1495,8 @@ redef class AClosureDef closure = esc.closure var old_var_ctx = v.variable_ctx + var old_base_var_ctx = v.base_variable_ctx + v.base_variable_ctx = v.variable_ctx v.variable_ctx = v.variable_ctx.sub(self) variables = new Array[AutoVariable] for i in [0..n_id.length[ do @@ -1488,6 +1517,7 @@ redef class AClosureDef end end v.variable_ctx = old_var_ctx + v.base_variable_ctx = old_base_var_ctx end end