예제 #1
0
        internal override SObject GetMember(ScriptProcessor processor, SObject accessor, bool isIndexer)
        {
            if (isIndexer && accessor.TypeOf() == LITERAL_TYPE_NUMBER)
            {
                if (IndexerGetFunction != null)
                {
                    return IndexerGetFunction.Call(processor, this, this, new SObject[] { accessor });
                }
                else
                {
                    return processor.Undefined;
                }
            }

            string memberName;
            if (accessor is SString)
                memberName = ((SString)accessor).Value;
            else
                memberName = accessor.ToString(processor).Value;

            if (Members.ContainsKey(memberName))
            {
                return Members[memberName];
            }
            else if (Prototype != null && Prototype.HasMember(processor, memberName))
            {
                return Prototype.GetMember(processor, accessor, isIndexer);
            }
            else if (SuperClass != null)
            {
                return SuperClass.GetMember(processor, accessor, isIndexer);
            }

            return processor.Undefined;
        }
예제 #2
0
        internal static string AddOperator(ScriptProcessor processor, SObject left, SObject right)
        {
            if (left is SString || right is SString)
            {
                string strLeft, strRight;

                if (left is SString)
                    strLeft = ((SString)left).Value;
                else
                    strLeft = left.ToString(processor).Value;

                if (right is SString)
                    strRight = ((SString)right).Value;
                else
                    strRight = right.ToString(processor).Value;

                return strLeft + strRight;
            }
            else
            {
                var numbers = GetNumericOperatorParameters(processor, left, right);

                return SNumber.ConvertToScriptString(numbers.Item1 + numbers.Item2);
            }
        }
예제 #3
0
 internal override void SetMember(ScriptProcessor processor, SObject accessor, bool isIndexer, SObject value)
 {
     if (processor.Context.HasCallback(CallbackType.SetMember))
     {
         var callback = (DSetMember)processor.Context.GetCallback(CallbackType.SetMember);
         Task task = Task.Factory.StartNew(() => callback(processor, accessor, isIndexer, value));
         task.Wait();
     }
     else
     {
         processor.ErrorHandler.ThrowError(ErrorType.APIError, ErrorHandler.MESSAGE_API_NOT_SUPPORTED);
     }
 }
예제 #4
0
        internal override SObject ExecuteMethod(ScriptProcessor processor, string methodName, SObject caller, SObject This, SObject[] parameters)
        {
            if (processor.Context.HasCallback(CallbackType.ExecuteMethod))
            {
                var callback = (DExecuteMethod)processor.Context.GetCallback(CallbackType.ExecuteMethod);
                Task<SObject> task = Task<SObject>.Factory.StartNew(() => callback(processor, methodName, parameters));
                task.Wait();

                return task.Result;
            }
            else
            {
                processor.ErrorHandler.ThrowError(ErrorType.APIError, ErrorHandler.MESSAGE_API_NOT_SUPPORTED);
                return processor.Undefined;
            }
        }
예제 #5
0
        private static Tuple<double, double> GetNumericOperatorParameters(ScriptProcessor processor, SObject left, SObject right)
        {
            double numLeft, numRight;

            if (left is SNumber)
                numLeft = ((SNumber)left).Value;
            else
                numLeft = left.ToNumber(processor).Value;

            if (right is SNumber)
                numRight = ((SNumber)right).Value;
            else
                numRight = right.ToNumber(processor).Value;

            return new Tuple<double, double>(numLeft, numRight);
        }
예제 #6
0
        internal override SObject GetMember(ScriptProcessor processor, SObject accessor, bool isIndexer)
        {
            if (processor.Context.HasCallback(CallbackType.GetMember))
            {
                var callback = (DGetMember)processor.Context.GetCallback(CallbackType.GetMember);
                Task<SObject> task = Task<SObject>.Factory.StartNew(() => callback(processor, accessor, isIndexer));
                task.Wait();

                return task.Result;
            }
            else
            {
                processor.ErrorHandler.ThrowError(ErrorType.APIError, ErrorHandler.MESSAGE_API_NOT_SUPPORTED);
                return processor.Undefined;
            }
        }
예제 #7
0
        private static Tuple<bool, bool> GetBooleanicOperatorParameters(ScriptProcessor processor, SObject left, SObject right)
        {
            bool boolLeft, boolRight;

            if (left is SBool)
                boolLeft = ((SBool)left).Value;
            else
                boolLeft = left.ToBool(processor).Value;

            if (right is SBool)
                boolRight = ((SBool)right).Value;
            else
                boolRight = right.ToBool(processor).Value;

            return new Tuple<bool, bool>(boolLeft, boolRight);
        }
