예제 #1
0
        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);
        }
예제 #2
0
        public static Cons List(params object[] items)
        {
            var root = new Cons();

            foreach (var item in items)
            {
                root.Add(item);
            }

            return(root);
        }
예제 #3
0
        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);
        }
예제 #4
0
            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);
            }
예제 #5
0
        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);
        }
예제 #6
0
        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;
                }
            }
        }