Exemplo n.º 1
0
        /// <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());
        }