private static void Define(Evaluator eval, StackFrame frame) { var(sym, value, context) = StructureUtils.Split3(frame.args); if (sym.type != AtomType.Symbol) { throw new ArgumentException("Definition name must be symbol!"); } if (eval.HaveReturn()) { string name = (string)sym.value; Atom result = eval.TakeReturn(); Context ctx = context?.value as Context ?? frame.context.value as Context; if (result?.value is Closure function) { function.Name = name; } //Console.WriteLine($"DEFINE: '{name}' = '{result}' at -internal-state-{ctx}"); ContextUtils.Define(ctx, result, name); eval.Return(result); return; } eval.CreateFrame("-eval-", value, frame.context); frame.state = Atoms.INTERNAL_STATE; }
private static void Open(Evaluator eval, StackFrame frame) { var(path, accessType, modeType) = StructureUtils.Split3(frame.args); if (path == null || !path.IsString) { throw new ArgumentException("Path must be string!"); } string file = (string)path.value; FileAccess access = ArgUtils.GetEnum <FileAccess>(accessType, 1, FileAccess.Read); FileMode mode = ArgUtils.GetEnum <FileMode>(modeType, 2, FileMode.Open); if (access == FileAccess.Read) { StreamReader reader = new StreamReader(File.Open(file, mode, access)); eval.Return(new Atom(AtomType.Native, reader)); return; } if (access == FileAccess.Write) { StreamWriter writer = new StreamWriter(File.Open(file, mode, access)); eval.Return(new Atom(AtomType.Native, writer)); return; } eval.Return(null); }
public static void Substr(Evaluator eval, StackFrame frame) { var(strArg, starts, length) = StructureUtils.Split3(frame.args); // if (!strArg.IsString) throw new ArgumentException("first argument must be string!"); // if (!starts.IsNumber) throw new ArgumentException("second argument must be string!"); // if (!length.IsNumber) throw new ArgumentException("third argument must be string!"); string str = strArg.value as string; string res = str.Substring((int)starts.value, (int)length.value); eval.Return(new Atom(AtomType.String, res)); }
private static void Filter(Evaluator eval, StackFrame frame) { (var list, var proc, var skip) = StructureUtils.Split3(frame.args); bool skipNull = (bool?)skip?.value ?? false; switch (frame.state.value) { case "-eval-sexp-body-": frame.temp1 = list; frame.state = new Atom("-built-in-map-"); break; case "-built-in-map-": if (eval.HaveReturn()) { var pred = eval.TakeReturn(); bool add = (bool?)pred?.value ?? false; if (add) { frame.temp2 = StructureUtils.BuildListContainer(frame.temp2, frame.temp3); } } if (frame.temp1 != null) { while (skipNull && frame.temp1.atom == null) { frame.temp1 = frame.temp1.next; } var subExpression = frame.temp1.atom; frame.temp3 = subExpression; frame.temp1 = frame.temp1.next; subExpression = new Atom(subExpression, null); frame.temp1 = frame.temp1.next; var newFrame = eval.CreateFrame( "-eval-sexp-args-", new Atom(proc, subExpression), frame.context); newFrame.function = proc; newFrame.args = subExpression; } else { eval.SetReturn(frame.temp2.atom); frame.state = new Atom("-eval-sexp-body-"); } break; } }
public static void Replace(Evaluator eval, StackFrame frame) { var(strArg, subArg, newArg) = StructureUtils.Split3(frame.args); // if (!strArg.IsString) throw new ArgumentException("first argument must be string!"); // if (!subArg.IsString) throw new ArgumentException("second argument must be string!"); // if (!newArg.IsString) throw new ArgumentException("third argument must be string!"); string str = strArg.value as string; string sub = subArg.value as string; string n_w = newArg.value as string; string res = str.Replace(sub, n_w); eval.Return(new Atom(AtomType.String, res)); }
private static void Each(Evaluator eval, StackFrame frame) { (var list, var proc, var skip) = StructureUtils.Split3(frame.args); bool skipNull = (bool?)skip?.value ?? false; switch (frame.state.value) { case "-eval-sexp-body-": frame.temp1 = list; frame.state = new Atom("-built-in-each-"); break; case "-built-in-each-": if (eval.HaveReturn()) { frame.temp2 = StructureUtils.BuildListContainer(frame.temp2, eval.TakeReturn()); } if (frame.temp1 != null) { while (skipNull && frame.temp1.atom == null) { frame.temp1 = frame.temp1.next; } var subExpression = new Atom(frame.temp1.atom, null); var newFrame = eval.CreateFrame( "-eval-sexp-body-", StructureUtils.List(proc, frame.temp1.atom), frame.context); newFrame.function = proc; newFrame.args = subExpression; frame.temp1 = frame.temp1.next; } else { eval.SetReturn(null); frame.state = new Atom("-eval-sexp-body-"); } break; } }
private static void TableImport(Evaluator eval, StackFrame frame) { var(src, dst, names) = StructureUtils.Split3(frame.args); if (names == null && dst.IsPair) { names = dst; dst = frame.context.atom; } var srcCtx = GetDictionary(src); var dstCtx = GetDictionary(dst); string[] nameList = StructureUtils.ListToStringArray(names, "TABLE"); ContextUtils.ImportSymbols(srcCtx, dstCtx, nameList); eval.Return(null); }
private static void Syntax(Evaluator eval, StackFrame frame) { var args = frame.args; // [tag before after] var(tag, before, after) = StructureUtils.Split3(args.atom); if (!tag.IsSymbol && !tag.IsString) { throw new ArgumentException("Tag must be string or symbol!"); } if (!before.IsBool) { throw new ArgumentException("Eval args flag must be boolean!"); } if (!after.IsBool) { throw new ArgumentException("Eval result flag must be boolean!"); } Atom vars = StructureUtils.CloneTree(args?.next?.atom); Atom body = StructureUtils.CloneTree(args?.next?.next); if (vars.type != AtomType.Pair && vars.type != AtomType.Symbol) { throw new ArgumentException("Args must be list or symbol!"); } var ctx = frame.context.value as Context; var closure = new Closure(ctx, vars, body, (string)tag.value); closure.EvalArgs = (bool)before.value; closure.EvalResult = (bool)after.value; eval.Return(new Atom(AtomType.Function, closure)); }
private static void If(Evaluator eval, StackFrame frame) { switch (frame.state.value) { case "-eval-sexp-body-": { // (cond BlockA BlockB) (frame.temp1, frame.temp2, frame.temp3) = StructureUtils.Split3(frame.args); frame.state = new Atom("-built-in-if-cond-"); } break; case "-built-in-if-cond-": { if (eval.HaveReturn()) { var condition = eval.TakeReturn(); if (!condition.IsBool) { throw new ArgumentException($"Condition must return boolean atom, but found: {condition}!"); } frame.state = new Atom((bool)condition.value ? "-built-in-if-then-" : "-built-in-if-else-"); } else { eval.CreateFrame("-eval-", frame.temp1, frame.context); } } break; case "-built-in-if-then-": { if (frame.temp2 == null) { throw new ArgumentException($"If statement must have at least one block of code!"); } if (eval.HaveReturn()) { eval.CloseFrame(); break; } eval.CreateFrame("-eval-", frame.temp2, frame.context); } break; case "-built-in-if-else-": frame.state = new Atom("-eval-sexp-body-"); if (eval.HaveReturn()) { eval.CloseFrame(); break; } if (frame.temp3 == null) { eval.Return(null); } else { eval.CreateFrame("-eval-", frame.temp3, frame.context); } break; } }