void ISpecialParamHolder.Process(CallSiteContext info, Expression valueExpr) { Debug.Assert(Value != null); info.AddRestriction(BindingRestrictions.GetInstanceRestriction(valueExpr, Value)); // {arg} != null && {arg} == Value info.TargetType = Value; }
protected override MethodBase[] ResolveMethods(CallSiteContext bound) { // check bound.TargetType is assignable from bound.TargetInstance if (bound.TargetType == null || bound.CurrentTargetInstance == null || bound.TargetType.Type.IsAssignableFrom(bound.CurrentTargetInstance.GetType()) == false) { // target instance cannot be used bound.TargetInstance = null; } // if (bound.Name != null) { // candidates: IEnumerable <MethodBase> candidates = bound.TargetType .SelectRuntimeMethods(bound.Name, bound.ClassContext) .SelectVisible(bound.ClassContext); if (bound.TargetInstance == null) { candidates = candidates.SelectStatic(); } // return(candidates.Construct(bound.TypeArguments).ToArray()); } else { throw new ArgumentException(); } }
protected override Expression BindMissingMethod(CallSiteContext bound) { if (bound.TargetType == null) // already reported - class cannot be found { return(ConvertExpression.BindDefault(this.ReturnType)); } var call = BinderHelpers.FindMagicMethod(bound.TargetType, (bound.TargetInstance == null) ? TypeMethods.MagicMethods.__callstatic : TypeMethods.MagicMethods.__call); if (call != null) { var name_expr = (_name != null) ? Expression.Constant(_name) : bound.IndirectName; // T.__callStatic(name, array) var call_args = new Expression[] { name_expr, BinderHelpers.NewPhpArray(bound.Arguments), }; return(OverloadBinder.BindOverloadCall(_returnType, bound.TargetInstance, call.Methods, bound.Context, call_args, true, lateStaticType: bound.TargetType)); } // return(base.BindMissingMethod(bound)); }
protected virtual Expression BindMissingMethod(CallSiteContext bound) { string nameText = bound.Name ?? "???"; // TODO: ErrCode method not found throw new ArgumentException(string.Format("Function '{0}' not found!", nameText)); }
protected override Expression BindMissingMethod(CallSiteContext bound) { var name_expr = (_name != null) ? Expression.Constant(_name) : bound.IndirectName; // resolve target expression: var isobject = bound.TargetType != null; if (isobject == false) { /* Template: * PhpException.MethodOnNonObject(name_expr); // aka PhpException.Throw(Error, method_called_on_non_object, name_expr) * return NULL; */ var throwcall = Expression.Call(typeof(PhpException), "MethodOnNonObject", Array.Empty <Type>(), ConvertExpression.Bind(name_expr, typeof(string), bound.Context)); return(Expression.Block(throwcall, ConvertExpression.BindDefault(this.ReturnType))); } var call = BinderHelpers.FindMagicMethod(bound.TargetType, TypeMethods.MagicMethods.__call); if (call != null) { // target.__call(name, array) var call_args = new Expression[] { name_expr, BinderHelpers.NewPhpArray(bound.Arguments), }; return(OverloadBinder.BindOverloadCall(_returnType, bound.TargetInstance, call.Methods, bound.Context, call_args, false)); } return(base.BindMissingMethod(bound)); }
protected virtual Expression BindMissingMethod(CallSiteContext bound) { /* Template: * PhpException.UndefinedFunctionCalled(name); // aka PhpException.Throw(Error, undefined_function_called, name) * return NULL; */ var throwcall = Expression.Call(typeof(PhpException), "UndefinedFunctionCalled", Array.Empty <Type>(), bound.IndirectName ?? Expression.Constant(bound.Name)); return(Expression.Block(throwcall, ConvertExpression.BindDefault(this.ReturnType))); }
public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) { bool hasTargetInstance = (target.LimitType != typeof(TargetTypeParam)); var bound = new CallSiteContext(!hasTargetInstance) { ClassContext = _classContext, Name = _name } .ProcessArgs(target, args, hasTargetInstance); if (hasTargetInstance) { var isobject = bound.TargetType != null; if (isobject == false) { var defaultexpr = ConvertExpression.BindDefault(_returnType); if (!_access.Quiet()) { // PhpException.VariableMisusedAsObject(target, _access.ReadRef) var throwcall = BinderHelpers.VariableMisusedAsObject(target.Expression, _access.EnsureAlias()); defaultexpr = Expression.Block(throwcall, defaultexpr); } return(new DynamicMetaObject(defaultexpr, bound.Restrictions)); } // instance := (T)instance bound.TargetInstance = Expression.Convert(bound.TargetInstance, bound.TargetType.Type); } Debug.Assert(IsClassConst ? (bound.TargetInstance == null) : true); // var getter = IsClassConst ? BinderHelpers.BindClassConstant(bound.TargetType, bound.ClassContext, bound.Name, bound.Context) : BinderHelpers.BindField(bound.TargetType, bound.ClassContext, bound.TargetInstance, bound.Name, bound.Context, _access, null); if (getter != null) { // return(new DynamicMetaObject(ConvertExpression.Bind(getter, _returnType, bound.Context), bound.Restrictions)); } if (IsClassConst) { // error: constant not defined // ... } // unreachable: property not found throw new InvalidOperationException($"{bound.TargetType.Name}::{bound.Name} could not be resolved."); }
protected override MethodBase[] ResolveMethods(CallSiteContext bound) { if (_name != null) { return(ResolveMethods(bound, _name, _nameOpt)); } else { throw new NotImplementedException(); } }
protected virtual Expression BindMissingMethod(CallSiteContext bound) { /* Template: * PhpException.UndefinedFunctionCalled(name); * return NULL; */ var throwcall = bound.TargetType != null ? Expression.Call(typeof(PhpException), "UndefinedMethodCalled", Array.Empty <Type>(), Expression.Constant(bound.TargetType.Name), bound.IndirectName ?? Expression.Constant(bound.Name)) : Expression.Call(typeof(PhpException), "UndefinedFunctionCalled", Array.Empty <Type>(), bound.IndirectName ?? Expression.Constant(bound.Name)); return(Expression.Block(throwcall, ConvertExpression.BindDefault(this.ReturnType))); }
public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) { bool hasTargetInstance = (target.LimitType != typeof(TargetTypeParam)); var bound = new CallSiteContext() { ClassContext = _classContext, Name = _name } .ProcessArgs(target, args, hasTargetInstance); if (hasTargetInstance) { var isobject = bound.TargetType != null; if (isobject == false) { var defaultexpr = ConvertExpression.BindDefault(_returnType); if (!_access.Quiet()) { // PhpException.VariableMisusedAsObject(target, _access.ReadRef) var throwcall = Expression.Call(typeof(PhpException), "VariableMisusedAsObject", Array.Empty <Type>(), ConvertExpression.BindToValue(target.Expression), Expression.Constant(_access.EnsureAlias())); defaultexpr = Expression.Block(throwcall, defaultexpr); } return(new DynamicMetaObject(defaultexpr, bound.Restrictions)); } // instance := (T)instance bound.TargetInstance = Expression.Convert(bound.TargetInstance, bound.TargetType.Type.AsType()); } Debug.Assert(IsClassConst ? (bound.TargetInstance == null) : true); // var getter = IsClassConst ? BinderHelpers.BindClassConstant(bound.TargetType, bound.ClassContext, bound.Name, bound.Context) : BinderHelpers.BindField(bound.TargetType, bound.ClassContext, bound.TargetInstance, bound.Name, bound.Context, _access, null); if (getter != null) { // return(new DynamicMetaObject(ConvertExpression.Bind(getter, _returnType, bound.Context), bound.Restrictions)); } // field not found throw new NotImplementedException(); }
protected override Expression BindMissingMethod(CallSiteContext bound) { var type = bound.TargetType; if (type == null) // already reported - class cannot be found { return(ConvertExpression.BindDefault(this.ReturnType)); } if (bound.TargetInstance != null && bound.CurrentTargetInstance != null) // it has been checked it is a subclass of TargetType { // ensure current scope's __call() is favoured over the specified class type = bound.CurrentTargetInstance.GetPhpTypeInfo(); } var call = BinderHelpers.FindMagicMethod(type, (bound.TargetInstance == null) ? TypeMethods.MagicMethods.__callstatic : TypeMethods.MagicMethods.__call); if (call != null) { Expression[] call_args; var name_expr = (_name != null) ? Expression.Constant(_name) : bound.IndirectName; if (call.Methods.All(IsClrMagicCallWithParams)) { // Template: target.__call(name, arg1, arg2, ...) // flatterns the arguments: call_args = ArrayUtils.AppendRange(name_expr, bound.Arguments); } else { // Template: target.__call(name, array) // regular PHP behavior: call_args = new Expression[] { name_expr, BinderHelpers.NewPhpArray(bound.Arguments, bound.Context, bound.ClassContext), }; } return(OverloadBinder.BindOverloadCall(_returnType, bound.TargetInstance, call.Methods, bound.Context, call_args, isStaticCallSyntax: true, lateStaticType: bound.TargetType, classContext: bound.ClassContext)); } // return(base.BindMissingMethod(bound)); }
protected override MethodBase[] ResolveMethods(CallSiteContext bound) { // resolve target expression: var isobject = bound.TargetType != null; if (isobject == false) { return(null); // no methods } // candidates: return(bound.TargetType .SelectRuntimeMethods(bound.Name) .SelectVisible(bound.ClassContext) .ToArray()); }
void ISpecialParamHolder.Process(CallSiteContext info, Expression valueExpr) { if (valueExpr.Type != typeof(string)) { throw new InvalidOperationException(); } var name = (string)(object)Value; info.IndirectName = valueExpr; info.AddRestriction(Expression.Equal(valueExpr, Expression.Constant(name))); if (info.Name == null) { info.Name = name; } }
protected override Expression BindMissingMethod(CallSiteContext bound) { var name_expr = (_name != null) ? Expression.Constant(_name) : bound.IndirectName; // resolve target expression: var isobject = bound.TargetType != null; if (isobject == false) { /* Template: * PhpException.MethodOnNonObject(name_expr); * return NULL; */ var throwcall = Expression.Call(typeof(PhpException), "MethodOnNonObject", Array.Empty <Type>(), ConvertExpression.Bind(name_expr, typeof(string), bound.Context)); return(Expression.Block(throwcall, ConvertExpression.BindDefault(this.ReturnType))); } var call = BinderHelpers.FindMagicMethod(bound.TargetType, TypeMethods.MagicMethods.__call); if (call != null) { Expression[] call_args; if (call.Methods.All(IsClrMagicCallWithParams)) { // Template: target.__call(name, arg1, arg2, ...) // flatterns the arguments: call_args = ArrayUtils.AppendRange(name_expr, bound.Arguments); } else { // Template: target.__call(name, array) // regular PHP behavior: call_args = new Expression[] { name_expr, BinderHelpers.NewPhpArray(bound.Arguments, bound.Context, bound.ClassContext), }; } return(OverloadBinder.BindOverloadCall(_returnType, bound.TargetInstance, call.Methods, bound.Context, call_args, false)); } return(base.BindMissingMethod(bound)); }
MethodBase[] ResolveMethods(CallSiteContext bound, string name, string nameOpt) { var routine = bound.CurrentContext.GetDeclaredFunction(name) ?? ((nameOpt != null) ? bound.CurrentContext.GetDeclaredFunction(nameOpt) : null); if (routine == null) { return(null); } if (routine is PhpRoutineInfo || routine is DelegateRoutineInfo) { Debug.Assert(routine.Index != 0); // restriction: ctx.CheckFunctionDeclared(index, routine.GetHashCode()) var checkExpr = Expression.Call( bound.Context, typeof(Context).GetMethod("CheckFunctionDeclared", typeof(int), typeof(int)), Expression.Constant(routine.Index), Expression.Constant(routine.GetHashCode())); bound.AddRestriction(checkExpr); } else if (routine is ClrRoutineInfo) { // CLR routines persist across whole app, no restriction needed } // var targetInstance = routine.Target; if (targetInstance != null) { bound.TargetInstance = Expression.Constant(targetInstance); } if (bound.TypeArguments != null && bound.TypeArguments.Length != 0) { // global functions cannot be (should not be) generic! throw new InvalidOperationException(); // NS } // return(routine.Methods); }
public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) { bool hasTargetInstance = (target.LimitType != typeof(TargetTypeParam)); var bound = new CallSiteContext(!hasTargetInstance) { ClassContext = _classContext, Name = _name, } .ProcessArgs(target, args, hasTargetInstance); // if (hasTargetInstance) { var isobject = bound.TargetType != null; if (isobject == false) { // VariableMisusedAsObject return(new DynamicMetaObject( BinderHelpers.VariableMisusedAsObject(target.Expression, false), bound.Restrictions)); } // instance := (T)instance bound.TargetInstance = Expression.Convert(bound.TargetInstance, bound.TargetType.Type.AsType()); } // var setter = BinderHelpers.BindField(bound.TargetType, bound.ClassContext, bound.TargetInstance, bound.Name, bound.Context, _access, bound.Arguments.FirstOrDefault()); if (setter != null) { // return(new DynamicMetaObject(setter, bound.Restrictions)); } // field not found throw new NotImplementedException(); }
void ISpecialParamHolder.Process(CallSiteContext info, Expression valueExpr) { info.Context = valueExpr; }
void ISpecialParamHolder.Process(CallSiteContext info, Expression valueExpr) { throw new InvalidOperationException(); }
void ISpecialParamHolder.Process(CallSiteContext info, Expression valueExpr) { info.AddRestriction(Expression.Call(valueExpr, Cache.Operators.RuntimeTypeHandle_Equals_RuntimeTypeHandle, Expression.Constant(Value))); info.ClassContext = Type.GetTypeFromHandle(Value); }
void ISpecialParamHolder.Process(CallSiteContext info, Expression valueExpr) { throw new NotImplementedException(); }
MethodBase[] ResolveMethods(CallSiteContext bound, string name, string nameOpt) { var routine = bound.CurrentContext.GetDeclaredFunction(name) ?? ((nameOpt != null) ? bound.CurrentContext.GetDeclaredFunction(nameOpt) : null); if (routine == null) { // add restriction // https://github.com/iolevel/wpdotnet-sdk/issues/92 // restriction: ctx.GetDeclaredFunction(name) == null var checkExpr = Expression.ReferenceEqual( Expression.Call(bound.Context, Cache.Operators.GetDeclaredFunction_Context_String, Expression.Constant(name)), Cache.Expressions.Null); bound.AddRestriction(checkExpr); if (nameOpt != null) { // restriction: ctx.GetDeclaredFunction(nameOpt) == null checkExpr = Expression.ReferenceEqual( Expression.Call(bound.Context, Cache.Operators.GetDeclaredFunction_Context_String, Expression.Constant(nameOpt)), Cache.Expressions.Null); bound.AddRestriction(checkExpr); } return(null); } if (routine is PhpRoutineInfo || routine is DelegateRoutineInfo) { Debug.Assert(routine.Index != 0); // restriction: CheckFunctionDeclared(ctx, index, routine.GetHashCode()) var checkExpr = Expression.Call( Cache.Operators.CheckFunctionDeclared_Context_Int_Int, bound.Context, Expression.Constant(routine.Index), Expression.Constant(routine.GetHashCode())); bound.AddRestriction(checkExpr); } else if (routine is ClrRoutineInfo) { // CLR routines persist across whole app, no restriction needed } // var targetInstance = routine.Target; if (targetInstance != null) { bound.TargetInstance = Expression.Constant(targetInstance); } if (bound.TypeArguments != null && bound.TypeArguments.Length != 0) { // global functions cannot be (should not be) generic! throw new InvalidOperationException(); // NS } // return(routine.Methods); }
void ISpecialParamHolder.Process(CallSiteContext info, Expression valueExpr) { info.AddRestriction(BindingRestrictions.GetInstanceRestriction(valueExpr, Value)); info.TargetType = Value; }
void ISpecialParamHolder.Process(CallSiteContext info, Expression valueExpr) { info.LateStaticType = valueExpr; }
/// <summary> /// Resolves methods to be called. /// </summary> protected abstract MethodBase[] ResolveMethods(CallSiteContext bound);