progress
This commit is contained in:
parent
16e76d6b31
commit
484dbfc9d9
529 changed files with 113694 additions and 0 deletions
183
AspClassic.VBScript/Binders/VBScriptBinaryOperationBinder.cs
Normal file
183
AspClassic.VBScript/Binders/VBScriptBinaryOperationBinder.cs
Normal file
|
@ -0,0 +1,183 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
//using System.Text;
|
||||
using System.Reflection;
|
||||
using System.Dynamic;
|
||||
#if USE35
|
||||
using AspClassic.Scripting.Ast;
|
||||
#else
|
||||
using System.Linq.Expressions;
|
||||
#endif
|
||||
using Debug = System.Diagnostics.Debug;
|
||||
using Dlrsoft.VBScript.Runtime;
|
||||
|
||||
namespace Dlrsoft.VBScript.Binders
|
||||
{
|
||||
public class VBScriptBinaryOperationBinder : BinaryOperationBinder
|
||||
{
|
||||
public VBScriptBinaryOperationBinder(ExpressionType operation)
|
||||
: base(operation)
|
||||
{
|
||||
}
|
||||
|
||||
public override DynamicMetaObject FallbackBinaryOperation(
|
||||
DynamicMetaObject target, DynamicMetaObject arg,
|
||||
DynamicMetaObject errorSuggestion)
|
||||
{
|
||||
// Defer if any object has no value so that we evaulate their
|
||||
// Expressions and nest a CallSite for the InvokeMember.
|
||||
if (!target.HasValue || !arg.HasValue)
|
||||
{
|
||||
return Defer(target, arg);
|
||||
}
|
||||
var restrictions = target.Restrictions.Merge(arg.Restrictions);
|
||||
|
||||
if (target.Value == null)
|
||||
{
|
||||
restrictions = restrictions.Merge(
|
||||
BindingRestrictions.GetInstanceRestriction(target.Expression, null)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
restrictions = restrictions.Merge(BindingRestrictions.GetTypeRestriction(
|
||||
target.Expression, target.LimitType));
|
||||
}
|
||||
|
||||
if (arg.Value == null)
|
||||
{
|
||||
restrictions = restrictions.Merge(BindingRestrictions.GetInstanceRestriction(
|
||||
arg.Expression, null));
|
||||
}
|
||||
else
|
||||
{
|
||||
restrictions = restrictions.Merge(BindingRestrictions.GetTypeRestriction(
|
||||
arg.Expression, arg.LimitType));
|
||||
}
|
||||
|
||||
if (this.Operation == ExpressionType.Add)
|
||||
{
|
||||
if (target.LimitType == typeof(string) && arg.LimitType == typeof(string))
|
||||
{
|
||||
return new DynamicMetaObject(
|
||||
RuntimeHelpers.EnsureObjectResult(Expression.Call(
|
||||
typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string) }),
|
||||
Expression.Convert(target.Expression, target.LimitType),
|
||||
Expression.Convert(arg.Expression, arg.LimitType))),
|
||||
restrictions
|
||||
);
|
||||
}
|
||||
if (target.LimitType == typeof(DateTime))
|
||||
{
|
||||
return new DynamicMetaObject(
|
||||
RuntimeHelpers.EnsureObjectResult( Expression.Call(
|
||||
typeof(BuiltInFunctions).GetMethod("DateAdd"),
|
||||
Expression.Constant("d"),
|
||||
Expression.Convert(arg.Expression, typeof(object)),
|
||||
target.Expression)),
|
||||
restrictions
|
||||
);
|
||||
}
|
||||
else if (arg.LimitType == typeof(DateTime))
|
||||
{
|
||||
return new DynamicMetaObject(
|
||||
Expression.Call(
|
||||
typeof(BuiltInFunctions).GetMethod("DateAdd"),
|
||||
Expression.Constant("d"),
|
||||
Expression.Convert(target.Expression, typeof(object)),
|
||||
arg.Expression),
|
||||
restrictions
|
||||
);
|
||||
}
|
||||
else if (!target.LimitType.IsPrimitive || !arg.LimitType.IsPrimitive)
|
||||
{
|
||||
DynamicMetaObject[] args = new DynamicMetaObject[] { target, arg };
|
||||
List<MethodInfo> res = RuntimeHelpers.GetExtensionMethods("op_Addition", target, args);
|
||||
if (res.Count > 0)
|
||||
{
|
||||
MethodInfo mi = null;
|
||||
if (res.Count > 1)
|
||||
{
|
||||
//If more than one results found, attempt overload resolution
|
||||
mi = RuntimeHelpers.ResolveOverload(res, args);
|
||||
}
|
||||
else
|
||||
{
|
||||
mi = res[0];
|
||||
}
|
||||
|
||||
// restrictions and conversion must be done consistently.
|
||||
var callArgs = RuntimeHelpers.ConvertArguments(args, mi.GetParameters());
|
||||
|
||||
return new DynamicMetaObject(
|
||||
RuntimeHelpers.EnsureObjectResult(
|
||||
Expression.Call(null, mi, callArgs)
|
||||
),
|
||||
restrictions
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (target.LimitType.IsPrimitive && arg.LimitType.IsPrimitive)
|
||||
{
|
||||
Type targetType;
|
||||
Expression first;
|
||||
Expression second;
|
||||
if (target.LimitType == arg.LimitType || target.LimitType.IsAssignableFrom(arg.LimitType))
|
||||
{
|
||||
targetType = target.LimitType;
|
||||
first = Expression.Convert(target.Expression, targetType);
|
||||
//if variable is object type, need to convert twice (unbox + convert)
|
||||
second = Expression.Convert(
|
||||
Expression.Convert(arg.Expression, arg.LimitType),
|
||||
targetType
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
targetType = arg.LimitType;
|
||||
first = Expression.Convert(
|
||||
Expression.Convert(target.Expression, target.LimitType),
|
||||
targetType
|
||||
);
|
||||
second = Expression.Convert(arg.Expression, targetType);
|
||||
}
|
||||
|
||||
return new DynamicMetaObject(
|
||||
RuntimeHelpers.EnsureObjectResult(
|
||||
Expression.MakeBinary(
|
||||
this.Operation,
|
||||
first,
|
||||
second
|
||||
)
|
||||
),
|
||||
restrictions
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
DynamicMetaObject[] args = null;
|
||||
MethodInfo mi = null;
|
||||
|
||||
mi = typeof(HelperFunctions).GetMethod("BinaryOp");
|
||||
Expression op = Expression.Constant(this.Operation);
|
||||
DynamicMetaObject mop = new DynamicMetaObject(Expression.Constant(this.Operation), BindingRestrictions.Empty, this.Operation);
|
||||
|
||||
args = new DynamicMetaObject[] { mop, target, arg };
|
||||
// restrictions and conversion must be done consistently.
|
||||
var callArgs = RuntimeHelpers.ConvertArguments(args, mi.GetParameters());
|
||||
|
||||
return new DynamicMetaObject(
|
||||
RuntimeHelpers.EnsureObjectResult(
|
||||
Expression.Call(
|
||||
mi,
|
||||
callArgs
|
||||
)
|
||||
),
|
||||
restrictions
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue