public string ToString(EcmaState state) { switch (this.type) { case EcmaValueType.Undefined: return("undefined"); case EcmaValueType.Null: return("null"); case EcmaValueType.Boolean: return(this.ToBoolean(state) ? "true" : "false"); case EcmaValueType.Number: return(EcmaGramma.ConvertStringToNumber(this.ToNumber(state))); case EcmaValueType.String: return((string)this.value); case EcmaValueType.Object: return((this.value as EcmaHeadObject).DefaultValue(state, "String").ToString(state)); default: throw new EcmaRuntimeException("Cant convert " + this.type.ToString() + " to string"); } }
public EcmaHeadObject ToObject(EcmaState state) { EcmaValue[] arg = new EcmaValue[] { this }; switch (this.type) { case EcmaValueType.Undefined: case EcmaValueType.Null: throw new EcmaRuntimeException("Cant convert " + this.type.ToString() + " to Object"); case EcmaValueType.Boolean: //return (state.Boolean as IConstruct).Construct(arg).ToObject(state); return(new EcmaHeadObject()); case EcmaValueType.Number: //return (state.Number as IConstruct).Construct(arg).ToObject(state); return(new EcmaHeadObject()); case EcmaValueType.String: return((state.String as IConstruct).Construct(arg).ToObject(state)); case EcmaValueType.Object: return(this.value as EcmaHeadObject); default: throw new EcmaRuntimeException("Cant convert " + this.type.ToString() + " to Object"); } }
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); }
private static EcmaComplication CreateFuncDec(EcmaState state, EcmaStatment statment) { EcmaValue func = EcmaValue.Object(new FunctionInstance(state, statment.Args, statment.Statment)); state.GlobalObject.Put(statment.Name, func); return(new EcmaComplication(EcmaComplicationType.Normal, func)); }
public bool ToBoolean(EcmaState state) { switch (this.type) { case EcmaValueType.Undefined: case EcmaValueType.Null: return(false); case EcmaValueType.Boolean: return((bool)this.value); case EcmaValueType.Number: double number = this.ToNumber(state); if (number == 0 || Double.IsNaN(number)) { return(false); } return(true); case EcmaValueType.String: return(this.ToString(state).Length > 0); default: return(true); } }
public double ToNumber(EcmaState state) { switch (this.type) { case EcmaValueType.Undefined: return(Double.NaN); case EcmaValueType.Null: return(0.0); case EcmaValueType.Boolean: return(this.ToBoolean(state) ? 1.0 : 0.0); case EcmaValueType.Number: return((double)this.value); case EcmaValueType.String: return(EcmaGramma.ConvertStringToNumber(this.ToString(state))); case EcmaValueType.Object: return((this.value as EcmaHeadObject).DefaultValue(state, "Number").ToNumber(state)); } throw new EcmaRuntimeException("Cant convert " + this.type + " to Number"); }
public static string[] ToStringArray(EcmaState state, EcmaHeadObject obj) { string[] result = new string[obj.Get("length").ToInt32(state)]; for (int i = 0; i < result.Length; i++) { result[i] = obj.Get(i.ToString()).ToString(state); } return(result); }
public static EcmaValue Plus(EcmaState state, EcmaValue left, EcmaValue right) { if (left.ToPrimitiv(state) is String || right.ToPrimitiv(state) is String) { return(EcmaValue.String(left.ToString(state) + right.ToString(state))); } return(EcmaValue.Number(left.ToNumber(state) + right.ToNumber(state))); }
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)); }
public object ToPrimitiv(EcmaState state) { if (this.IsObject()) { EcmaValue value = (this.value as EcmaHeadObject).DefaultValue(state); if (value.IsObject() || value.IsRefrence()) { throw new EcmaRuntimeException("Cant convert Object to primitiv value"); } return(value); } return(this.value); }
private static EcmaValue[] GetArguments(EcmaState state, EcmaHeadObject owner, ExpresionData[] args) { int length = owner.HasProperty("length") ? owner.Get("length").ToInt32(state) : 0; int i = 0; EcmaValue[] a = new EcmaValue[Math.Max(args.Length, length)]; for (; i < args.Length; i++) { a[i] = Reference.GetValue(EvulateExpresion(state, args[i])); } for (; i < length; i++) { a[i] = EcmaValue.Undefined(); } return(a); }
public static EcmaValue Math(EcmaState state, EcmaValue left, string sign, EcmaValue Right) { switch (sign) { case "|": return(BitwiseOr(state, left, Right)); case "^": return(BitwiseXOR(state, left, Right)); case "&": return(BitwiseAND(state, left, Right)); case "<<": return(LeftShit(state, left, Right)); case ">>": return(RightShift(state, left, Right)); case ">>>": return(UnsignedRightShit(state, left, Right)); case "+": return(Plus(state, left, Right)); case "-": return(Minus(state, left, Right)); case "*": return(Gange(state, left, Right)); case "/": return(Divide(state, left, Right)); case "%": return(Remainder(state, left, Right)); default: throw new EcmaRuntimeException("Unknown math sign: " + sign); } }
public static EcmaValue Remainder(EcmaState state, EcmaValue left, EcmaValue right) { return(EcmaValue.Number(left.ToNumber(state) % right.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); } }
public int ToInt32(EcmaState state) { return((int)(uint)ToNumber(state)); }
public static EcmaValue Minus(EcmaState state, EcmaValue left, EcmaValue right) { return(EcmaValue.Number(left.ToNumber(state) - right.ToNumber(state))); }
public static EcmaValue Divide(EcmaState state, EcmaValue left, EcmaValue right) { return(EcmaValue.Number(left.ToNumber(state) / right.ToNumber(state))); }
public uint ToUint32(EcmaState state) { return((uint)ToNumber(state)); }
public double ToInteger(EcmaState state) { return((long)ToNumber(state)); }
public static EcmaValue Gange(EcmaState state, EcmaValue left, EcmaValue right) { return(EcmaValue.Number(left.ToNumber(state) * right.ToNumber(state))); }
public static EcmaValue UnsignedRightShit(EcmaState state, EcmaValue left, EcmaValue right) { return(EcmaValue.Number((uint)left.ToInt32(state) >> (int)(right.ToUint32(state) & 0x1F))); }
public static EcmaValue LeftShit(EcmaState state, EcmaValue left, EcmaValue right) { return(EcmaValue.Number(left.ToInt32(state) << right.ToInt32(state))); }
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)); }
public static EcmaValue RightShift(EcmaState state, EcmaValue left, EcmaValue right) { return(EcmaValue.Number(left.ToInt32(state) >> right.ToInt32(state))); }
internal static EcmaComplication Evulate(EcmaState state, EcmaStatment statment) { EcmaComplication c = new EcmaComplication(EcmaComplicationType.Normal, EcmaValue.Undefined()); switch (statment.Type) { case EcmaStatmentType.FunctionDec: return(CreateFuncDec(state, statment)); case EcmaStatmentType.Expresion: return(new EcmaComplication(EcmaComplicationType.Normal, EvulateExpresion(state, statment.Expresion))); case EcmaStatmentType.Return: return(new EcmaComplication(EcmaComplicationType.Return, statment.Expresion == null ? EcmaValue.Undefined() : EvulateExpresion(state, statment.Expresion))); case EcmaStatmentType.If: if (Reference.GetValue(EvulateExpresion(state, statment.Expresion)).ToBoolean(state)) { return(Evulate(state, statment.Statment)); } else { if (statment.Else == null) { return(new EcmaComplication(EcmaComplicationType.Normal, EcmaValue.Undefined())); } return(Evulate(state, statment.Else)); } case EcmaStatmentType.Block: for (int i = 0; i < statment.Statments.Count; i++) { c = Evulate(state, statment.Statments[i]); if (c.Type != EcmaComplicationType.Normal) { return(c); } } return(new EcmaComplication(EcmaComplicationType.Normal, EcmaValue.Null())); case EcmaStatmentType.Var: EcmaHeadObject putIn = state.GetScope()[state.GetScope().Length - 1]; foreach (string key in statment.VarList.Keys) { putIn.Put(key, statment.VarList[key] == null ? EcmaValue.Undefined() : Reference.GetValue(EvulateExpresion(state, statment.VarList[key]))); } return(new EcmaComplication(EcmaComplicationType.Normal, EcmaValue.Undefined())); case EcmaStatmentType.While: c = new EcmaComplication(EcmaComplicationType.Normal, EcmaValue.Undefined()); while (EvulateExpresion(state, statment.Expresion).ToBoolean(state)) { c = Evulate(state, statment.Statment); if (c.Type == EcmaComplicationType.Break) { return(new EcmaComplication(EcmaComplicationType.Normal, EcmaValue.Undefined())); } else if (c.Type == EcmaComplicationType.Continue) { c = new EcmaComplication(EcmaComplicationType.Normal, EcmaValue.Undefined()); } else if (c.Type == EcmaComplicationType.Return) { return(c); } } return(c); case EcmaStatmentType.For: if (statment.Expresion != null) { Reference.GetValue(EvulateExpresion(state, statment.Expresion)); } while (statment.Second == null || Reference.GetValue(EvulateExpresion(state, statment.Second)).ToBoolean(state)) { c = Evulate(state, statment.Statment); if (c.Type == EcmaComplicationType.Break) { return(new EcmaComplication(EcmaComplicationType.Normal, EcmaValue.Undefined())); } else if (c.Type == EcmaComplicationType.Return) { return(c); } else if (c.Type == EcmaComplicationType.Continue) { c = new EcmaComplication(EcmaComplicationType.Normal, EcmaValue.Undefined()); } if (statment.Tree != null) { Reference.GetValue(EvulateExpresion(state, statment.Tree)); } } return(c); case EcmaStatmentType.ForIn: EcmaHeadObject obj = Reference.GetValue(EvulateExpresion(state, statment.Second)).ToObject(state); c = new EcmaComplication(EcmaComplicationType.Normal, EcmaValue.Undefined()); foreach (string key in obj.Property.Keys) { if (obj.Property[key].DontEnum) { continue; } if (statment.Expresion.Type == ExpresionType.VarList) { Reference.PutValue(EvulateExpresion(state, statment.Expresion.Multi[0].Left), EcmaValue.String(key), state.GlobalObject); } else { Reference.PutValue(EvulateExpresion(state, statment.Expresion), EcmaValue.String(key), state.GlobalObject); } c = Evulate(state, statment.Statment); if (c.Type != EcmaComplicationType.Normal) { if (c.Type == EcmaComplicationType.Break) { return(new EcmaComplication(EcmaComplicationType.Normal, EcmaValue.Undefined())); } if (c.Type == EcmaComplicationType.Continue) { c = new EcmaComplication(EcmaComplicationType.Normal, EcmaValue.Undefined()); } if (c.Type == EcmaComplicationType.Return) { return(c); } } } return(c); case EcmaStatmentType.Continue: return(new EcmaComplication(EcmaComplicationType.Continue, EcmaValue.Undefined())); default: throw new EcmaRuntimeException("Evulator out of sync. Unknown statment type: " + statment.Type.ToString()); } }
public static EcmaValue BitwiseAND(EcmaState state, EcmaValue left, EcmaValue right) { return(EcmaValue.Number(left.ToInt32(state) & right.ToInt32(state))); }
public EcmaScript() { this.State = new EcmaState(); }