Upsilon/Upsilon/Evaluator/EvaluationScope.cs

102 lines
2.9 KiB
C#

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<string, ScriptType> Variables;
internal EvaluationScope(EvaluationScope parentScope)
{
ParentScope = parentScope;
Variables = new Dictionary<string, ScriptType>();
}
internal EvaluationScope(Dictionary<string, ScriptType> vars)
{
Variables = vars;
}
internal static EvaluationScope CreateWithGetOnlyParent(EvaluationScope parent)
{
var scope = new EvaluationScope(new Dictionary<string, ScriptType>()) {_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;
}
}
}