From 1177a6fcadc48d265cea7d94438675de70ef5993 Mon Sep 17 00:00:00 2001 From: Jean Privat Date: Fri, 19 Jun 2009 02:03:54 -0400 Subject: [PATCH] syntax: Move VariableContext and related to a new control_flow.nit Signed-off-by: Jean Privat --- src/syntax/control_flow.nit | 218 +++++++++++++++++++++++++++++++++++++++++++ src/syntax/typing.nit | 199 +-------------------------------------- 2 files changed, 219 insertions(+), 198 deletions(-) create mode 100644 src/syntax/control_flow.nit diff --git a/src/syntax/control_flow.nit b/src/syntax/control_flow.nit new file mode 100644 index 0000000..ceadd4e --- /dev/null +++ b/src/syntax/control_flow.nit @@ -0,0 +1,218 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Copyright 2008-2009 Jean Privat +# +# 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. + +# Analysis control flow and variable visibility in property bodies, statements and expressions +package control_flow + +import syntax_base + +# Associate symbols to variable and variables to type +# Can be nested +abstract class VariableContext + # Look for the variable from its name + # Return null if nothing found + meth [](s: Symbol): Variable + do + if _dico.has_key(s) then + return _dico[s] + else + return null + end + end + + # Register a new variable with its name + meth add(v: Variable) + do + _dico[v.name] = v + _all_variables.add(v) + end + + meth mark_is_set(v: Variable) + do + _set_variables.add(v) + end + + meth check_is_set(n: PNode, v: Variable) + do + if v.must_be_set and not is_set(v) then + _visitor.error(n, "Error: variable '{v}' is possibly unset.") + var x = self + while true do + print " {x.node.locate}: {x._set_variables.join(", ")} ; {x._dico.join(", ")}" + var x0 = x + if x0 isa SubVariableContext then + x = x0.prev + else + break + end + end + end + end + + # The effective static type of a given variable + # May be different from the declaration static type + meth stype(v: Variable): MMType + do + return v.stype + end + + # Variables by name (in the current context only) + attr _dico: Map[Symbol, Variable] + + # All variables in all contextes + attr _all_variables: Set[Variable] + + # Build a new VariableContext + meth sub(node: PNode): SubVariableContext + do + return new SubVariableContext.with_prev(self, node) + end + + # Build a nested VariableContext with new variable information + meth sub_with(node: PNode, v: Variable, t: MMType): SubVariableContext + do + return new CastVariableContext.with_prev(self, node, v, t) + end + + # The visitor of the context (used to display error) + attr _visitor: AbsSyntaxVisitor + + # The syntax node that introduced the context + readable attr _node: PNode + + init(visitor: AbsSyntaxVisitor, node: PNode) + do + _visitor = visitor + _node = node + _dico = new HashMap[Symbol, Variable] + end + + # Is a control flow break met? (return, break, continue) + 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 = false + + # Set of variable that are set (assigned) + readable attr _set_variables: HashSet[Variable] = new HashSet[Variable] + + # Is a variable set? + meth is_set(v: Variable): Bool + do + return _set_variables.has(v) + end + + # Merge back one flow context information + meth merge(ctx: VariableContext) + do + if ctx.unreash then + unreash = true + if ctx.already_unreash then already_unreash = true + return + end + for v in _all_variables do + if not is_set(v) and ctx.is_set(v) then + mark_is_set(v) + end + end + end + + # Merge back two alternative flow context informations + meth merge2(ctx1, ctx2: VariableContext) + do + if ctx1.unreash then + merge(ctx2) + else if ctx2.unreash then + merge(ctx1) + end + for v in _all_variables do + if not is_set(v) and ctx1.is_set(v) and ctx2.is_set(v) then + mark_is_set(v) + end + end + end +end + +class RootVariableContext +special VariableContext + init(visitor: AbsSyntaxVisitor, node: PNode) + do + super(visitor, node) + _all_variables = new HashSet[Variable] + end +end + +class SubVariableContext +special VariableContext + readable attr _prev: VariableContext + + redef meth [](s) + do + if _dico.has_key(s) then + return _dico[s] + else + return prev[s] + end + end + + redef meth stype(v) + do + return prev.stype(v) + end + + init with_prev(p: VariableContext, node: PNode) + do + init(p._visitor, node) + _prev = p + _all_variables = p._all_variables + end + + redef meth is_set(v) + do + return _set_variables.has(v) or _prev.is_set(v) + end +end + +class CastVariableContext +special SubVariableContext + attr _variable: Variable + attr _var_type: MMType + + redef meth stype(v) + do + if _variable == v then + return _var_type + end + return prev.stype(v) + end + + init with_prev(p: VariableContext, node: PNode, v: Variable, t: MMType) + do + super(p, node) + _variable = v + _var_type =t + 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 diff --git a/src/syntax/typing.nit b/src/syntax/typing.nit index ee2eb0a..721c76b 100644 --- a/src/syntax/typing.nit +++ b/src/syntax/typing.nit @@ -19,6 +19,7 @@ package typing import syntax_base import escape +import control_flow redef class MMSrcModule # Walk trough the module and type statments and expressions @@ -124,204 +125,6 @@ special AbsSyntaxVisitor end end -# Associate symbols to variable and variables to type -# Can be nested -abstract class VariableContext - # Look for the variable from its name - # Return null if nothing found - meth [](s: Symbol): Variable - do - if _dico.has_key(s) then - return _dico[s] - else - return null - end - end - - # Register a new variable with its name - meth add(v: Variable) - do - _dico[v.name] = v - _all_variables.add(v) - end - - meth mark_is_set(v: Variable) - do - _set_variables.add(v) - end - - meth check_is_set(n: PNode, v: Variable) - do - if v.must_be_set and not is_set(v) then - _visitor.error(n, "Error: variable '{v}' is possibly unset.") - var x = self - while true do - print " {x.node.locate}: {x._set_variables.join(", ")} ; {x._dico.join(", ")}" - var x0 = x - if x0 isa SubVariableContext then - x = x0.prev - else - break - end - end - end - end - - # The effective static type of a given variable - # May be different from the declaration static type - meth stype(v: Variable): MMType - do - return v.stype - end - - # Variables by name (in the current context only) - attr _dico: Map[Symbol, Variable] - - # All variables in all contextes - attr _all_variables: Set[Variable] - - # Build a new VariableContext - meth sub(node: PNode): SubVariableContext - do - return new SubVariableContext.with_prev(self, node) - end - - # Build a nested VariableContext with new variable information - meth sub_with(node: PNode, v: Variable, t: MMType): SubVariableContext - do - return new CastVariableContext.with_prev(self, node, v, t) - end - - # The visitor of the context (used to display error) - attr _visitor: AbsSyntaxVisitor - - # The syntax node that introduced the context - readable attr _node: PNode - - init(visitor: AbsSyntaxVisitor, node: PNode) - do - _visitor = visitor - _node = node - _dico = new HashMap[Symbol, Variable] - end - - # Is a control flow break met? (return, break, continue) - 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 = false - - # Set of variable that are set (assigned) - readable attr _set_variables: HashSet[Variable] = new HashSet[Variable] - - # Is a variable set? - meth is_set(v: Variable): Bool - do - return _set_variables.has(v) - end - - # Merge back one flow context information - meth merge(ctx: VariableContext) - do - if ctx.unreash then - unreash = true - if ctx.already_unreash then already_unreash = true - return - end - for v in _all_variables do - if not is_set(v) and ctx.is_set(v) then - mark_is_set(v) - end - end - end - - # Merge back two alternative flow context informations - meth merge2(ctx1, ctx2: VariableContext) - do - if ctx1.unreash then - merge(ctx2) - else if ctx2.unreash then - merge(ctx1) - end - for v in _all_variables do - if not is_set(v) and ctx1.is_set(v) and ctx2.is_set(v) then - mark_is_set(v) - end - end - end -end - -class RootVariableContext -special VariableContext - init(visitor: AbsSyntaxVisitor, node: PNode) - do - super(visitor, node) - _all_variables = new HashSet[Variable] - end -end - -class SubVariableContext -special VariableContext - readable attr _prev: VariableContext - - redef meth [](s) - do - if _dico.has_key(s) then - return _dico[s] - else - return prev[s] - end - end - - redef meth stype(v) - do - return prev.stype(v) - end - - init with_prev(p: VariableContext, node: PNode) - do - init(p._visitor, node) - _prev = p - _all_variables = p._all_variables - end - - redef meth is_set(v) - do - return _set_variables.has(v) or _prev.is_set(v) - end -end - -class CastVariableContext -special SubVariableContext - attr _variable: Variable - attr _var_type: MMType - - redef meth stype(v) - do - if _variable == v then - return _var_type - end - return prev.stype(v) - end - - init with_prev(p: VariableContext, node: PNode, v: Variable, t: MMType) - do - super(p, node) - _variable = v - _var_type =t - 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 - ############################################################################### -- 1.7.9.5