/// <summary>
        /// Default implementation of <see cref="IAccessorVisitor.Visit"/> that supports evaluation of intrinsic
        /// functions Number(), String(), Boolean().
        /// By overriding this any binding to to external objects can be achieved (recall to call this base
        /// method when overriding).
        /// </summary>
        /// <param name="frame">The current frame (gives access to the next frame if any).</param>
        public virtual PExpr Visit(IAccessorFrame frame)
        {
            IAccessorMemberFrame head = frame as IAccessorMemberFrame;

            // We can only handle member access at the root level:
            if (head == null)
            {
                return(frame.SetError());
            }

            // Lookup from the longest path to the head in registered objects:
            // more "precise" objects mask root ones.
            var deepestMemberFrame = frame.NextAccessors(true)
                                     .Select(f => f as IAccessorMemberFrame)
                                     .TakeWhile(f => f != null)
                                     .LastOrDefault();

            // We obtain at least the head, hence the do...while.
            do
            {
                RuntimeObj obj;
                if (_objects.TryGetValue(deepestMemberFrame.Expr.MemberFullName, out obj))
                {
                    return(deepestMemberFrame.SetResult(obj));
                }
                deepestMemberFrame = deepestMemberFrame.PrevMemberAccessor;
            }while(deepestMemberFrame != null);
            var s = frame.GetImplementationState(c =>
                                                 c.On("Number").OnCall((f, args) =>
            {
                if (args.Count == 0)
                {
                    return(f.SetResult(DoubleObj.Zero));
                }
                return(f.SetResult(args[0] as DoubleObj ?? DoubleObj.Create(args[0].ToDouble())));
            }
                                                                       )
                                                 .On("String").OnCall((f, args) =>
            {
                if (args.Count == 0)
                {
                    return(f.SetResult(StringObj.EmptyString));
                }
                return(f.SetResult(StringObj.Create(args[0].ToString())));
            })
                                                 .On("Boolean").OnCall((f, args) =>
            {
                return(f.SetResult(args.Count == 1 && args[0].ToBoolean() ? BooleanObj.True : BooleanObj.False));
            })
                                                 );

            return(s != null?s.Visit() : frame.SetError());
        }
示例#2
0
        public override PExpr Visit(IAccessorFrame frame)
        {
            var s = frame.GetImplementationState(c =>
                                                 c.On("ToString").OnCall((f, args) =>
            {
                int radix = 10;
                if (args.Count == 1)
                {
                    radix = JSSupport.ToInt32(args[0].ToDouble());
                }
                if (radix < 2 || radix > 36)
                {
                    return(f.SetError("Radix must be between 2 and 36."));
                }
                return(f.SetResult(StringObj.Create(JSSupport.ToString(_value, radix))));
            }
                                                                         ));

            return(s != null?s.Visit() : frame.SetError());
        }
示例#3
0
        public override PExpr Visit(IAccessorFrame frame)
        {
            var s = frame.GetImplementationState(c =>
                                                 c.OnIndex((f, arg) =>
            {
                int idx = JSSupport.ToInt32(arg.ToDouble());
                if (idx < 0 || idx >= _value.Length)
                {
                    return(f.SetResult(EmptyString));
                }
                return(f.SetResult(Create(new string( _value[idx], 1 ))));
            })
                                                 .On("ToString").OnCall((f, args) =>
            {
                return(f.SetResult(this));
            }
                                                                        ));

            return(s != null?s.Visit() : frame.SetError());
        }
            public override PExpr Visit(IAccessorFrame frame)
            {
                var s = frame.GetImplementationState(c => c
                                                     .On("AnIntrinsicArray").OnIndex((f, idx) =>
                {
                    if (idx.Type != "number")
                    {
                        return(f.SetError("Number expected."));
                    }
                    int i = JSSupport.ToInt32(idx.ToDouble());
                    if (i < 0 || i >= AnIntrinsicArray.Length)
                    {
                        return(f.SetError("Index out of range."));
                    }
                    return(f.SetResult(DoubleObj.Create(AnIntrinsicArray[i])));
                })
                                                     .On("An").On("array").On("with").On("one").On("cell").OnIndex((f, idx) =>
                {
                    return(f.SetResult(StringObj.Create("An.array.with.one.cell[] => " + idx.ToString())));
                })
                                                     .On("array").OnIndex((f, idx) =>
                {
                    throw new Exception("Accessing XXX.array other than 'An.Array' must not be found.");
                })
                                                     .On("Ghost").On("M").OnCall((f, args) =>
                {
                    Console.WriteLine("Ghost.M() called with {0} arguments: {1} (=> returns {0}).",
                                      args.Count,
                                      string.Join(", ", args.Select(a => a.ToString())));
                    return(f.SetResult(DoubleObj.Create(args.Count)));
                })
                                                     .On("Ghost").On("M").OnIndex((f, idx) =>
                {
                    Console.WriteLine("Ghost.M[{0}] called (=> returns {0}).", JSSupport.ToInt32(idx.ToDouble()));
                    return(f.SetResult(idx));
                })
                                                     );

                return(s == null?base.Visit(frame) : s.Visit());
            }