KumiScript/interpreter/Environment.cs
2024-01-25 23:37:51 -06:00

83 lines
No EOL
2.2 KiB
C#

using System.Diagnostics.CodeAnalysis;
namespace KumiScript.Interpreter
{
public class Environment
{
readonly Environment? _outer;
readonly Dictionary<Symbol, Expression> _bindings;
public Environment()
{
_bindings = new Dictionary<Symbol, Expression>(SymbolComparer.GetInstance());
}
public Environment(Environment outer)
{
_bindings = new Dictionary<Symbol, Expression>(SymbolComparer.GetInstance());
_outer = outer;
}
public Expression Lookup(Symbol symbol)
{
Expression? result;
_bindings.TryGetValue(symbol, out result);
if (result is not null)
return result;
if (_outer is null)
throw new InterpreterUnboundSymbolException();
return _outer.Lookup(symbol);
}
public void AddSymbol(Symbol symbol, Expression value)
{
_bindings.Add(symbol, value);
return;
}
public void RedefineSymbol(Symbol symbol, Expression value)
{
if (_bindings.ContainsKey(symbol))
{
_bindings.Remove(symbol);
_bindings.Add(symbol, value);
return;
}
if (_outer is null)
throw new InterpreterUnboundSymbolException(symbol.ToString());
_outer.RedefineSymbol(symbol, value);
}
}
internal class SymbolComparer : IEqualityComparer<Symbol>
{
private static SymbolComparer? _instance;
private SymbolComparer()
{
}
public static SymbolComparer GetInstance()
{
if (_instance is null)
_instance = new SymbolComparer();
return _instance;
}
public bool Equals(Symbol? x, Symbol? y)
{
if (x is not Symbol || y is not Symbol)
return false;
return x.Equals(y);
}
public int GetHashCode([DisallowNull] Symbol obj)
{
return obj.ToString().GetHashCode();
}
}
}