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 AppendLines(Evaluator eval, StackFrame frame) { var(path, list) = StructureUtils.Split2(frame.args); if (path == null || !path.IsString) { throw new ArgumentException("First argument must be string!"); } string file = (string)path.value; if (list == null || !list.IsPair) { throw new ArgumentException("Second argument must be list of strings!"); } List <string> lines = new List <string>(); for (Atom iter = list; iter != null; iter = iter.next) { Atom line = iter.atom; if (line == null || !line.IsString) { throw new ArgumentException("Second argument must be list of strings!"); } lines.Add((string)line.value); } File.AppendAllLines(file, lines, System.Text.Encoding.UTF8); eval.Return(null); }
private static object BitOperation(Atom list, Func <object, object, object> handle) { object result = list.atom.value; StructureUtils.Each(list.next, atom => { result = handle(result, atom.value); }); return(result); }
private static bool CheckLogic(Atom list, Func <object, object, bool> check) { bool result = true; StructureUtils.Each2(list, (a, b) => { result &= check(a.value, b.value); }); return(result); }
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); }
private static void Reverse(Evaluator eval, StackFrame frame) { var args = frame.args; var list = StructureUtils.CloneList((Atom)args?.value); var reversedList = StructureUtils.Reverse(list); eval.Return(reversedList); }
// TODO: Осознать, что тут происходит private static void TableEach(Evaluator eval, StackFrame frame) { var args = frame.args; var(dict, func) = StructureUtils.Split2(args); Context dictionary = GetDictionary(dict); Function proc = func?.value as Function; if (dictionary == null) { throw new ArgumentException("First argument must be table!"); } if (proc == null) { throw new ArgumentException("Second argument must be procedure!"); } switch (frame.state.value) { case "-eval-sexp-body-": var list = dictionary .Select(pair => StructureUtils.List(new Atom(AtomType.String, pair.Key), pair.Value)) .ToArray(); frame.temp1 = StructureUtils.List(list); frame.state = new Atom("-built-in-table-each-"); break; case "-built-in-table-each-": if (eval.HaveReturn()) { frame.temp2 = StructureUtils.BuildListContainer(frame.temp2, eval.TakeReturn()); } if (frame.temp1 != null) { var pair = frame.temp1.atom; frame.temp1 = frame.temp1.next; var newFrame = eval.CreateFrame( "-eval-sexp-args-", new Atom(func, pair), frame.context); newFrame.function = func; newFrame.args = frame.temp1.atom; } else { eval.SetReturn(null); frame.state = new Atom("-eval-sexp-body-"); } break; } }
private static void Eval(Evaluator eval, StackFrame frame) { if (!eval.HaveReturn()) { var(expression, ctxAtom) = StructureUtils.Split2(frame.args); Context ctx = ctxAtom?.value as Context ?? frame.context.value as Context; eval.CreateFrame("-eval-", expression, ctx); return; } eval.CloseFrame(); }
public static void Contains(Evaluator eval, StackFrame frame) { var(strArg, subArg) = StructureUtils.Split2(frame.args); // if (!strArg.IsString) throw new ArgumentException("first argument must be string!"); // if (!subArg.IsString) throw new ArgumentException("second argument must be string!"); string str = strArg.value as string; string sub = subArg.value as string; eval.Return(str.Contains(sub) ? Atoms.TRUE : Atoms.FALSE); }
public static void GetChar(Evaluator eval, StackFrame frame) { var(strArg, num) = StructureUtils.Split2(frame.args); // if (!str.IsString) throw new ArgumentException("Argument must be string!"); // if (!num.IsNumber) throw new ArgumentException("Argument must be number!"); string str = strArg.value as string; int index = Convert.ToInt32(num.value); char res = str[index]; eval.Return(new Atom(AtomType.Number, res)); }
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 Atom Handle(List <Token> tokens) { Atom list = null; int offset = 0; int length = tokens.Count; while (offset < length) { Atom node = ReadNode(tokens, ref offset, true); list = StructureUtils.BuildListContainer(list, node); } return(list?.atom); }
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)); }
public static void Neq(Evaluator eval, StackFrame frame) { var args = frame.args; // Особый механизм - сравнение всего for (Atom iter = args; iter != null && iter.next != null; iter = iter.next) { if (StructureUtils.Compare((Atom)iter.value, (Atom)iter.next.value)) { eval.Return(Atoms.FALSE); return; } } eval.Return(Atoms.TRUE); }
private static void TableImportAll(Evaluator eval, StackFrame frame) { var(src, dst) = StructureUtils.Split2(frame.args); if (dst == null || dst.IsPair) { dst = frame.context.atom; } var srcCtx = GetDictionary(src); var dstCtx = GetDictionary(dst); ContextUtils.ImportAllSymbols(srcCtx, dstCtx); eval.Return(null); }
private static void ReadDirectory(Evaluator eval, StackFrame frame) { Atom args = frame.args; Atom path = args?.atom; if (path == null || !path.IsString) { throw new ArgumentException("Path must be string!"); } string directory = (string)path.value; Atom pattern = args?.next?.atom; Atom mode = args?.next?.next?.atom; SearchOption option = ArgUtils.GetEnum <SearchOption>(mode, 3); string[] dirs = null; if (pattern == null) { dirs = Directory.GetDirectories(directory); } else { dirs = Directory.GetDirectories(directory, (string)pattern.value, option); } string[] files = null; if (pattern == null) { files = Directory.GetFiles(directory); } else { files = Directory.GetFiles(directory, (string)pattern.value, option); } Atom[] elements = new Atom[dirs.Length + files.Length]; for (int i = 0; i < dirs.Length; i++) { elements[i] = new Atom(AtomType.String, dirs[i]); } for (int i = 0; i < files.Length; i++) { elements[i + dirs.Length] = new Atom(AtomType.String, files[i]); } eval.Return(StructureUtils.List(elements)); }
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 SetCdr(Evaluator eval, StackFrame frame) { var args = frame.args; Atom list = (Atom)args?.value; if (list.type != AtomType.Pair) { throw new ArgumentException("Argument must be List!"); } if (StructureUtils.Compare(list, Atoms.EMPTY)) { throw new ArgumentException("Can't modyficate base EMPTY list!"); } list.next = (Atom)args.next.value; eval.Return(list.next); }
private static void Preprocessor(Evaluator eval, StackFrame frame) { var args = frame.args; Atom vars = StructureUtils.CloneTree((Atom)args?.value); Atom body = StructureUtils.CloneTree(args?.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, "preprocessor"); closure.EvalArgs = false; closure.EvalResult = false; eval.Return(new Atom(AtomType.Function, closure)); }
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 Apply(Evaluator eval, StackFrame frame) { if (eval.HaveReturn()) { var args = frame.args; Atom func = args.atom; Atom rest = StructureUtils.CloneList(args.next.atom); Function proc = func?.value as Function; if (proc == null) { throw new ArgumentException("First argument must be procedure!"); } eval.CreateFrame("-eval-", new Atom(func, rest), frame.context); return; } eval.CloseFrame(); }
private static void ReadLines(Evaluator eval, StackFrame frame) { Atom path = frame.args?.atom; if (path == null || !path.IsString) { throw new ArgumentException("Path must be string!"); } string file = (string)path.value; string[] lines = File.ReadAllLines(file, System.Text.Encoding.UTF8); Atom[] atoms = new Atom[lines.Length]; for (int i = 0; i < lines.Length; i++) { atoms[i] = new Atom(AtomType.String, lines[i]); } eval.Return(StructureUtils.List(atoms)); }
private static void AppendText(Evaluator eval, StackFrame frame) { var(path, text) = StructureUtils.Split2(frame.args); if (path == null || !path.IsString) { throw new ArgumentException("First argument must be string!"); } string file = (string)path.value; if (text == null || !text.IsString) { throw new ArgumentException("Second argument must be string!"); } string data = (string)text.value; File.AppendAllText(file, data, System.Text.Encoding.UTF8); eval.Return(null); }
private static void Append(Evaluator eval, StackFrame frame) { // (define append (lambda [list item] // (set-cdr! (last list) item) list // )) var args = frame.args; Atom list1 = StructureUtils.CloneList(args.atom); Atom list2 = StructureUtils.CloneList(args.next.atom); if (list2 == null || list2.IsEmpty) { eval.Return(list1); return; } if (list1 == null || list1.IsEmpty) { eval.Return(list2); return; } if (!list1.IsPair) { throw new ArgumentException("Argument must be list!"); } Atom pair = list1; while ( pair.IsPair && pair.next != null) { pair = pair.next; } pair.next = list2; eval.Return(list1); }
private static void Contains(Evaluator eval, StackFrame frame) { var args = frame.args; Atom list = args?.atom; Atom value = args?.next?.atom; if (list == null || !list.IsPair) { throw new ArgumentException("First argument must be list!"); } bool contains = false; for (Atom iter = list; iter != null; iter = iter.next) { if (StructureUtils.Compare(value, iter.atom)) { contains = true; break; } } eval.Return(contains ? Atoms.TRUE : Atoms.FALSE); }
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)); }
public static void Split(Evaluator eval, StackFrame frame) { var(strArg, splits) = StructureUtils.Split2(frame.args); // if (!strArg.IsString) throw new ArgumentException("first argument must be string!"); // if (!splits.IsString) throw new ArgumentException("second argument must be string!"); string str = strArg.value as string; string spl = splits.value as string; string[] list = str.Split(new string[] { spl }, StringSplitOptions.RemoveEmptyEntries); Atom head, tail; head = tail = new Atom(); tail.value = new Atom(AtomType.String, list[0]); for (int i = 1; i < list.Length; i++) { tail = tail.next = new Atom(); tail.value = new Atom(AtomType.String, list[0]); } eval.Return(head); }
public Atom Evaluate(Atom atom, Context current_context, string startState = null) { _retValue = null; _haveReturn = false; Stack.CreateFrame(startState ?? "-eval-", atom, current_context); Console.WriteLine("Start evaluation"); while (Stack.stack.Count > 0) { if (ErrorMessage != null) { Console.WriteLine($"[ERROR] {ErrorMessage}"); ErrorMessage = null; return(null); } // Console.WriteLine($"RetValue: {_retValue}"); // Stack.Dump(1); //Thread.Sleep(50); Function func; StackFrame frame = Stack.TopFrame; switch (frame.state.value) { case "-eval-": if (frame.expression.IsPair) { frame.state = new Atom("-eval-sexp-head-"); continue; } if (frame.expression.IsSymbol) { var name = (string)frame.expression.value; try { SetReturn(ContextUtils.Get((Context)frame.context.value, name)); } catch (BombardoException e) { Console.WriteLine($"[ERROR] {e}"); return(null); } CloseFrame(); continue; } SetReturn(frame.expression); CloseFrame(); continue; case "-eval-each-": if (HaveReturn()) { frame.temp1 = StructureUtils.BuildListContainer(frame.temp1, TakeReturn()); } if (frame.expression != null) { var subExpression = frame.expression.atom; frame.expression = frame.expression.next; Stack.CreateFrame("-eval-", subExpression, frame.context); continue; } SetReturn(frame.temp1.atom); // frame.temp1 = null; CloseFrame(); continue; case "-eval-block-": if (HaveReturn()) { frame.temp1 = TakeReturn(); } if (frame.expression != null) { var subExpression = frame.expression.atom; frame.expression = frame.expression.next; Stack.CreateFrame("-eval-", subExpression, frame.context); continue; } SetReturn(frame.temp1); // frame.temp1 = null; CloseFrame(); continue; case "-eval-sexp-head-": if (!HaveReturn()) { var head = frame.expression.atom; Stack.CreateFrame("-eval-", head, frame.context); continue; } frame.function = TakeReturn(); if (!frame.function.IsFunction) { Console.WriteLine($"[ERROR] Head is not function: {frame.function}"); return(null); } frame.state = new Atom("-eval-sexp-args-"); continue; case "-eval-sexp-args-": if (!HaveReturn()) { func = (Function)frame.function.value; if (func.EvalArgs && frame.expression.next != null) { Stack.CreateFrame("-eval-each-", frame.expression.next, frame.context); continue; } frame.args = frame.expression.next; frame.state = new Atom("-eval-sexp-body-"); continue; } frame.args = TakeReturn(); frame.state = new Atom("-eval-sexp-body-"); continue; case "-eval-sexp-body-": func = (Function)frame.function.value; if (!HaveReturn()) { func.Apply(this, frame); continue; } if (func.EvalResult) { frame.state = new Atom("-eval-sexp-result-"); frame.temp1 = TakeReturn(); continue; } CloseFrame(); continue; case "-eval-sexp-result-": if (!HaveReturn()) { Stack.CreateFrame("-eval-", frame.temp1, frame.context); continue; } SetReturn(frame.temp1); frame.temp1 = null; CloseFrame(); continue; } // Ни один из указанных стейтов, значит: // Либо это стейты функции и тогда её надо вызывать if (frame.function != null) { func = (Function)frame.function.value; func.Apply(this, frame); continue; } // Либо если нет функции - то это ошибка интерпретации SetError($"Wrong evaluation state: {frame.state.value}"); } if (HaveReturn()) { return(TakeReturn()); } return(null); }
private static void Write(Evaluator eval, StackFrame frame) { var(stream, value) = StructureUtils.Split2(frame.args); if (stream.type != AtomType.Native) { throw new ArgumentException("Argument must be stream!"); } StreamWriter writer = stream?.value as StreamWriter; if (writer == null) { throw new ArgumentException("Argument must be stream!"); } if (value == null) { throw new ArgumentException("Second argument can't be null!"); } switch (value.type) { case AtomType.Number: var type = UNumber.NumberType(value?.value); switch (type) { case UNumber.UINT_8: writer.Write(Convert.ToByte(value.value)); break; case UNumber.SINT_8: writer.Write(Convert.ToSByte(value.value)); break; case UNumber.UINT16: writer.Write(Convert.ToUInt16(value.value)); break; case UNumber.SINT16: writer.Write(Convert.ToInt16(value.value)); break; case UNumber._CHAR_: writer.Write(Convert.ToChar(value.value)); break; case UNumber.UINT32: writer.Write(Convert.ToUInt32(value.value)); break; case UNumber.SINT32: writer.Write(Convert.ToInt32(value.value)); break; case UNumber.UINT64: writer.Write(Convert.ToUInt64(value.value)); break; case UNumber.SINT64: writer.Write(Convert.ToInt64(value.value)); break; case UNumber.FLO32: writer.Write(Convert.ToSingle(value.value)); break; case UNumber.FLO64: writer.Write(Convert.ToDouble(value.value)); break; default: writer.Write(value.value); break; } break; default: writer.Write(value.value); break; } eval.Return(null); }