示例#1
0
文件: MondValue.cs 项目: foobit/Mond
        /// <summary>
        /// Get or set values in the Object or Array or its' prototype.
        /// </summary>
        public MondValue this[MondValue index]
        {
            get
            {
                if (ReferenceEquals(index, null))
                {
                    throw new ArgumentNullException(nameof(index));
                }

                if (Type == MondValueType.Array && (index.Type == MondValueType.Number || index.Type == MondValueType.Object))
                {
                    var n = (int)index;

                    if (n < 0)
                    {
                        n += ArrayValue.Count;
                    }

                    if (n < 0 || n >= ArrayValue.Count)
                    {
                        throw new MondRuntimeException(RuntimeError.IndexOutOfBounds);
                    }

                    return(ArrayValue[n]);
                }

                MondValue indexValue;
                if (Type == MondValueType.Object)
                {
                    if (ObjectValue.Values.TryGetValue(index, out indexValue))
                    {
                        return(CheckWrapFunction(indexValue));
                    }
                }

                var i         = 0;
                var prototype = Prototype;

                while (prototype != null)
                {
                    var currentValue = prototype;

                    if (currentValue.Type != MondValueType.Object)
                    {
                        break;
                    }

                    var currentObjValue = currentValue.ObjectValue;
                    if (currentObjValue.Values.TryGetValue(index, out indexValue))
                    {
                        return(CheckWrapFunction(indexValue));
                    }

                    prototype = currentValue.Prototype;
                    i++;

                    if (i > 100)
                    {
                        throw new MondRuntimeException(RuntimeError.CircularPrototype);
                    }
                }

                if (Type == MondValueType.Object)
                {
                    if (TryDispatch("__get", out indexValue, this, index))
                    {
                        return(CheckWrapFunction(indexValue));
                    }
                }

                return(Undefined);
            }
            set
            {
                if (ReferenceEquals(index, null))
                {
                    throw new ArgumentNullException(nameof(index));
                }

                if (ReferenceEquals(value, null))
                {
                    throw new ArgumentNullException(nameof(value));
                }

                if (Type == MondValueType.Array && (index.Type == MondValueType.Number || index.Type == MondValueType.Object))
                {
                    var n = (int)index;

                    if (n < 0)
                    {
                        n += ArrayValue.Count;
                    }

                    if (n < 0 || n >= ArrayValue.Count)
                    {
                        throw new MondRuntimeException(RuntimeError.IndexOutOfBounds);
                    }

                    ArrayValue[n] = value;
                    return;
                }

                if (Type == MondValueType.Object && ObjectValue.Values.ContainsKey(index))
                {
                    if (ObjectValue.Locked)
                    {
                        throw new MondRuntimeException(RuntimeError.ObjectIsLocked);
                    }

                    ObjectValue.Values[index] = value;
                    return;
                }

                var i         = 0;
                var prototype = Prototype;

                while (prototype != null)
                {
                    var currentValue = prototype;

                    if (currentValue.Type != MondValueType.Object)
                    {
                        break;
                    }

                    var values = currentValue.ObjectValue.Values;
                    if (values.ContainsKey(index))
                    {
                        if (currentValue.ObjectValue.Locked)
                        {
                            break; // hit a wall in the prototype chain, don't continue
                        }
                        values[index] = value;
                        return;
                    }

                    prototype = currentValue.Prototype;
                    i++;

                    if (i > 100)
                    {
                        throw new MondRuntimeException(RuntimeError.CircularPrototype);
                    }
                }

                if (Type != MondValueType.Object)
                {
                    throw new MondRuntimeException(RuntimeError.CantCreateField, Type.GetName());
                }

                if (ObjectValue.Locked)
                {
                    throw new MondRuntimeException(RuntimeError.ObjectIsLocked);
                }

                if (TryDispatch("__set", out var _, this, index, value))
                {
                    return;
                }

                ObjectValue.Values[index] = value;
            }
        }
示例#2
0
 private static void UnsupportedMondTypeError( MondValueType type )
 {
     throw new NotSupportedException( "Unsupported MondValueType '{0}'".With( type.GetName() ) );
 }
示例#3
0
 private static void UnsupportedMondTypeError(MondValueType type) => throw new NotSupportedException(
           $"Unsupported MondValueType '{type.GetName()}'");