예제 #8
0
        internal override void SetMember(ScriptProcessor processor, SObject accessor, bool isIndexer, SObject value)
        {
            string memberName;
            if (accessor is SString)
                memberName = ((SString)accessor).Value;
            else
                memberName = accessor.ToString(processor).Value;

            if (_context.IsVariable(memberName))
            {
                _context.GetVariable(memberName).Data = value;
            }
            else
            {
                processor.ErrorHandler.ThrowError(ErrorType.ReferenceError, ErrorHandler.MESSAGE_REFERENCE_NOT_DEFINED, new object[] { memberName });
            }
        }
예제 #9
0
        /// <summary>
        /// Compares two objects for equality, respecting their typings.
        /// </summary>
        /// <remarks>Used by the === and !== equality operators.</remarks>
        public static bool StrictEquals(ScriptProcessor processor, SObject left, SObject right)
        {
            left = SObject.Unbox(left);
            right = SObject.Unbox(right);

            if (left.TypeOf() != right.TypeOf())
            {
                return false;
            }
            // If they are undefined or null, return true:
            else if (left.TypeOf() == SObject.LITERAL_UNDEFINED || left.TypeOf() == SObject.LITERAL_NULL)
            {
                return true;
            }
            // Both are numbers:
            else if (left.TypeOf() == SObject.LITERAL_TYPE_NUMBER)
            {
                double numLeft = ((SNumber)left).Value;
                double numRight = ((SNumber)right).Value;

                return numLeft == numRight;
            }
            // Both are string:
            else if (left.TypeOf() == SObject.LITERAL_TYPE_STRING)
            {
                string strLeft = ((SString)left).Value;
                string strRight = ((SString)right).Value;

                return strLeft == strRight;
            }
            // Both are bool:
            else if (left.TypeOf() == SObject.LITERAL_TYPE_BOOL)
            {
                bool boolLeft = ((SBool)left).Value;
                bool boolRight = ((SBool)right).Value;

                return boolLeft == boolRight;
            }
            else
            {
                return ReferenceEquals(left, right);
            }
        }
예제 #10
0
        internal override SObject ExecuteMethod(ScriptProcessor processor, string methodName, SObject caller, SObject This, SObject[] parameters)
        {
            // The statement that entered this method looks like this: this.varName(), where varName is a variable containing an SFunction object.

            if (_context.IsVariable(methodName))
            {
                SVariable methodVariable = _context.GetVariable(methodName);
                SObject method = methodVariable.Data;

                if (method is SFunction)
                {
                    return ((SFunction)method).Call(processor, caller, This, parameters);
                }
                else
                {
                    return processor.ErrorHandler.ThrowError(ErrorType.TypeError, ErrorHandler.MESSAGE_TYPE_NOT_A_FUNCTION, new object[] { methodName });
                }
            }
            return processor.ErrorHandler.ThrowError(ErrorType.ReferenceError, ErrorHandler.MESSAGE_REFERENCE_NOT_DEFINED, new object[] { methodName });
        }
예제 #11
0
        internal static string AndOperator(ScriptProcessor processor, SObject left, SObject right)
        {
            var bools = GetBooleanicOperatorParameters(processor, left, right);

            return SBool.ConvertToScriptString(bools.Item1 && bools.Item2);
        }
예제 #12
0
        internal static string LargerOperator(ScriptProcessor processor, SObject left, SObject right)
        {
            var numbers = GetNumericOperatorParameters(processor, left, right);

            return SBool.ConvertToScriptString(numbers.Item1 > numbers.Item2);
        }
예제 #13
0
 internal static string TypeNotEqualsOperator(ScriptProcessor processor, SObject left, SObject right)
 {
     return SBool.ConvertToScriptString(!ObjectComparer.StrictEquals(processor, left, right));
 }
예제 #14
0
        internal static string DecrementOperator(ScriptProcessor processor, SObject obj)
        {
            // Only variables can be decremented:

            if (obj is SVariable)
            {
                var svar = (SVariable)obj;
                svar.Data = processor.CreateNumber(svar.Data.ToNumber(processor).Value - 1D);
                return svar.Identifier;
            }
            else
            {
                processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_INVALID_DECREMENT);
                return "";
            }
        }
예제 #15
0
 /// <summary>
 /// Creates an instance of the given prototype.
 /// </summary>
 internal SObject CreateInstance(Prototype prototype, SObject[] parameters)
 {
     if (!prototype.IsAbstract)
         return prototype.CreateInstance(_processor, parameters, true);
     else
         return _processor.ErrorHandler.ThrowError(ErrorType.TypeError, ErrorHandler.MESSAGE_TYPE_ABSTRACT_NO_INSTANCE);
 }
