/// <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()); }
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()); }
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()); }