This commit is contained in:
Jelle Luteijn 2022-05-15 11:19:49 +02:00
parent 16e76d6b31
commit 484dbfc9d9
529 changed files with 113694 additions and 0 deletions

View file

@ -0,0 +1,182 @@
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq.Expressions;
using AspClassic.Scripting.Utils;
namespace AspClassic.Scripting;
public sealed class ScopeStorage : IDynamicMetaObjectProvider
{
private class Meta : DynamicMetaObject
{
public new ScopeStorage Value => (ScopeStorage)base.Value;
public Meta(Expression parameter, ScopeStorage storage)
: base(parameter, BindingRestrictions.Empty, storage)
{
}
public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
{
return DynamicTryGetValue(binder.Name, binder.IgnoreCase, binder.FallbackGetMember(this).Expression, (Expression tmp) => tmp);
}
public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args)
{
return DynamicTryGetValue(binder.Name, binder.IgnoreCase, binder.FallbackInvokeMember(this, args).Expression, (Expression tmp) => binder.FallbackInvoke(new DynamicMetaObject(tmp, BindingRestrictions.Empty), args, null).Expression);
}
private DynamicMetaObject DynamicTryGetValue(string name, bool ignoreCase, Expression fallback, Func<Expression, Expression> resultOp)
{
IScopeVariable variable = Value.GetVariable(name, ignoreCase);
ParameterExpression parameterExpression = Expression.Parameter(typeof(object));
return new DynamicMetaObject(Expression.Block(new ParameterExpression[1] { parameterExpression }, Expression.Condition(Expression.Call(Variable(variable), variable.GetType().GetMethod("TryGetValue"), parameterExpression), ExpressionUtils.Convert(resultOp(parameterExpression), typeof(object)), ExpressionUtils.Convert(fallback, typeof(object)))), BindingRestrictions.GetInstanceRestriction(base.Expression, Value));
}
private static Expression Variable(IScopeVariable variable)
{
return Expression.Convert(Expression.Property(Expression.Constant(((IWeakReferencable)variable).WeakReference), typeof(WeakReference).GetProperty("Target")), variable.GetType());
}
public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value)
{
IScopeVariable variable = Value.GetVariable(binder.Name, binder.IgnoreCase);
Expression expression = ExpressionUtils.Convert(value.Expression, typeof(object));
return new DynamicMetaObject(Expression.Block(Expression.Call(Variable(variable), variable.GetType().GetMethod("SetValue"), expression), expression), BindingRestrictions.GetInstanceRestriction(base.Expression, Value));
}
public override DynamicMetaObject BindDeleteMember(DeleteMemberBinder binder)
{
IScopeVariable variable = Value.GetVariable(binder.Name, binder.IgnoreCase);
return new DynamicMetaObject(Expression.Condition(Expression.Call(Variable(variable), variable.GetType().GetMethod("DeleteValue")), Expression.Default(binder.ReturnType), binder.FallbackDeleteMember(this).Expression), BindingRestrictions.GetInstanceRestriction(base.Expression, Value));
}
public override IEnumerable<string> GetDynamicMemberNames()
{
return Value.GetMemberNames();
}
}
private readonly Dictionary<string, ScopeVariableIgnoreCase> _storage = new Dictionary<string, ScopeVariableIgnoreCase>(StringComparer.OrdinalIgnoreCase);
public dynamic this[string index]
{
get
{
return GetValue(index, ignoreCase: false);
}
set
{
SetValue(index, ignoreCase: false, (object)value);
}
}
public dynamic GetValue(string name, bool ignoreCase)
{
if (GetVariable(name, ignoreCase).TryGetValue(out var value))
{
return value;
}
throw new KeyNotFoundException("no value");
}
public bool TryGetValue(string name, bool ignoreCase, out dynamic value)
{
if (HasVariable(name) && GetVariable(name, ignoreCase).TryGetValue(out var value2))
{
value = value2;
return true;
}
value = null;
return false;
}
public void SetValue(string name, bool ignoreCase, object value)
{
GetVariable(name, ignoreCase).SetValue(value);
}
public bool DeleteValue(string name, bool ignoreCase)
{
if (!HasVariable(name))
{
return false;
}
return GetVariable(name, ignoreCase).DeleteValue();
}
public bool HasValue(string name, bool ignoreCase)
{
if (!HasVariable(name))
{
return false;
}
return GetVariable(name, ignoreCase).HasValue;
}
public IScopeVariable GetVariable(string name, bool ignoreCase)
{
if (ignoreCase)
{
return GetVariableIgnoreCase(name);
}
return GetVariable(name);
}
public ScopeVariable GetVariable(string name)
{
return GetVariableIgnoreCase(name).GetCaseSensitiveStorage(name);
}
public ScopeVariableIgnoreCase GetVariableIgnoreCase(string name)
{
lock (_storage)
{
if (!_storage.TryGetValue(name, out var value))
{
value = (_storage[name] = new ScopeVariableIgnoreCase(name));
}
return value;
}
}
public IList<string> GetMemberNames()
{
List<string> list = new List<string>();
lock (_storage)
{
foreach (ScopeVariableIgnoreCase value in _storage.Values)
{
value.AddNames(list);
}
return list;
}
}
public IList<KeyValuePair<string, object>> GetItems()
{
List<KeyValuePair<string, object>> list = new List<KeyValuePair<string, object>>();
lock (_storage)
{
foreach (ScopeVariableIgnoreCase value in _storage.Values)
{
value.AddItems(list);
}
return list;
}
}
private bool HasVariable(string name)
{
lock (_storage)
{
return _storage.ContainsKey(name);
}
}
public DynamicMetaObject GetMetaObject(Expression parameter)
{
return new Meta(parameter, this);
}
}