예제 #16
0
 internal static string NotOperator(ScriptProcessor processor, SObject obj)
 {
     return SBool.ConvertToScriptString(!obj.ToBool(processor).Value);
 }
예제 #17
0
 internal override SObject ExecuteMethod(ScriptProcessor processor, string methodName, SObject caller, SObject This, SObject[] parameters)
 {
     if (Members.ContainsKey(methodName))
     {
         if (Members[methodName].Data.TypeOf() == LITERAL_TYPE_FUNCTION)
         {
             return ((SFunction)Members[methodName].Data).Call(processor, caller, this, parameters);
         }
         else
         {
             return processor.ErrorHandler.ThrowError(ErrorType.TypeError, ErrorHandler.MESSAGE_TYPE_NOT_A_FUNCTION, new object[] { methodName });
         }
     }
     else if (Prototype != null && Prototype.HasMember(processor, methodName))
     {
         return Prototype.ExecuteMethod(processor, methodName, caller, This, parameters);
     }
     else if (SuperClass != null)
     {
         return SuperClass.ExecuteMethod(processor, methodName, caller, This, parameters);
     }
     else
     {
         return processor.ErrorHandler.ThrowError(ErrorType.TypeError, ErrorHandler.MESSAGE_TYPE_NOT_A_FUNCTION, new object[] { methodName });
     }
 }
예제 #18
0
        internal static string ModulusOperator(ScriptProcessor processor, SObject left, SObject right)
        {
            var numbers = GetNumericOperatorParameters(processor, left, right);

            if (numbers.Item2 == 0D) // Because, when we divide by 0, we get Infinity, but when we do (x % 0), we get NaN. Great.
                return SObject.LITERAL_NAN;

            return SNumber.ConvertToScriptString(numbers.Item1 % numbers.Item2);
        }
예제 #19
0
        /// <summary>
        /// Throws an error with the given error object.
        /// </summary>
        public SObject ThrowError(SObject errorObject)
        {
            ErrorObject = errorObject;

            throw new ScriptException(ErrorObject);
        }
예제 #20
0
        internal static string MultiplyOperator(ScriptProcessor processor, SObject left, SObject right)
        {
            var numbers = GetNumericOperatorParameters(processor, left, right);

            return SNumber.ConvertToScriptString(numbers.Item1 * numbers.Item2);
        }
예제 #21
0
 public ScriptException(SObject errorObject)
 {
     ErrorObject = errorObject;
 }
예제 #22
0
 internal void AddMember(string idenfifier, SObject data)
 {
     Members.Add(idenfifier, new SVariable(idenfifier, data));
 }
예제 #23
0
 /// <summary>
 /// Creates an instance with the given prototype name.
 /// </summary>
 internal SObject CreateInstance(string prototypeName, SObject[] parameters)
 {
     return CreateInstance(GetPrototype(prototypeName), parameters);
 }
예제 #24
0
        internal static string ExponentOperator(ScriptProcessor processor, SObject left, SObject right)
        {
            var numbers = GetNumericOperatorParameters(processor, left, right);

            return SNumber.ConvertToScriptString(Math.Pow(numbers.Item1, numbers.Item2));
        }
예제 #25
0
 internal override SObject ExecuteMethod(ScriptProcessor processor, string methodName, SObject caller, SObject This, SObject[] parameters)
 {
     return Call(processor, caller, This, parameters);
 }
예제 #26
0
        internal override void SetMember(ScriptProcessor processor, SObject accessor, bool isIndexer, SObject value)
        {
            if (isIndexer && accessor.TypeOf() == LITERAL_TYPE_NUMBER)
            {
                if (IndexerSetFunction != null)
                {
                    IndexerSetFunction.Call(processor, this, this, new SObject[] { accessor, value });
                }
            }

            string memberName;
            if (accessor is SString)
                memberName = ((SString)accessor).Value;
            else
                memberName = accessor.ToString(processor).Value;

            if (Members.ContainsKey(memberName))
            {
                Members[memberName].Data = value;
            }
            else if (Prototype != null && Prototype.HasMember(processor, memberName) && !Prototype.IsStaticMember(memberName))
            {
                // This is the case when new members got added to the prototype, and we haven't copied them over to the instance yet.
                // So we do that now, and then set the value of that member:
                AddMember(memberName, value);
            }
            else if (SuperClass != null)
            {
                SuperClass.SetMember(processor, accessor, isIndexer, value);
            }
        }
예제 #27
0
        /// <summary>
        /// Multiplies an object with -1.
        /// </summary>
        internal static SObject NegateNumber(ScriptProcessor processor, SObject obj)
        {
            double number;
            if (obj is SNumber)
                number = ((SNumber)obj).Value;
            else
                number = obj.ToNumber(processor).Value;

            return processor.CreateNumber(number * -1);
        }
