Ejemplo n.º 1
0
        private static bool _method_filter(MethodBase method, call_conditions cond)
        {
            var parameters = method.GetParameters();

            //Hide Sctx parameter
            if (_sctx_hack(parameters, cond))
            {
                var relevantParameters = new ParameterInfo[parameters.Length - 1];
                Array.Copy(parameters, 1, relevantParameters, 0, relevantParameters.Length);
                parameters = relevantParameters;
            }

            //Criteria No.1: The number of arguments has to match the number of parameters
            if (cond.Args.Length != parameters.Length)
                return false;

            //Criteria No.2: All Type-Locked arguments must match without a conversion
            for (var i = 0; i < parameters.Length; i++)
            {
                if (cond.Args[i].IsTypeLocked)
                {
                    var P = parameters[i].ParameterType;
                    var A = cond.Args[i].ClrType;
                    if (!(P.Equals(A) || P.IsAssignableFrom(A))) //Neiter Equal nor assignable
                        return false;
                }
            }

            //optional Criteria No.3: Return types must match
            if (cond.returnType != null && method is MethodInfo)
            {
                var methodEx = method as MethodInfo;
                if (!(methodEx.ReturnType.Equals(cond.returnType) ||
                    cond.returnType.IsAssignableFrom(methodEx.ReturnType)))
                {
                    return false;
                }
            }

            //The method is a candidate
            return true;
        }
Ejemplo n.º 2
0
        public bool TryContruct(
            StackContext sctx, PValue[] args, out PValue result, out MemberInfo resolvedMember)
        {
            var cond = new call_conditions(sctx, args, PCall.Get, "")
                {
                    IgnoreId = true
                };

            //Get member candidates            
            var candidates = new Stack<MemberInfo>();
            foreach (var ctor in _clrType.GetConstructors())
            {
                if (_method_filter(ctor, cond))
                    candidates.Push(ctor);
            }

            resolvedMember = null;
            if (candidates.Count == 1)
                resolvedMember = candidates.Peek();

            var ret = _try_execute(candidates, cond, null, out result);
            if (!ret)
                resolvedMember = null;

            return ret;
        }
Ejemplo n.º 3
0
 /// <summary>
 ///     Checks whether the StackContext hack can be applied.
 /// </summary>
 /// <param name = "parameters">The parameters array to check.</param>
 /// <param name = "cond">The call_condition object for the current call.</param>
 /// <returns>True if the the hack can be applied, otherwise false.</returns>
 private static bool _sctx_hack(ParameterInfo[] parameters, call_conditions cond)
 {
     //StackContext Hack
     //NOTE: This might be the source of strange problems!
     //If the one argument is missing and the first formal parameter is a StackContext,
     //supply the StackContext received in cond.sctx.
     return (
         //There have to be parameters
         parameters.Length > 0 &&
             //One argument must be missing
             cond.Args.Length + 1 == parameters.Length &&
                 //First parameter must be a StackContext
                 typeof (StackContext).IsAssignableFrom(parameters[0].ParameterType));
 }
