示例#1
0
        public static bool IsEquel(EcmaState state, EcmaValue x, EcmaValue y)
        {
            if (x.Type() == y.Type())
            {
                if (x.IsUndefined() || x.IsNull())
                {
                    return(true);
                }

                if (x.IsNumber())
                {
                    double xn = x.ToNumber(state);
                    double yn = y.ToNumber(state);

                    if (Double.IsNaN(xn) || Double.IsNaN(yn))
                    {
                        return(false);
                    }

                    if (xn == +0 && yn == -0 || xn == -0 && yn == +0)
                    {
                        return(true);
                    }
                    return(xn == yn);
                }

                if (x.IsString())
                {
                    return(x.ToString(state) == y.ToString(state));
                }

                if (x.IsBoolean())
                {
                    return(x.ToBoolean(state) == y.ToBoolean(state));
                }

                return(y.ToObject(state) == x.ToObject(state));
            }

            if (x.IsNull() && y.IsUndefined() || x.IsUndefined() && y.IsUndefined())
            {
                return(true);
            }

            if (!(x.IsNumber() || x.IsString()) && y.IsObject() || x.IsObject() && !(y.IsNumber() || y.IsString()))
            {
                return(x.ToPrimitiv(state) == y.ToPrimitiv(state));
            }
            return(x.ToNumber(state) == y.ToNumber(state));
        }
示例#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);
            }
        }