using System; using System.Collections.Generic; using Upsilon.BaseTypes; using Upsilon.Binder; using Upsilon.Binder.VariableSymbols; namespace Upsilon.Evaluator { public class EvaluationScope : IDisposable { public EvaluationScope ParentScope { get; private set; } private EvaluationScope _getOnlyParentScope; public readonly Dictionary Variables; internal EvaluationScope(EvaluationScope parentScope) { ParentScope = parentScope; Variables = new Dictionary(); } internal EvaluationScope(Dictionary vars) { Variables = vars; } internal static EvaluationScope CreateWithGetOnlyParent(EvaluationScope parent) { var scope = new EvaluationScope(new Dictionary()) {_getOnlyParentScope = parent}; return scope; } public void Dispose() { ParentScope?.Dispose(); ParentScope = null; Variables.Clear(); } public void AssignToNearest(VariableSymbol symbol, ScriptType value) { lock (Variables) { if (Variables.ContainsKey(symbol.Name)) { Variables[symbol.Name] = value; } else if (ParentScope != null) { ParentScope.AssignToNearest(symbol, value); } else { Variables.Add(symbol.Name, value); } } } public void CreateLocal(VariableSymbol symbol, ScriptType value) { Variables[symbol.Name] = value; } public void Delete(VariableSymbol symbol) { Variables.Remove(symbol.Name); } public void Delete(string name) { Variables.Remove(name); } public bool TryGet(VariableSymbol symbol, out ScriptType obj) { if (Variables.TryGetValue(symbol.Name, out obj)) return true; if (ParentScope != null) if (ParentScope.TryGet(symbol, out obj)) return true; if (_getOnlyParentScope != null) if (_getOnlyParentScope.TryGet(symbol, out obj)) return true; return false; } public bool TryGet(string variable, out ScriptType obj) { if (Variables.TryGetValue(variable, out obj)) return true; if (ParentScope != null) if (ParentScope.TryGet(variable, out obj)) return true; if (_getOnlyParentScope != null) if (_getOnlyParentScope.TryGet(variable, out obj)) return true; return false; } } }