diff --git a/Upsilon/Binder/Binder.cs b/Upsilon/Binder/Binder.cs index bfe3ad4..19d1682 100644 --- a/Upsilon/Binder/Binder.cs +++ b/Upsilon/Binder/Binder.cs @@ -398,7 +398,8 @@ namespace Upsilon.Binder var valueType = Type.Unknown; var dictionary = new Dictionary(); var statements = ImmutableArray.CreateBuilder(); - Scope = new BoundScope(Scope); + var s = Scope; + Scope = BoundScope.WithReadOnlyScope(s); foreach (var expressionSyntax in e.Expressions) { var bound = BindStatement((StatementSyntax) expressionSyntax); @@ -409,7 +410,7 @@ namespace Upsilon.Binder { dictionary.Add(variable.Key, true); } - Scope = Scope.ParentScope; + Scope = s; return new BoundTableExpression(keyType, valueType, dictionary, statements); } diff --git a/Upsilon/Binder/BoundScope.cs b/Upsilon/Binder/BoundScope.cs index 3dc4185..ff2a081 100644 --- a/Upsilon/Binder/BoundScope.cs +++ b/Upsilon/Binder/BoundScope.cs @@ -1,32 +1,50 @@ -using System; using System.Collections.Generic; -using System.Linq; -using Upsilon.BaseTypes; namespace Upsilon.Binder { internal class BoundScope { public readonly BoundScope ParentScope; + private BoundScope _readOnlyScope; internal readonly Dictionary Variables; + internal readonly Dictionary LocalVariables; + public BoundScope(BoundScope parentScope) { ParentScope = parentScope; Variables = new Dictionary(); + LocalVariables = new Dictionary(); } public BoundScope(Dictionary variables, BoundScope parentScope) { ParentScope = parentScope; Variables = variables; + LocalVariables = new Dictionary(); + } + + public static BoundScope WithReadOnlyScope(BoundScope readOnlyScope) + { + var scope = new BoundScope(null) {_readOnlyScope = readOnlyScope}; + return scope; } public void SetVariable(VariableSymbol var) { - if (Variables.ContainsKey(var.Name)) - Variables[var.Name] = var; + if (var.Local) + { + if (LocalVariables.ContainsKey(var.Name)) + LocalVariables[var.Name] = var; + else + LocalVariables.Add(var.Name, var); + } else - Variables.Add(var.Name, var); + { + if (Variables.ContainsKey(var.Name)) + Variables[var.Name] = var; + else + Variables.Add(var.Name, var); + } } public void SetGlobalVariable(VariableSymbol var) @@ -44,6 +62,10 @@ namespace Upsilon.Binder public bool TryGetVariable(string key, bool allowUpperScopes, out VariableSymbol result) { + if (LocalVariables.TryGetValue(key, out result)) + { + return true; + } if (Variables.TryGetValue(key, out result)) { return true; @@ -52,6 +74,10 @@ namespace Upsilon.Binder { return ParentScope.TryGetVariable(key, true, out result); } + if (_readOnlyScope != null && allowUpperScopes) + { + return _readOnlyScope.TryGetVariable(key, true, out result); + } return false; } diff --git a/Upsilon/Evaluator/EvaluationScope.cs b/Upsilon/Evaluator/EvaluationScope.cs index 7cab80e..adec341 100644 --- a/Upsilon/Evaluator/EvaluationScope.cs +++ b/Upsilon/Evaluator/EvaluationScope.cs @@ -71,10 +71,10 @@ namespace Upsilon.Evaluator public bool TryGet(VariableSymbol symbol, out LuaType obj) { - if (Variables.TryGetValue(symbol.Name, out obj)) - return true; if (LocalVariables.TryGetValue(symbol.Name, out obj)) return true; + if (Variables.TryGetValue(symbol.Name, out obj)) + return true; if (_parentScope != null) if (_parentScope.TryGet(symbol, out obj)) return true; @@ -86,10 +86,10 @@ namespace Upsilon.Evaluator public bool TryGet(string variable, out LuaType obj) { - if (Variables.TryGetValue(variable, out obj)) - return true; if (LocalVariables.TryGetValue(variable, out obj)) return true; + if (Variables.TryGetValue(variable, out obj)) + return true; if (_parentScope != null) if (_parentScope.TryGet(variable, out obj)) return true;