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); }
public static Cons List(params object[] items) { var root = new Cons(); foreach (var item in items) { root.Add(item); } return(root); }
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); }
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); }
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; } } }