using System.Collections.Generic; using Upsilon.BaseTypes; using Upsilon.Binder; namespace Upsilon.Evaluator { public class EvaluationScope { private readonly EvaluationScope _parentScope; private EvaluationScope _getOnlyParentScope; public readonly Dictionary Variables; private readonly Dictionary _localVariables; internal EvaluationScope(EvaluationScope parentScope) { _parentScope = parentScope; Variables = new Dictionary(); _localVariables = new Dictionary(); } internal EvaluationScope(Dictionary vars) { Variables = vars; _localVariables = new Dictionary(); } internal static EvaluationScope CreateWithGetOnlyParent(EvaluationScope parent) { var scope = new EvaluationScope(new Dictionary()) {_getOnlyParentScope = parent}; return scope; } public void Set(VariableSymbol symbol, ScriptType obj, bool createNew) { if (symbol.Local && createNew) { if (_localVariables.ContainsKey(symbol.Name)) { _localVariables[symbol.Name] = obj; } else { _localVariables.Add(symbol.Name, obj); } } else { if (Variables.ContainsKey(symbol.Name)) { Variables[symbol.Name] = obj; } else if (_localVariables.ContainsKey(symbol.Name)) { _localVariables[symbol.Name] = obj; } else if (_parentScope != null && _parentScope.TryGet(symbol.Name, out _)) { _parentScope.Set(symbol, obj, false); } else { Variables.Add(symbol.Name, obj); } } } public void SetGlobal(VariableSymbol symbol, ScriptType obj) { if (_parentScope != null) _parentScope.SetGlobal(symbol, obj); else { Set(symbol, obj, true); } } public bool TryGet(VariableSymbol symbol, out ScriptType obj) { 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; if (_getOnlyParentScope != null) if (_getOnlyParentScope.TryGet(symbol, out obj)) return true; return false; } public bool TryGet(string variable, out ScriptType obj) { 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; if (_getOnlyParentScope != null) if (_getOnlyParentScope.TryGet(variable, out obj)) return true; return false; } } }