Ejemplo n.º 4
0
        private static bool _try_execute(
            Stack<MemberInfo> candidates,
            call_conditions cond,
            PValue subject,
            out PValue ret)
        {
            ret = null;
            object result;
            while (candidates.Count > 0)
            {
                var candidate = candidates.Pop();
                switch (candidate.MemberType)
                {
                    case MemberTypes.Method:
                    case MemberTypes.Constructor:
                        //Try to execute the method
                        var method = (MethodBase) candidate;
                        var parameters = method.GetParameters();
                        var cargs = new object[parameters.Length];
                        //The Sctx hack needs to modify the supplied arguments, so we need a copy of the original reference
                        var sargs = cond.Args;

                        if (_sctx_hack(parameters, cond))
                        {
                            //Add cond.Sctx to the array of arguments
                            sargs = new PValue[sargs.Length + 1];
                            Array.Copy(cond.Args, 0, sargs, 1, cond.Args.Length);
                            sargs[0] = Object.CreatePValue(cond.Sctx);
                        }

                        for (var i = 0; i < cargs.Length; i++)
                        {
                            var arg = sargs[i];
                            if (!(arg.IsTypeLocked || arg.IsNull)) //Neither Type-locked nor null
                            {
                                var P = parameters[i].ParameterType;
                                var A = arg.ClrType;
                                if (!(P.Equals(A) || P.IsAssignableFrom(A))) //Is conversion needed?
                                {
                                    if (!arg.TryConvertTo(cond.Sctx, P, false, out arg))
                                        //Try to convert
                                        goto failed;
                                    //can't use break; because of the surrounding for-loop
                                }
                            }
                            cargs[i] = arg.Value;
                        }

                        //All conversions were succesful, ready to call the method
                        if (method is ConstructorInfo)
                        {
                            result = ((ConstructorInfo) method).Invoke(cargs);
                        }
                        else
                        {
                            try
                            {
                                if (subject == null)
                                    result = method.Invoke(null, cargs);
                                else
                                    result = method.Invoke(subject.Value, cargs);
                            }
                            catch (TargetInvocationException exc)
                            {
                                var innerRt = exc.InnerException as PrexoniteRuntimeException;

                                if (innerRt != null)
                                    throw innerRt.InnerException;
                                else
                                    throw;
                            }
                        }
                        goto success;

                        failed: //The method cannot be called. Go on to the next candidate
                        break;
                    case MemberTypes.Field:
                        //Do field access
                        var field = (FieldInfo) candidate;
                        if (cond.Call == PCall.Get)
                            if (subject == null)
                                result = field.GetValue(null);
                            else
                                result = field.GetValue(subject.Value);
                        else
                        {
                            var arg = cond.Args[0];
                            if (!(arg.IsTypeLocked || arg.IsNull)) //Neither Type-locked nor null
                            {
                                var P = field.FieldType;
                                var A = arg.ClrType;
                                if (!(P.Equals(A) || P.IsAssignableFrom(A))) //Is conversion needed?
                                {
                                    if (!arg.TryConvertTo(cond.Sctx, P, false, out arg))
                                        //Try to convert
                                        break;
                                }
                            }
                            if (subject == null)
                                field.SetValue(null, arg.Value);
                            else
                                field.SetValue(subject.Value, arg.Value);
                            result = null;
                        }
                        goto success;
                    case MemberTypes.Property:
                        //Push accessor method
                        var property = (PropertyInfo) candidate;
                        if (cond.Call == PCall.Get)
                            candidates.Push(property.GetGetMethod());
                        else
                            candidates.Push(property.GetSetMethod());
                        break;
                    case MemberTypes.Event:
                        //Push requested method
                        var info = (EventInfo) candidate;
                        if (cond.Directive == "" ||
                            Engine.DefaultStringComparer.Compare(cond.Directive, "Raise") == 0)
                        {
                            candidates.Push(info.GetRaiseMethod());
                        }
                        else if (Engine.DefaultStringComparer.Compare(cond.Directive, "Add") == 0)
                        {
                            candidates.Push(info.GetAddMethod());
                        }
                        else if (Engine.DefaultStringComparer.Compare(cond.Directive, "Remove") == 0)
                        {
                            candidates.Push(info.GetRemoveMethod());
                        }
                        break;
                }
            }

            return false;

            success:
            if (cond.Call == PCall.Get)
            {
                //We'll let the executing engin decide which ptype suits best:
                ret = cond.Sctx.CreateNativePValue(result);
            }
            return true;
        }
Ejemplo n.º 5
0
        private bool _try_call_conversion_operator(
            StackContext sctx,
            PValue[] args,
            PCall call,
            string id,
            Type targetType,
            out PValue result)
        {
            result = null;

            if (string.IsNullOrEmpty(id))
                throw new ArgumentException("id may not be null or empty.");

            var cond = new call_conditions(sctx, args, call, id)
                {
                    returnType = targetType
                };

            //Get member candidates            
            var candidates = new Stack<MemberInfo>(
                _clrType.FindMembers(
                    MemberTypes.Method,
                    //Member types
                    BindingFlags.Static | BindingFlags.Public,
                    //Search domain
                    _member_filter,
                    cond)); //Filter

            return _try_execute(candidates, cond, null, out result);
        }
