/// <summary> /// (rename old-name new-name) /// </summary> public static SSObject Rename(SSExpression[] exps, SSScope scope) { string oname = exps[0].Token.Value; string nname = exps[1].Token.Value; (!oname.Equals(nname)).OrThrows("same name {0}".Fmt(oname)); try { var obj = scope.Find(oname); scope.Define(nname, obj); scope.Undefine(oname); return(nname + " " + obj.ToString()); } catch (Exception) { Func <SSExpression[], SSScope, SSObject> obj = null; if (SSScope.BuiltinFunctions.TryGetValue(oname, out obj)) { SSScope.BuiltinFunctions[nname] = obj; SSScope.BuiltinFunctions.Remove(oname); return(nname + " " + obj.ToString()); } throw new Exception("cannot find {0} in scope, and it is not a builtin".Fmt(nname)); } }
public static SSObject Mul(SSExpression[] exps, SSScope scope) { var iter = exps.Select(obj => obj.Evaluate(scope)).GetEnumerator(); double db = 1.0; var dbE = exps.Select(exp => exp.Evaluate(scope)) .Where(v => v is SSFloat); if (dbE.Count() > 0) { db = dbE.Cast <SSFloat>(). Aggregate((exp, b) => exp * b); } Int64 i = 1; var iE = exps.Select(exp => exp.Evaluate(scope)) .Where(exp => exp is SSInteger); if (iE.Count() > 0) { i = iE.Cast <SSInteger>(). Aggregate((exp, b) => exp * b); } return(-0.0000001 < db && db < 0.0000001 ? i : db *i); }
public static SSObject Sub(SSExpression[] exps, SSScope scope) { var first = exps[0].Evaluate(scope); //var b = first is SSFloat ? (SSFloat)first : (SSInteger)first; if (exps.Length == 1) { return(first is SSFloat ? -(SSFloat)first : -(SSInteger)first); } else { var sec = Add(exps.Skip(1), scope); if (sec is SSFloat || first is SSFloat) { return((first as SSNumber).FloatVal() - (sec as SSFloat).FloatVal()); } else { return((SSInteger)first - (SSInteger)sec); } //if (sec is SSFloat) // return b - sec; //var c = sec is SSFloat ? (SSFloat)sec : (SSInteger)sec; //return b - c; } }
/// <summary> /// /// (set-at! p-str 4 'x') /// </summary> public static SSObject SetAt(SSExpression[] exps, SSScope scope) { SSObject newval = null; (exps.Length == 3 && (newval = (exps[2]).Evaluate(scope)) != null ).OrThrows("Expect a container, an integer and a new NSObject"); var nv = exps[1].Evaluate(scope); var cont = exps[0].Evaluate(scope); if (cont is SSList) { ((SSList)cont).Val[(SSInteger)nv] = newval; } else if (cont is SSString) { var b = new StringBuilder((SSString)cont); b[(SSInteger)nv] = (SSChar)newval; cont.Replace(b.ToString()); } else if (cont is SSDict) { ((SSDict)cont).Val[nv] = newval; } return(newval); }
public static SSObject StrToLs(SSExpression[] exps, SSScope scope) { (exps.Length == 1).OrThrows("expect one parameter"); var v = ((SSString)exps.Evaluate(scope).First()); return(new SSList(v.Val.Select(a => new SSChar(a)))); }
/// <summary> /// (hash any-thing) /// </summary> public static SSObject Hash(SSExpression[] exps, SSScope scope) { int h = 1; exps.Evaluate(scope).ForEach(a => h = 31 * h + a.GetHashCode()); return(h); }
/// <summary> /// if () /// () /// elif () /// () /// () /// </summary> /// <param name="exps"></param> /// <param name="scope"></param> /// <returns></returns> public static SSObject If(SSExpression[] exps, SSScope scope) { if (exps[0].Evaluate(scope) as SSBool) { return(exps[1].Evaluate(scope)); } else if (exps[2].Token.Type == TokenType.ElIf) { var idx = 2; do { idx++; if (exps[idx].Evaluate(scope) as SSBool) { return(exps[++idx].Evaluate(scope)); } idx += 2; } while (exps[idx].Token.Type == TokenType.ElIf); return(exps[idx].Evaluate(scope)); } else { return(exps[2].Evaluate(scope)); } }
public static SSInteger BitOp(this SSExpression[] exps, SSScope scope, Func <SSInteger, SSInteger> ops) { (exps.Length == 1).OrThrows("expect one or more parameter"); var ret = exps.Evaluate <SSInteger>(scope).First(); return(ops(ret)); }
public static SSObject Op <T>(this SSExpression[] exps, SSScope scope, Func <T, SSObject> ops) where T : SSObject { (exps.Length == 1).OrThrows("expect one parameter"); var ret = exps.Evaluate <T>(scope).First(); return(ops(ret)); }
public static SSObject Func(SSExpression[] exps, SSScope scope) { var parameters = exps[0].Children.Select(exp => exp.Token).ToArray(); var body = exps[1]; var nsc = new SSScope(scope); return(new SSFunction(body, parameters, nsc)); }
public static SSObject Power(SSExpression[] exps, SSScope scope) { (exps.Length == 2).OrThrows("expect 2 parameters, get " + exps.Length); var nums = exps.Select(o => o.Evaluate(scope)).ToArray(); var i1 = (SSNumber)nums[0]; //is SSFloat ? (SSFloat)nums[0] : (SSInteger)nums[0]; var i2 = (SSNumber)nums[1]; // is SSFloat ? (SSFloat)nums[1] : (SSInteger)nums[1]; return(Math.Pow(i1.FloatVal(), i2.FloatVal())); }
public static SSList RetrieveSList(this SSExpression[] expressions, SSScope scope, String operationName) { SSList list = null; (expressions.Length == 1 && (list = (expressions[0].Evaluate(scope) as SSList)) != null) .OrThrows("[" + operationName + "] must apply to a list"); return(list); }
public SSScope(SSScope parent) { this.Parent = parent; this.VariableTable = new Dictionary <string, SSObject>(32); this.Output = parent == null ? Console.Out : parent.Output; this.Output = Output ?? Console.Out; this.Rand = parent == null ? null : parent.Rand; this.Rand = Rand ?? new Random(); }
public static SSObject Ops <T>(this SSExpression[] exps, SSScope scope, Func <T, T, SSObject> ops) where T : SSObject { (exps.Length == 2).OrThrows("expect two parameters"); var ret = exps.Evaluate <T>(scope); var b0 = ret.ElementAt(0); var b1 = ret.ElementAt(1); return(ops(b0, b1)); }
public static SSInteger BitOps(this SSExpression[] exps, SSScope scope, Func <SSInteger, SSInteger, SSInteger> ops) { (exps.Length == 2).OrThrows("expect one or more parameter"); var ret = exps.Evaluate <SSInteger>(scope); var b0 = ret.ElementAt(0); var b1 = ret.ElementAt(1); return(ops(b0, b1)); }
public static SSObject Error(SSExpression[] exps, SSScope scope) { var ret = exps.Evaluate(scope); if (ret != null) { ret.ForEach(a => scope.Output.WriteLine(a)); throw new SystemException(ret.Last().ToString()); } throw new SystemException("Error"); }
public SSFunction Update(SSObject[] arguments) { var existingArguments = this.Parameters.Select(p => this.Scope.FindInTop(p.Value)) .Where(obj => obj != null); var newArguments = existingArguments.Concat(arguments).ToArray(); SSScope newScope = this.Scope.Parent.SpawnScopeWith(this.Parameters, newArguments); return(new SSFunction(this.Body, this.Parameters, newScope)); }
public SSScope SpawnScopeWith(CodeToken[] toks, SSObject[] values) { (toks.Length >= values.Length).OrThrows("Too many arguments."); var scope = new SSScope(this); for (var i = 0; i < values.Length; i++) { scope.VariableTable.Add(toks[i].Value, values[i]); } return(scope); }
public static SSObject Require(SSExpression[] exps, SSScope scope) { exps.ForEach(a => { var name = a.Token.Value; if (!scope.VariableTable.ContainsKey(name) && !SSScope.BuiltinFunctions.ContainsKey(name)) { throw new KeyNotFoundException("cannot find [{0}] in local scope and global scope".Fmt(name)); } }); return(true); }
public static SSScope LoadLib(this SSScope scope, string lib) { scope.Output.WriteLine(">>> Loading Library [{0}] ...".Fmt(lib)); using (var sr = new StreamReader(lib)) { string code = null; if ((code = sr.ReadToEnd()).NotEmpty()) { scope.BulkEval(code); } } return(scope); }
public static SSObject Swap(SSExpression[] exps, SSScope scope) { var na = exps[0].Token.Value; var va = exps[0].Evaluate(scope); var nb = exps[1].Token.Value; var vb = exps[1].Evaluate(scope); scope.Undefine(nb); scope.Undefine(na); scope.Define(nb, va); scope.Define(na, vb); return(true); }
/// <summary> /// try{ /// value /// } /// catch(ex){ /// } /// </summary> public static SSObject TryCatch(SSExpression[] exps, SSScope scope) { try { return(exps[0].Evaluate(scope)); } catch (Exception ex) { var tok = exps[2].Children[0].Token; scope.Define(tok.Value, ex.Message); return(exps[3].Evaluate(scope)); } }
/// <summary> /// set name value /// </summary> public static SSObject Set(SSExpression[] exps, SSScope scope) { (exps.Length == 2).OrThrows("expect two parameters"); var b0 = exps[0]; var b1 = exps[1].Evaluate(scope); if (!b0.Evaluate(scope).Replace(b1)) { scope.Undefine(b0.Token.Value); scope.Define(b0.Token.Value, b1); } return(b1); }
public SSObject Remove(String name) { SSScope current = this; while (current != null) { if (current.VariableTable.Remove(name)) { return(true); } current = current.Parent; } throw new Exception(name + " is undefined."); }
/// <summary> /// null? list null? str /// </summary> public static SSObject IsNull(SSExpression[] exps, SSScope scope) { (exps.Length == 1).OrThrows("expect one list or string"); var v = exps[0].Evaluate(scope); if (v is SSList) { return(((SSList)v).Length < 1); } else { return(((SSString)v).Val.Length < 1); } }
/// <summary> /// (switch (val) /// case (a) (b) /// case (c) (d) /// /// ) /// </summary> public static SSObject Switch(SSExpression[] exps, SSScope scope) { var cond = exps[0].Evaluate(scope); //var rest = exps.Skip(1); for (int i = 2; i < exps.Count(); i += 3) { if (exps[i].Evaluate(scope).Eq(cond)) { return(exps[++i].Evaluate(scope)); } } return(exps.Last().Evaluate(scope)); }
public static SSObject While(SSExpression[] exps, SSScope scope) { (exps.Length == 2).OrThrows("expect two parameters"); SSObject ret = null; while ((SSBool)exps[0].Evaluate(scope)) { ret = exps[1].Evaluate(scope); if (ret == SSSignal.Break) { break; } } return(ret); }
/// <summary> /// (length a-list) || (length a-str) /// </summary> public static SSObject Length(SSExpression[] exps, SSScope scope) { //nsexps.Evaluate<NSList>(scope).First().Length (exps.Length == 1).OrThrows("expect one parameter"); var v = exps.Evaluate(scope).First(); if (v is SSList) { return(((SSList)v).Length); } else { return(((SSString)v).Val.Length); } }
public static SSObject Abs(SSExpression[] exps, SSScope scope) { //(exps.Length == 2).OrThrows("expect 2 parameters, get " + exps.Length); var ret = exps.Evaluate(scope).First(); if (ret is SSFloat) { return(Math.Abs((SSFloat)ret)); } else { return(Math.Abs((SSInteger)ret)); } //return ret is SSFloat ? Math.Abs((SSFloat)ret) : Math.Abs((SSInteger)ret); }
public static SSObject Loop(SSExpression[] exps, SSScope scope) { (exps.Length == 2).OrThrows("expect two parameters"); int num = exps[0].Evaluate(scope) as SSInteger; SSObject ret = null; while (num-- != 0) { ret = exps[1].Evaluate(scope); if (ret == SSSignal.Break) { break; } } return(ret); }