예제 #1
0
        public static EcmaHeadObject ToArray(EcmaState state, List <Object> item)
        {
            ArrayIntstance array = new ArrayIntstance(state, new EcmaValue[0]);

            for (int i = 0; i < item.Count; i++)
            {
                if (item[i] is EcmaHeadObject)
                {
                    array.Put(i.ToString(), EcmaValue.Object(item[i] as EcmaHeadObject));
                }
                else if (item[i] is String)
                {
                    array.Put(i.ToString(), EcmaValue.String(item[i] as String));
                }
                else if (item[i] is Boolean)
                {
                    array.Put(i.ToString(), EcmaValue.Boolean((bool)item[i]));
                }
                else if (item[i] is Double)
                {
                    array.Put(i.ToString(), EcmaValue.Number((double)item[i]));
                }
                else if (item[i] == null)
                {
                    array.Put(i.ToString(), EcmaValue.Null());
                }
                else
                {
                    throw new EcmaRuntimeException("Could not convert " + item[i].GetType().FullName + " to ecma value");
                }
            }
            return(array);
        }
예제 #2
0
        private static EcmaValue EvulateExpresion(EcmaState state, ExpresionData expresion)
        {
            EcmaValue      value = null;
            EcmaHeadObject obj;

            switch (expresion.Type)
            {
            case ExpresionType.MultiExpresion:
                for (int i = 0; i < expresion.Multi.Count; i++)
                {
                    value = Reference.GetValue(EvulateExpresion(state, expresion.Multi[i]));
                }
                return(value);

            case ExpresionType.Assign:
                if (expresion.Sign == "=")
                {
                    EcmaValue ai = EvulateExpresion(state, expresion.Left);
                    value = Reference.GetValue(EvulateExpresion(state, expresion.Right));
                    Reference.PutValue(ai, value, state.GlobalObject);
                    return(value);
                }
                else
                {
                    EcmaValue sa = EvulateExpresion(state, expresion.Left);
                    value = Reference.GetValue(EvulateExpresion(state, expresion.Right));
                    value = EcmaMath.Math(state, Reference.GetValue(sa), expresion.Sign.Substring(0, 1), value);
                    Reference.PutValue(sa, value, state.GlobalObject);
                    return(value);
                }

            case ExpresionType.Conditional:
                return(Reference.GetValue(EvulateExpresion(state, expresion.Test)).ToBoolean(state) ? Reference.GetValue(EvulateExpresion(state, expresion.Left)) : Reference.GetValue(EvulateExpresion(state, expresion.Right)));

            case ExpresionType.Or:
                value = Reference.GetValue(EvulateExpresion(state, expresion.Left));
                if (value.ToBoolean(state))
                {
                    return(value);
                }
                return(Reference.GetValue(EvulateExpresion(state, expresion.Right)));

            case ExpresionType.AND:
                value = Reference.GetValue(EvulateExpresion(state, expresion.Left));
                if (!value.ToBoolean(state))
                {
                    return(value);
                }
                return(Reference.GetValue(EvulateExpresion(state, expresion.Right)));

            case ExpresionType.BOR:
                return(EcmaMath.Math(state, Reference.GetValue(EvulateExpresion(state, expresion.Left)), "|", Reference.GetValue(EvulateExpresion(state, expresion.Right))));

            case ExpresionType.XOR:
                return(EcmaMath.Math(state, Reference.GetValue(EvulateExpresion(state, expresion.Left)), "^", Reference.GetValue(EvulateExpresion(state, expresion.Right))));

            case ExpresionType.BAND:
                return(EcmaMath.Math(state, Reference.GetValue(EvulateExpresion(state, expresion.Left)), "&", Reference.GetValue(EvulateExpresion(state, expresion.Right))));

            case ExpresionType.Equlity:
                bool er = EcmaEquel.IsEquel(state, Reference.GetValue(EvulateExpresion(state, expresion.Left)), Reference.GetValue(EvulateExpresion(state, expresion.Right)));
                return(EcmaValue.Boolean(expresion.Sign == "==" ? er : !er));

            case ExpresionType.Relational:
                if (expresion.Sign == "<")
                {
                    value = EcmaRelational.DoRelational(state, Reference.GetValue(EvulateExpresion(state, expresion.Left)), Reference.GetValue(EvulateExpresion(state, expresion.Right)));
                    if (value.IsUndefined())
                    {
                        return(EcmaValue.Boolean(false));
                    }
                    return(value);
                }
                else if (expresion.Sign == ">")
                {
                    value = Reference.GetValue(EvulateExpresion(state, expresion.Left));
                    value = EcmaRelational.DoRelational(state, Reference.GetValue(EvulateExpresion(state, expresion.Right)), value);
                    if (value.IsUndefined())
                    {
                        return(EcmaValue.Boolean(false));
                    }
                    return(value);
                }
                else if (expresion.Sign == "<=")
                {
                    value = EcmaRelational.DoRelational(state, Reference.GetValue(EvulateExpresion(state, expresion.Right)), Reference.GetValue(EvulateExpresion(state, expresion.Left)));
                    if (value.IsBoolean() && value.ToBoolean(state) || value.IsUndefined())
                    {
                        return(EcmaValue.Boolean(false));
                    }
                    return(EcmaValue.Boolean(true));
                }
                else if (expresion.Sign == ">=")
                {
                    value = EcmaRelational.DoRelational(state, Reference.GetValue(EvulateExpresion(state, expresion.Left)), Reference.GetValue(EvulateExpresion(state, expresion.Right)));
                    if (value.IsBoolean() && value.ToBoolean(state) || value.IsUndefined())
                    {
                        return(EcmaValue.Boolean(false));
                    }
                    return(EcmaValue.Boolean(true));
                }
                return(EcmaValue.Boolean(false));

            case ExpresionType.Shift:
                return(EcmaMath.Math(state, Reference.GetValue(EvulateExpresion(state, expresion.Left)), expresion.Sign, Reference.GetValue(EvulateExpresion(state, expresion.Right))));

            case ExpresionType.Additive:
                return(EcmaMath.Math(state, Reference.GetValue(EvulateExpresion(state, expresion.Left)), expresion.Sign, Reference.GetValue(EvulateExpresion(state, expresion.Right))));

            case ExpresionType.Multiplicative:
                return(EcmaMath.Math(state, Reference.GetValue(EvulateExpresion(state, expresion.Left)), expresion.Sign, Reference.GetValue(EvulateExpresion(state, expresion.Right))));

            case ExpresionType.Unary:
                value = EvulateExpresion(state, expresion.Left);
                switch (expresion.Sign)
                {
                case "delete":
                    return(EcmaValue.Boolean(Reference.GetBase(value).Delete(Reference.GetPropertyName(value))));

                case "void":
                    Reference.GetValue(value);
                    return(EcmaValue.Undefined());

                case "typeof":
                    if (value.IsRefrence() && Reference.GetBase(value) == null)
                    {
                        return(EcmaValue.String("undefined"));
                    }

                    value = Reference.GetValue(value);

                    if (value.IsObject())
                    {
                        obj = value.ToObject(state);
                        if (obj is ICallable)
                        {
                            return(EcmaValue.String("function"));
                        }
                    }

                    return(EcmaValue.String(value.Type().ToString().ToLower()));

                case "++":
                    double ul = Reference.GetValue(EvulateExpresion(state, expresion.Left)).ToNumber(state);
                    Reference.PutValue(value, EcmaValue.Number(ul + 1), state.GlobalObject);
                    return(EcmaValue.Number(ul + 1));

                case "--":
                    double nul = Reference.GetValue(EvulateExpresion(state, expresion.Left)).ToNumber(state);
                    Reference.PutValue(value, EcmaValue.Number(nul + 1), state.GlobalObject);
                    return(EcmaValue.Number(nul + 1));

                case "+":
                    return(EcmaValue.Number(+Reference.GetValue(value).ToNumber(state)));

                case "-":
                    return(EcmaValue.Number(-Reference.GetValue(value).ToNumber(state)));

                case "~":
                    return(EcmaValue.Number(~Reference.GetValue(value).ToInt32(state)));

                case "!":
                    return(EcmaValue.Boolean(!Reference.GetValue(value).ToBoolean(state)));

                default:
                    throw new EcmaRuntimeException("Unary evulation out of sync. Unknown sign: " + expresion.Sign);
                }

            case ExpresionType.ItemGet:
                obj = Reference.GetValue(EvulateExpresion(state, expresion.Left)).ToObject(state);
                return(EcmaValue.Reference(new Reference(
                                               Reference.GetValue(EvulateExpresion(state, expresion.Right)).ToString(state),
                                               obj
                                               )));

            case ExpresionType.ObjGet:
                return(EcmaValue.Reference(new Reference(
                                               expresion.Sign,
                                               Reference.GetValue(EvulateExpresion(state, expresion.Left)).ToObject(state)
                                               )));

            case ExpresionType.New:
                value = Reference.GetValue(EvulateExpresion(state, expresion.Left));
                if (!value.IsObject())
                {
                    throw new EcmaRuntimeException("After 'new' keyword there must be a object");
                }
                obj = value.ToObject(state);

                if (!(obj is IConstruct))
                {
                    throw new EcmaRuntimeException("Object dont implements Constructor");
                }

                value = (obj as IConstruct).Construct(GetArguments(state, obj, expresion.Arg));

                if (!value.IsObject())
                {
                    throw new EcmaRuntimeException("The constructor dont return a object");
                }

                return(value);

            case ExpresionType.Call:
                EcmaValue func = EvulateExpresion(state, expresion.Left);
                value = Reference.GetValue(func);
                obj   = value.ToObject(state);
                if (!(obj is ICallable))
                {
                    throw new EcmaRuntimeException("The object dont implements Call");
                }

                EcmaHeadObject self;

                if (func.IsRefrence())
                {
                    self = Reference.GetBase(func);
                }
                else
                {
                    self = null;
                }

                return((obj as ICallable).Call(self, GetArguments(state, obj, expresion.Arg)));

            case ExpresionType.This:
                return(EcmaValue.Object(state.GetThis()));

            case ExpresionType.Identify:
                return(EcmaValue.Reference(state.GetIdentify(expresion.Name)));

            case ExpresionType.Number:
                return(EcmaValue.Number(Double.Parse(expresion.Sign)));

            case ExpresionType.Null:
                return(EcmaValue.Undefined());

            case ExpresionType.Bool:
                return(EcmaValue.Boolean(expresion.Sign == "true"));

            case ExpresionType.String:
                return(EcmaValue.String(expresion.Sign));

            case ExpresionType.VarList:
                for (int i = 0; i < expresion.Multi.Count; i++)
                {
                    value = EvulateExpresion(state, expresion.Multi[i]);
                }
                return(value);

            default:
                throw new EcmaRuntimeException("Evulator expresion out of sync. Unknown expresion type: " + expresion.Type);
            }
        }