예제 #28
0
        /// <summary>
        /// Executes the function.
        /// </summary>
        /// <param name="processor">The processor with context that called this functions.</param>
        /// <param name="caller">The calling object.</param>
        /// <param name="This">The "This" reference used in the call context.</param>
        /// <param name="parameters">The parameters used in this function call.</param>
        public SObject Call(ScriptProcessor processor, SObject caller, SObject This, SObject[] parameters)
        {
            ScriptProcessor functionProcessor = new ScriptProcessor(processor.Context);
            SObject functionReturnObject;

            if (_method != null)
            {
                functionReturnObject = _method(functionProcessor, caller, This, parameters);
            }
            else
            {
                for (int i = 0; i < _parameters.Length; i++)
                {
                    if (parameters.Length > i)
                    {
                        functionProcessor.Context.AddVariable(_parameters[i], parameters[i]);
                    }
                    else
                    {
                        functionProcessor.Context.AddVariable(_parameters[i], functionProcessor.Undefined);
                    }
                }

                functionProcessor.Context.This = This;
                functionReturnObject = functionProcessor.Run(Body);
            }

            if (functionProcessor.ErrorHandler.ThrownError)
                processor.ErrorHandler.ThrowError(functionProcessor.ErrorHandler.ErrorObject);

            return functionReturnObject;
        }
예제 #29
0
        /// <summary>
        /// Compares two objects for equality, converting types if needed.
        /// </summary>
        /// <remarks>Used by the == and != equality operators.</remarks>
        public static bool LooseEquals(ScriptProcessor processor, SObject left, SObject right)
        {
            left = SObject.Unbox(left);
            right = SObject.Unbox(right);

            // both types are the same:
            if (left.TypeOf() == right.TypeOf())
            {
                // If they are undefined or null, return true:
                if (left.TypeOf() == SObject.LITERAL_UNDEFINED || left.TypeOf() == SObject.LITERAL_NULL)
                {
                    return true;
                }
                // Both are numbers:
                else if (left.TypeOf() == SObject.LITERAL_TYPE_NUMBER)
                {
                    double numLeft = ((SNumber)left).Value;
                    double numRight = ((SNumber)right).Value;

                    return numLeft == numRight;
                }
                // Both are string:
                else if (left.TypeOf() == SObject.LITERAL_TYPE_STRING)
                {
                    string strLeft = ((SString)left).Value;
                    string strRight = ((SString)right).Value;

                    return strLeft == strRight;
                }
                // Both are bool:
                else if (left.TypeOf() == SObject.LITERAL_TYPE_BOOL)
                {
                    bool boolLeft = ((SBool)left).Value;
                    bool boolRight = ((SBool)right).Value;

                    return boolLeft == boolRight;
                }
                else
                {
                    return ReferenceEquals(left, right);
                }
            }
            // null & undefined
            else if (left.TypeOf() == SObject.LITERAL_NULL && right.TypeOf() == SObject.LITERAL_UNDEFINED ||
                left.TypeOf() == SObject.LITERAL_UNDEFINED && right.TypeOf() == SObject.LITERAL_NULL)
            {
                return true;
            }
            // When one is a number and another is a string, convert the string to a number and compare:
            else if (left.TypeOf() == SObject.LITERAL_TYPE_STRING && right.TypeOf() == SObject.LITERAL_TYPE_NUMBER)
            {
                double numLeft = left.ToNumber(processor).Value;
                double numRight = ((SNumber)right).Value;

                return numLeft == numRight;
            }
            else if (left.TypeOf() == SObject.LITERAL_TYPE_NUMBER && right.TypeOf() == SObject.LITERAL_TYPE_STRING)
            {
                double numRight = right.ToNumber(processor).Value;
                double numLeft = ((SNumber)left).Value;

                return numLeft == numRight;
            }
            else if (left.TypeOf() == SObject.LITERAL_TYPE_BOOL)
            {
                return LooseEquals(processor, left.ToNumber(processor), right);
            }
            else if (right.TypeOf() == SObject.LITERAL_TYPE_BOOL)
            {
                return LooseEquals(processor, left, right.ToNumber(processor));
            }
            else
            {
                return false;
            }
        }
예제 #30
0
        internal static string DivideOperator(ScriptProcessor processor, SObject left, SObject right)
        {
            var numbers = GetNumericOperatorParameters(processor, left, right);

            if (numbers.Item2 == 0D) // Catch division by 0 by returning infinity (wtf -> what a terrible feature).
                return SObject.LITERAL_INFINITY;

            return SNumber.ConvertToScriptString(numbers.Item1 / numbers.Item2);
        }