public Cons MacroProcessing(Cons seq) // TODO { var rseq = new Cons(); foreach (var o in seq.GetIterator()) { var exp = o.Car(); if (exp is Cons) { var op = exp.Car() as Symbol; var arguments = exp.Cdr() as Cons; if (op?.Name == "define-syntax") { DefineMacro(arguments); continue; } else if (Macro.Lookup(op)) { foreach (var o1 in (Macro.Get(op).Expand(arguments)).GetIterator()) { if (o1.Car() is Cons) { rseq.Add(MacroProcessing(o1.Car())); } else { rseq.Add(o1.Car()); } } continue; } rseq.Add(MacroProcessing(exp)); } else { rseq.Add(exp); var rest = o?.Cdr(); if (!(rest is Cons)) { rseq.Add(rest, true); } } } return(rseq); }
private void DefineMacro(Cons cons) { var macroName = cons.Car() as Symbol; var macro = cons.Cdr().Car() as Cons; if ((macro.Car() as Symbol)?.Name == "syntax-rules") { var syntaxRules = BuildSynataxRules(macro.Cdr() as Cons); Macro.Define(macroName, syntaxRules); } else { // unsuported } }
private static SyntaxRules BuildSynataxRules(Cons macro) { var literals = macro.Car() as Cons; var clause = macro.Cdr() as Cons; var ruleItems = new List <SyntaxRuleItem>(); foreach (Cons rule in clause.GetIterator()) { ruleItems.Add(BuildSynataxRule(rule.Car() as Cons)); } return(new SyntaxRules() { Rules = ruleItems.ToArray() }); }
private Cons _lastElement; // optimisation public Cons Add(dynamic o, bool isDot = false) { lock (this) { if (_car == null && _cdr == null) { _car = o; return(this); } if (_lastElement == null) { _lastElement = this; } while (_lastElement._cdr != null) { if (_lastElement._cdr is Cons) { _lastElement = _lastElement._cdr as Cons; } else { break; } } if (isDot) { _lastElement._cdr = o; return(_lastElement); } else { var cndr = new Cons(o); _lastElement._cdr = cndr; _lastElement = cndr; return(cndr); } } }
private Cons Replacer(Cons seq, Dictionary <string, object> vals) { var rSeq = new Cons(); foreach (var o in seq.GetIterator()) { var itm = o.Car(); if (itm is Cons) { itm = Replacer(itm as Cons, vals); } else if (itm is Symbol) { if (vals.ContainsKey((itm as Symbol).Name)) { itm = vals[(itm as Symbol).Name]; } } rSeq.Add(itm); } return(rSeq); }
private static MemoryStream WriteConsSeq(MemoryStream ms, Cons tree, SymbolTable symbolTable) { ms.WriteByte(Codes.Open); foreach (var o in tree.GetIterator()) { WriteItem(ms, o.Car(), symbolTable); var cdr = o.Cdr(); if (cdr is Cons || (cdr == null)) { continue; } ms.WriteByte(Codes.Dot); WriteItem(ms, cdr, symbolTable); } ms.WriteByte(Codes.Close); return(ms); }
public static Cons MExpand(Cons seq) // TODO { var rseq = new Cons(); foreach (var o in seq.GetIterator()) { var exp = o.Car(); if (exp is Cons) { var op = exp.Car() as Symbol; var arguments = exp.Cdr() as Cons; if (op?.Name == "defmacro") { var mName = arguments?.Car().Car() as Symbol; var mArg = arguments?.Car().Cdr() as Cons; var mBody = arguments?.Cdr() as Cons; macro.Define(mName, new Macro(mArg, mBody)); continue; } else if (macro.Lookup(op)) { foreach (var o1 in (macro.Get(op).Expand(arguments)).GetIterator()) { rseq.Add(o1.Car()); } continue; } } rseq.Add(exp); } return(rseq); }
public Macro(Cons args, Cons body) { Args = args.GetIterator().Select(i => i.Car() as Symbol).ToArray(); Body = body; }
public static Operation CompileBegin(Cons seq, Operation next) { var res = Operation.Nop(); return(seq.GetIterator().Reverse().Aggregate(res, (current, exp) => Compile(exp.Car(), current.Cmd == Operation.Comand.Nop ? next : current))); }
public static Cons Read(string str) { var stack = new Stack <Cons>(); var root = new Cons(); stack.Push(root); var state = ReadState.Normal; var isDot = false; // подумать var word = ""; var curent = root; void Set(object o) { curent.Add(o, isDot); isDot = false; } foreach (var c in str) { switch (state) { case ReadState.Normal: { if (c == '(') { if (!string.IsNullOrWhiteSpace(word)) { Set(ParseSymbol(word)); word = ""; } var nod = new Cons(); curent.Add(nod); stack.Push(nod); curent = nod; } else if (c == ')') { if (!string.IsNullOrWhiteSpace(word)) { Set(ParseSymbol(word)); word = ""; } stack.Pop(); if (stack.Any()) { curent = stack.Peek(); } } else if (" \n\r\t\u200B".Any(ch => ch == c)) { if (!string.IsNullOrWhiteSpace(word)) { if (word == ".") { isDot = true; } else { curent.Add(ParseSymbol(word)); } curent = stack.Peek(); word = ""; } } else if (';' == c) { state = ReadState.Comment; } else if (c == '\"') { state = ReadState.String; } else if (c == '#') { state = ReadState.Sharp; } else if (c == '\'') { var nod = new Cons(new Symbol("quote")); Set(nod); curent = nod; } else { word += c; } break; } case ReadState.Comment: { if ("\n\r".Any(ch => ch == c)) { state = ReadState.Normal; } break; } case ReadState.Sharp: { switch (c) { case 'T': case 't': Set(true); state = ReadState.Normal; break; case 'F': case 'f': Set(false); state = ReadState.Normal; break; case '(': { var nod = new Cons(new Symbol("vector")); Set(nod); stack.Push(nod); curent = nod; state = ReadState.Normal; break; } case '\\': // read charter state = ReadState.Charter; break; default: { word += '#' + c; state = ReadState.Normal; break; } } break; } case ReadState.Charter: { Set(c); state = ReadState.Normal; break; } case ReadState.StringEscapeChr: { if (c == 'n') { word += Environment.NewLine; } else { word += c; } state = ReadState.String; break; } case ReadState.String: { // in string if (c == '\"') { Set(word); word = ""; state = ReadState.Normal; } else if (c == '\\') { state = ReadState.StringEscapeChr; } else { word += c; } break; } } } // foreach c if (!string.IsNullOrWhiteSpace(word)) { Set(state == ReadState.String ? word : ParseSymbol(word)); } return(root); }
public static Operation Compile(Cons seq) { //return CompileBegin(MExpand(seq), Operation.Halt()); return(CompileBegin(seq, Operation.Halt())); }
public object EvlExp(Cons seq, bool isWithMacro = true) { return(EvlSeq(new Cons(seq), DefaultEnviroment, isWithMacro)); }
public object EvlSeq(Cons seq, EnviromentFrame env, bool isWithMacro = true) { return(VirtualMashine.Eval(isWithMacro ? Compiler.Compile(MacroSystem.MacroProcessing(seq)) : Compiler.Compile(seq), env)); }
public object EvlSeq(Cons seq) { return(EvlSeq(seq, DefaultEnviroment)); }
public static Cons Read(MemoryStream data) { var stack = new Stack <Cons>(); var root = new Cons(); stack.Push(root); var isDot = false; // подумать var set = new Action <object>(o => { if (isDot) { stack.Peek().SetCdr(o); isDot = false; } else { stack.Peek().Add(o); } }); while (true) { var b = data.ReadByte(); if (b <= 0) { return(root); } // EOS switch (b) { case Codes.Open: { var nod = new Cons(); stack.Peek().Add(nod); stack.Push(nod); break; } case Codes.Close: stack.Pop(); break; case Codes.Dot: isDot = true; break; //FIXED SIZE case Codes.Integer16: set(BitConverter.ToInt16(R(data, 2), 0)); break; case Codes.Integer32: set(BitConverter.ToInt32(R(data, 4), 0)); break; case Codes.Integer64: set(BitConverter.ToInt64(R(data, 8), 0)); break; case Codes.Byte: set(data.ReadByte()); break; case Codes.Bool: set(data.ReadByte() != 0); break; case Codes.Charter8: set((char)data.ReadByte()); break; case Codes.Charter32: set(Encoding.UTF32.GetChars(R(data, 4)).FirstOrDefault()); break; case Codes.Float32: set(BitConverter.ToSingle(R(data, 4), 0)); break; case Codes.Float64: set(BitConverter.ToDouble(R(data, 8), 0)); break; //FLOAT SIZE case Codes.SymbolShort: set(new Symbol(Encoding.UTF8.GetString(R(data, data.ReadByte())))); break; case Codes.SymbolLong: set(new Symbol(Encoding.UTF8.GetString(R(data, BitConverter.ToInt16(R(data, 2), 0))))); break; case Codes.String: set(Encoding.UTF8.GetString(R(data, BitConverter.ToInt32(R(data, 4), 0)))); break; case Codes.StreamShort: set(new MemoryStream(R(data, BitConverter.ToInt32(R(data, 4), 0)))); break; case Codes.Null: set(null); break; case Codes.DateTime: set(DateTime.FromBinary(BitConverter.ToInt64(R(data, 8), 0))); break; case Codes.StreamLong: // TODO throw new Exception("Not supported"); case Codes.SpecialMessage: set(new SpecialMessage(Encoding.UTF8.GetString(R(data, BitConverter.ToInt32(R(data, 4), 0))))); break; case 'Q': { var nod = new Cons(new Symbol("quote")); stack.Peek().Add(nod); stack.Push(nod); break; } case 'V': { var nod = new Cons(new Symbol("vector")); stack.Peek().Add(nod); stack.Push(nod); break; } default: throw new Exception("Bad data format!"); } } }
static Cons Expand(Dictionary <string, object> binds, Cons body) // TODO bind val && arg { var newBody = new Cons(); while (body != null) { var syntax = body.Car() as SyntaxArgument; if (syntax != null) { var nextSym = body.Cdr().Car() as Symbol; if (nextSym != null && nextSym.Name == "...") { if (binds.TryGetValue(syntax.Original.Name, out var val)) { if (newBody.Car() == null && newBody.Cdr() == null && val is Cons) { newBody = binds[syntax.Original.Name] as Cons; // TODO not good } else { newBody.Add(binds[syntax.Original.Name], true); } } body = body.Cdr() as Cons; // skip ellipse } else { newBody.Add(binds[syntax.Original.Name]); } } else { var form = body.Car() as Cons; if (form != null) { newBody.Add(Expand(binds, form)); } else { newBody.Add(body.Car()); } } var next = body.Cdr(); if (next is Cons) { body = body.Cdr() as Cons; } else if (next is SyntaxArgument) // rest { syntax = next as SyntaxArgument; newBody.Add(binds[syntax.Original.Name], true); body = null; } else { body = null; } } return(newBody); }
static Dictionary <string, object> Bind(Cons args, Cons values) { var bind = new Dictionary <string, object>(); object a; object b; var isEllipseMode = false; void SetBind(string key, object value) { if (bind.TryGetValue(key, out var oo)) { if (oo is Cons) { var seq = oo as Cons; seq.Add(value); bind[key] = seq; } else { throw new Exception("error"); } } else { if (isEllipseMode) { bind[key] = new Cons(value); } else { bind[key] = value; } } } while (true) { a = args?.Car(); b = values?.Car(); isEllipseMode = (args?.Cdr().Car() as Symbol)?.Name == "..."; if ((a == null && b == null) || (isEllipseMode && b == null)) { return(bind); } if (a is Symbol && b != null) { var sym = a as Symbol; SetBind(sym.Name, b); } else if (a is Cons && b is Cons) { var bnd = Bind(a as Cons, b as Cons); foreach (var pair in bnd) { SetBind(pair.Key, pair.Value); } } else { return(null); } var nexA = args.Cdr(); if (nexA is Symbol) // rest { var lst = new Cons(); values = values.Cdr() as Cons; while (values != null) { b = values?.Car(); lst.Add(b); values = values.Cdr() as Cons; } SetBind(((Symbol)nexA).Name, lst); } values = values?.Cdr() as Cons; var nextCons = nexA as Cons; var nextSym = nextCons?.Car() as Symbol; if (nextSym?.Name == "...") // repeat for ... { if (values == null) // complete { return(bind); } } else { args = nextCons; } } }
public object ApplyClosure(VirtualMashine.Closure closure, params object[] args) { return(EvlSeq(new Cons(Cons.List(new object[] { closure }.Concat(args ?? new object[0]).ToArray())), false)); }
public static Cons Read(MemoryStream data, SymbolTable symbolTable) { var stack = new Stack <Cons>(); var root = new Cons(); stack.Push(root); var isDot = false; // подумать var set = new Action <object>(o => { if (isDot) { stack.Peek().SetCdr(o); isDot = false; } else { stack.Peek().Add(o); } }); while (true) { var b = data.ReadByte(); if (b <= 0) { return(root); } // EOS switch (b) { case Codes.Open: { var nod = new Cons(); stack.Peek().Add(nod); stack.Push(nod); break; } case Codes.Close: stack.Pop(); break; case Codes.Dot: isDot = true; break; //FIXED SIZE case Codes.Integer16_16: set(BitConverter.ToInt16(R(data, 2), 0)); break; case Codes.Integer16_8: set(BitConverter.ToInt16(R(data, 1, X1), 0)); break; case Codes.Integer16_8_Negate: set(BitConverter.ToInt16(R(data, 1, XN1), 0)); break; case Codes.Integer16_0: set((short)0); break; case Codes.Integer16_16_u: set(BitConverter.ToUInt16(R(data, 2), 0)); break; case Codes.Integer16_8_u: set(BitConverter.ToUInt16(R(data, 1, X1), 0)); break; case Codes.Integer16_0_u: set((ushort)0); break; case Codes.Integer32_32: set(BitConverter.ToInt32(R(data, 4), 0)); break; case Codes.Integer32_24: set(BitConverter.ToInt32(R(data, 3, X1), 0)); break; case Codes.Integer32_24_Negate: set(BitConverter.ToInt32(R(data, 3, XN1), 0)); break; case Codes.Integer32_16: set(BitConverter.ToInt32(R(data, 2, X2), 0)); break; case Codes.Integer32_16_Negate: set(BitConverter.ToInt32(R(data, 2, XN2), 0)); break; case Codes.Integer32_8: set(BitConverter.ToInt32(R(data, 1, X3), 0)); break; case Codes.Integer32_8_Negate: set(BitConverter.ToInt32(R(data, 1, XN3), 0)); break; case Codes.Integer32_0: set(0); break; case Codes.Integer32_32_u: set(BitConverter.ToUInt32(R(data, 4), 0)); break; case Codes.Integer32_24_u: set(BitConverter.ToUInt32(R(data, 3, X1), 0)); break; case Codes.Integer32_16_u: set(BitConverter.ToUInt32(R(data, 2, X2), 0)); break; case Codes.Integer32_8_u: set(BitConverter.ToUInt32(R(data, 1, X3), 0)); break; case Codes.Integer32_0_u: set(0u); break; case Codes.Integer64_64: set(BitConverter.ToInt64(R(data, 8), 0)); break; case Codes.Integer64_56: set(BitConverter.ToInt64(R(data, 7, X1), 0)); break; case Codes.Integer64_56_Negate: set(BitConverter.ToInt64(R(data, 7, XN1), 0)); break; case Codes.Integer64_48: set(BitConverter.ToInt64(R(data, 6, X2), 0)); break; case Codes.Integer64_48_Negate: set(BitConverter.ToInt64(R(data, 6, XN2), 0)); break; case Codes.Integer64_40: set(BitConverter.ToInt64(R(data, 5, X3), 0)); break; case Codes.Integer64_40_Negate: set(BitConverter.ToInt64(R(data, 5, XN3), 0)); break; case Codes.Integer64_32: set(BitConverter.ToInt64(R(data, 4, X4), 0)); break; case Codes.Integer64_32_Negate: set(BitConverter.ToInt64(R(data, 4, XN4), 0)); break; case Codes.Integer64_24: set(BitConverter.ToInt64(R(data, 3, X5), 0)); break; case Codes.Integer64_24_Negate: set(BitConverter.ToInt64(R(data, 3, XN5), 0)); break; case Codes.Integer64_16: set(BitConverter.ToInt64(R(data, 2, X6), 0)); break; case Codes.Integer64_16_Negate: set(BitConverter.ToInt64(R(data, 2, XN6), 0)); break; case Codes.Integer64_8: set(BitConverter.ToInt64(R(data, 1, X7), 0)); break; case Codes.Integer64_8_Negate: set(BitConverter.ToInt64(R(data, 1, XN7), 0)); break; case Codes.Integer64_0: set(0L); break; case Codes.Integer64_64_u: set(BitConverter.ToUInt64(R(data, 8), 0)); break; case Codes.Integer64_56_u: set(BitConverter.ToUInt64(R(data, 7, X1), 0)); break; case Codes.Integer64_48_u: set(BitConverter.ToUInt64(R(data, 6, X2), 0)); break; case Codes.Integer64_40_u: set(BitConverter.ToUInt64(R(data, 5, X3), 0)); break; case Codes.Integer64_32_u: set(BitConverter.ToUInt64(R(data, 4, X4), 0)); break; case Codes.Integer64_24_u: set(BitConverter.ToUInt64(R(data, 3, X5), 0)); break; case Codes.Integer64_16_u: set(BitConverter.ToUInt64(R(data, 2, X6), 0)); break; case Codes.Integer64_8_u: set(BitConverter.ToUInt64(R(data, 1, X7), 0)); break; case Codes.Integer64_0_u: set(0UL); break; case Codes.Byte: set(data.ReadByte()); break; case Codes.BoolTrue: set(true); break; case Codes.BoolFalse: set(false); break; case Codes.Charter8: set((char)data.ReadByte()); break; case Codes.Charter32: set(Encoding.UTF32.GetChars(R(data, 4)).FirstOrDefault()); break; case Codes.Float32: set(BitConverter.ToSingle(R(data, 4), 0)); break; case Codes.Float64: set(BitConverter.ToDouble(R(data, 8), 0)); break; //FLOAT SIZE case Codes.SymbolShort: set(new Symbol(Encoding.UTF8.GetString(R(data, data.ReadByte())))); break; case Codes.SymbolLong: set(new Symbol(Encoding.UTF8.GetString(R(data, BitConverter.ToInt16(R(data, 2), 0))))); break; case Codes.SymbolIndex: if (symbolTable != null) { set(new Symbol(symbolTable.Get(BitConverter.ToUInt16(R(data, 2), 0)))); } else { R(data, 2); set(new Symbol("<undefined-symbol-index>")); } break; case Codes.String32_32: set(Encoding.UTF8.GetString(R(data, BitConverter.ToInt32(R(data, 4), 0)))); break; case Codes.String32_24: set(Encoding.UTF8.GetString(R(data, BitConverter.ToInt32(R(data, 3, X1), 0)))); break; case Codes.String32_16: set(Encoding.UTF8.GetString(R(data, BitConverter.ToUInt16(R(data, 2), 0)))); break; case Codes.String32_8: set(Encoding.UTF8.GetString(R(data, data.ReadByte()))); break; case Codes.String32_0: set(""); break; case Codes.StreamShort: set(new MemoryStream(R(data, BitConverter.ToInt32(R(data, 4), 0)))); break; case Codes.Null: set(null); break; case Codes.DateTime: set(DateTime.FromBinary(BitConverter.ToInt64(R(data, 8), 0))); break; case Codes.StreamLong: // TODO throw new Exception("Not supported"); case Codes.SpecialMessage: set(new SpecialMessage(Encoding.UTF8.GetString(R(data, BitConverter.ToInt32(R(data, 4), 0))))); break; default: throw new Exception("Bad data format!"); } } }
static Cons PrepareBody(SyntaxArgument[] args, Cons body) { var item = body; while (item != null) { var symbol = item.Car() as Symbol; if (symbol != null) { //if (symbol.Name == "lambda") { // var largs = (item.Cdr().Car() as Cons)?.GetIterator().Select(a => (a.Car() as Symbol)?.Name) // .ToArray(); // var lbinds = args.Where(a => !largs.Any(la => la == a.Original.Name)).ToArray(); // PrepareBody(lbinds, item.Cdr().Cdr() as Cons); // break; //} if (symbol.Name == "quote") { // ignore quoted break; } else { var syntax = args.FirstOrDefault(s => symbol.Name == s.Original.Name); if (syntax != null) { ((Cons)item).SetCar(syntax); } } } else { var form = item.Car() as Cons; if (form != null) { PrepareBody(args, form); } } var next = item.Cdr(); if (next is Cons) { item = next as Cons; } else { symbol = item.Cdr() as Symbol; if (symbol != null) { var syntax = args.FirstOrDefault(s => symbol.Name == s.Original.Name); if (syntax != null) { ((Cons)item).SetCdr(syntax); } } item = null; } } return(body); }
public object EvlSeq(Cons seq, EnviromentFrame env) { return(VirtualMashine.Eval(Compiler.Compile(seq), env)); }
public Lambda() { Argument = new Cons(); Closure = new EnviromentFrame(); Body = new Cons[0]; }
public object EvlExp(Cons seq) { return(EvlSeq(new Cons(seq), DefaultEnviroment)); }
public static Operation Compile(Cons seq) { return(CompileBegin(seq, Operation.Halt())); }