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