Ejemplo n.º 6
0
        public bool TryStaticCall(
            StackContext sctx,
            PValue[] args,
            PCall call,
            string id,
            out PValue result,
            out MemberInfo resolvedMember)
        {
            result = null;
            resolvedMember = null;

            if (id == null)
                id = "";

            var cond = new call_conditions(sctx, args, call, id);
            MemberTypes mtypes;
            MemberFilter filter;
            if (id.Length != 0)
            {
                filter = _member_filter;
                if (id.LastIndexOf('\\') == 0)
                    return false; //Default index accessors do not accept calling directives
                mtypes = MemberTypes.Event | MemberTypes.Field | MemberTypes.Method |
                    MemberTypes.Property;
            }
            else
            {
                filter = _default_member_filter;
                mtypes = MemberTypes.Property | MemberTypes.Method;
                cond.memberRestriction = new List<MemberInfo>(_clrType.GetDefaultMembers());
                cond.IgnoreId = true;
            }

            //Get member candidates            
            var candidates = new Stack<MemberInfo>(
                _clrType.FindMembers(
                    mtypes,
                    //Member types
                    BindingFlags.Static | BindingFlags.Public,
                    //Search domain
                    filter,
                    cond)); //Filter

            if (candidates.Count == 1)
                resolvedMember = candidates.Peek();

            var ret = _try_execute(candidates, cond, null, out result);
            if (!ret) //Call did not succeed -> member invalid
                resolvedMember = null;
            return ret;
        }
Ejemplo n.º 7
0
        internal bool TryDynamicCall(
            StackContext sctx,
            PValue subject,
            PValue[] args,
            PCall call,
            string id,
            out PValue result,
            out MemberInfo resolvedMember,
            bool suppressIObject)
        {
            result = null;
            resolvedMember = null;

            if (id == null)
                id = "";

            var iobj = subject.Value as IObject;
            if ((!suppressIObject) && iobj != null &&
                iobj.TryDynamicCall(sctx, args, call, id, out result))
                return true;

            //Special interop members
            switch (id.ToLowerInvariant())
            {
                case @"\implements":
                    foreach (var arg in args)
                    {
                        Type T;
                        if (arg.Type is ObjectPType &&
                            typeof (Type).IsAssignableFrom(((ObjectPType) arg.Type).ClrType))
                            T = (Type) arg.Value;
                        else
                            T = GetType(sctx, arg.CallToString(sctx));

                        if (!T.IsAssignableFrom(ClrType))
                        {
                            result = false;
                            return true;
                        }
                    }
                    result = true;
                    return true;
                case @"\boxed":
                    result = sctx.CreateNativePValue(subject);
                    return true;
            }

            var cond = new call_conditions(sctx, args, call, id);
            MemberTypes mtypes;
            MemberFilter filter;
            if (id.Length != 0)
            {
                filter = _member_filter;

                if (id.LastIndexOf('\\') == 0)
                    return false; //Default index accessors do not accept calling directives
                mtypes = MemberTypes.Event | MemberTypes.Field | MemberTypes.Method |
                    MemberTypes.Property;
            }
            else
            {
                filter = _default_member_filter;
                mtypes = MemberTypes.Property | MemberTypes.Method;
                cond.memberRestriction = new List<MemberInfo>(_clrType.GetDefaultMembers());
                cond.IgnoreId = true;
                if (subject.Value is Array)
                {
                    cond.memberRestriction.AddRange(
                        _clrType.FindMembers(
                            MemberTypes.Method,
                            BindingFlags.Public | BindingFlags.Instance,
                            Type.FilterName,
                            cond.Call == PCall.Get ? "GetValue" : "SetValue"));
                    cond.memberRestriction.AddRange(
                        _clrType.FindMembers(
                            MemberTypes.Method,
                            BindingFlags.Public | BindingFlags.Instance,
                            Type.FilterName,
                            cond.Call == PCall.Get ? "Get" : "Set"));
                }
            }

            //Get public member candidates, a stack is used so that newly discovered members 
            // can be examined with priority
            var candidates = new Stack<MemberInfo>(
                _clrType.FindMembers(
                    mtypes,
                    //Member types
                    BindingFlags.Instance | BindingFlags.Public,
                    //Search domain
                    filter,
                    cond)); //Filter

            if (candidates.Count == 1)
                resolvedMember = candidates.Peek();

            var ret = _try_execute(candidates, cond, subject, out result);
            if (!ret) //Call did not succeed -> member invalid
                resolvedMember = null;

            return ret;
        }