public static IDictionary <Symbol, object> CreateBuiltins(Interpreter interpreter) { var builtins = new Dictionary <Symbol, object>(); builtins[Symbol.FromString("+")] = new NativeProcedure(Utils.MakeVariadic(Add), "+"); builtins[Symbol.FromString("-")] = new NativeProcedure(Utils.MakeVariadic(Minus), "-"); builtins[Symbol.FromString("*")] = new NativeProcedure(Utils.MakeVariadic(Multiply), "*"); builtins[Symbol.FromString("/")] = new NativeProcedure(Utils.MakeVariadic(Divide), "/"); builtins[Symbol.FromString("=")] = NativeProcedure.Create <double, double, bool>((x, y) => x == y, "="); builtins[Symbol.FromString("<")] = NativeProcedure.Create <double, double, bool>((x, y) => x < y, "<"); builtins[Symbol.FromString("<=")] = NativeProcedure.Create <double, double, bool>((x, y) => x <= y, "<="); builtins[Symbol.FromString(">")] = NativeProcedure.Create <double, double, bool>((x, y) => x > y, ">"); builtins[Symbol.FromString(">=")] = NativeProcedure.Create <double, double, bool>((x, y) => x >= y, ">="); builtins[Symbol.FromString("eq?")] = NativeProcedure.Create <object, object, bool>((x, y) => object.ReferenceEquals(x, y), "eq?"); builtins[Symbol.FromString("equal?")] = NativeProcedure.Create <object, object, bool>(EqualImpl, "equal?"); builtins[Symbol.FromString("boolean?")] = NativeProcedure.Create <object, bool>(x => x is bool, "boolean?"); builtins[Symbol.FromString("num?")] = NativeProcedure.Create <object, bool>(x => x is int || x is double, "num?"); builtins[Symbol.FromString("string?")] = NativeProcedure.Create <object, bool>(x => x is string, "string?"); builtins[Symbol.FromString("symbol?")] = NativeProcedure.Create <object, bool>(x => x is Symbol, "symbol?"); builtins[Symbol.FromString("list?")] = NativeProcedure.Create <object, bool>(x => x is List <object>, "list?"); builtins[Symbol.FromString("map")] = NativeProcedure.Create <ICallable, List <object>, List <object> >((func, ls) => ls.Select(x => func.Call(new List <object> { x })).ToList()); builtins[Symbol.FromString("reverse")] = NativeProcedure.Create <List <object>, List <object> >(ls => ls.Reverse <object>().ToList()); builtins[Symbol.FromString("range")] = new NativeProcedure(RangeImpl, "range"); builtins[Symbol.FromString("apply")] = NativeProcedure.Create <ICallable, List <object>, object>((proc, args) => proc.Call(args), "apply"); builtins[Symbol.FromString("list")] = new NativeProcedure(args => args, "list"); builtins[Symbol.FromString("list-ref")] = NativeProcedure.Create <List <object>, int, object>((ls, idx) => ls[idx]); builtins[Symbol.FromString("length")] = NativeProcedure.Create <List <object>, int>(list => list.Count, "length"); builtins[Symbol.FromString("car")] = NativeProcedure.Create <List <object>, object>(args => args[0], "car"); builtins[Symbol.FromString("cdr")] = NativeProcedure.Create <List <object>, List <object> >(args => args.Skip(1).ToList(), "cdr"); builtins[Symbol.CONS] = NativeProcedure.Create <object, List <object>, List <object> >((x, ys) => Enumerable.Concat(new[] { x }, ys).ToList(), "cons"); builtins[Symbol.FromString("not")] = NativeProcedure.Create <bool, bool>(x => !x, "not"); builtins[Symbol.APPEND] = NativeProcedure.Create <List <object>, List <object>, List <object> >((l1, l2) => Enumerable.Concat(l1, l2).ToList(), "append"); builtins[Symbol.FromString("null")] = NativeProcedure.Create <object>(() => (object)null, "null"); builtins[Symbol.FromString("null?")] = NativeProcedure.Create <object, bool>(x => x is List <object> && ((List <object>)x).Count == 0, "null?"); builtins[Symbol.FromString("assert")] = new NativeProcedure(AssertImpl, "assert"); builtins[Symbol.FromString("load")] = NativeProcedure.Create <string, None>(filename => LoadImpl(interpreter, filename), "load"); builtins[Symbol.FromString("call/cc")] = NativeProcedure.Create <ICallable, object>(Continuation.CallWithCurrentContinuation, "call/cc"); return(builtins); }
public static object CallWithCurrentContinuation(ICallable fc1) { var ccc = new Continuation { Stack = new StackTrace(), Thread = Thread.CurrentThread }; try { var exitproc = NativeProcedure.Create <object, object>(v => { var f1 = new StackTrace().GetFrames(); var c1 = ccc.Stack.GetFrames(); var offset = f1.Length - c1.Length; if (ccc.Thread == Thread.CurrentThread) { for (int i = c1.Length - 1; i >= 0; i--) { if (c1[i].GetMethod() != f1[i + offset].GetMethod()) { throw new NotImplementedException("not supported, continuation called outside dynamic extent"); } } } ccc.Value = v; throw ccc; }); return(fc1.Call(new List <object> { exitproc })); } catch (Continuation c) { if (ccc == c) { return(c.Value); } else { throw; } } }
public static void Main(string[] args) { Interpreter.CreateSymbolTableDelegate extension = _ => new Dictionary <Symbol, object>() { { Symbol.FromString("say-hi"), NativeProcedure.Create <Function>(() => name => $"Hello {name}!") }, { Symbol.FromString("truncate-string"), NativeProcedure.Create <int, Function>(len => input => ((string)input).Substring(0, len)) }, { Symbol.FromString("dump"), NativeProcedure.Create <object>(() => Symbol.AllSymbols()) }, { Symbol.FromString("print"), NativeProcedure.Create <object, object>((arg) => Print(arg)) }, { Symbol.FromString("typeof"), NativeProcedure.Create <object, object>((arg) => { if (null == arg) { return(null); } return(arg.GetType()); }) } }; // TODO: math /* * 1 三角函数 * double sin (double x); x的正弦值 * double cos (double x); x的余弦值 * double tan (double x); x的正切值 * * 2 反三角函数 * double asin (double x); 结果介于[-PI/2, PI/2],x值域为[-1,1] * double acos (double x); 结果介于[0, PI],x值域为[-1,1] * double atan (double x); 反正切(主值), 结果介于[-PI/2, PI/2] * double atan2 (double y, double x); 反正切(整圆值), 结果介于[-PI, PI] * * 3 双曲三角函数 * double sinh (double x); x的双曲正弦值 * double cosh (double x); x的双曲余弦值 * double tanh (double x); x的双曲正切值 * * 4 指数与对数 * double exp (double x); 幂函数e^x * double pow (double x, double y); x^y,如果x=0且y<=0,或者x<0且y不是整型数,将产生定义域错误 * double sqrt (double x); x的平方根,其中x>=0 * double log (double x); 以e为底的对数,自然对数,x>0 * double log10 (double x); 以10为底的对数,x>0 * * 5 取整 * double ceil (double x); 取上整 * double floor (double x); 取下整 * * 6 绝对值 * double fabs (double x); x的绝对值 * * 7 标准化浮点数 * double frexp (double x, int *exp); 标准化浮点数, x = f * 2^exp, 已知x求f, exp ( x介于[0.5, 1] )并返回f值 * double ldexp (double x, int exp); 与frexp相反, 已知x, exp求x*2^exp * * 8 取整与取余 * double modf (double x, double *ip); 将参数的整数部分通过指针回传, 返回小数部分,整数部分保存在*ip中 * double fmod (double x, double y); 返回两参数相除x/y的余数,符号与x相同。如果y为0,则结果与具体的额实现有关。 */ // max, min, abs // TODO: logic(and, or) // TODO: c# Reflection // TODO: string operations (upper, lower, substring, regex) // TODO: hash/dict // TODO: set-car! set-cdr! // TODO: alist // misc: incf decf ++ -- to-delegate // Console.WriteLine("Args: {0}#{1} {2}", args, args.Length, args[0]); if (args.Length > 0 && File.Exists(args[0])) { // evaluate input file's content var file = args[0]; // Console.WriteLine("Eval file ..."); var interpreter = new Interpreter(new[] { extension }, new ReadOnlyFileSystemAccessor()); using (TextReader reader = new StreamReader(file)) { object res = interpreter.Evaluate(reader); Console.WriteLine(Utils.PrintExpr(res)); } } else { // starts the REPL var interpreter = new Interpreter(new[] { extension }, new ReadOnlyFileSystemAccessor()); var headers = new[] { "-----------------------------------------------", "| Schemy - Scheme as a Configuration Language |", "| Press Ctrl-C to exit |", "-----------------------------------------------", }; interpreter.REPL(Console.In, Console.Out, "Schemy> ", headers); } }