예제 #3
0
        public static EcmaValue DoRelational(EcmaState state, EcmaValue left, EcmaValue right)
        {
            object l = left.ToPrimitiv(state);
            object r = right.ToPrimitiv(state);

            if (l is String && r is String)
            {
                string ls = l as String;
                string rs = r as String;
                if (ls.IndexOf(rs) == 0)
                {
                    return(EcmaValue.Boolean(false));
                }
                if (rs.IndexOf(ls) == 0)
                {
                    return(EcmaValue.Boolean(true));
                }
                char[] lc = ls.ToCharArray();
                char[] rc = rs.ToCharArray();

                for (int i = 0; i < Math.Min(ls.Length, rs.Length); i++)
                {
                    if (lc[i] > rc[i])
                    {
                        return(EcmaValue.Boolean(false));
                    }
                }

                return(EcmaValue.Boolean(true));
            }

            double x = left.ToNumber(state);
            double y = right.ToNumber(state);

            if (Double.IsNaN(x) || Double.IsNaN(y))
            {
                return(EcmaValue.Undefined());
            }

            if (x == y)
            {
                return(EcmaValue.Boolean(false));
            }

            if (x == -0 && y == +0 || x == +0 && y == -0)
            {
                return(EcmaValue.Boolean(false));
            }

            if (Double.IsPositiveInfinity(x) || Double.IsNegativeInfinity(y))
            {
                return(EcmaValue.Boolean(false));
            }

            if (Double.IsNegativeInfinity(x) || Double.IsPositiveInfinity(y))
            {
                return(EcmaValue.Boolean(true));
            }

            return(EcmaValue.Boolean(y > x));
        }