예제 #1
0
        private static void Cond(Evaluator eval, StackFrame frame)
        {
            switch (frame.state.value)
            {
            case "-eval-sexp-body-":
                frame.temp1 = frame.args;
                frame.state = new Atom("-built-in-cond-head-");
                break;

            case "-built-in-cond-head-":
                if (eval.HaveReturn())
                {
                    var condition = eval.TakeReturn();
                    if (!condition.IsBool)
                    {
                        throw new ArgumentException($"Condition must return boolean atom, but found: {condition}!");
                    }
                    if ((bool)condition.value)
                    {
                        frame.state = new Atom("-built-in-cond-body-");
                        break;
                    }
                }

                if (frame.temp1 != null)
                {
                    frame.temp2 = frame.temp1.atom;
                    frame.temp1 = frame.temp1.next;

                    if (!frame.temp2.IsPair)
                    {
                        throw new ArgumentException($"Condition element must be list, but found: {frame.temp2}!");
                    }

                    eval.CreateFrame("-eval-", frame.temp2.atom, frame.context);
                }
                else
                {
                    //  Ни одно из условий не выполнилось
                    frame.state = new Atom("-eval-sexp-body-");
                    eval.Return(Atoms.FALSE);
                }

                break;

            case "-built-in-cond-body-":
                if (eval.HaveReturn())
                {
                    eval.CloseFrame();
                }
                else
                {
                    eval.CreateFrame("-eval-block-", frame.temp2.next, frame.context);
                }

                break;
            }
        }
예제 #2
0
        private static void Until(Evaluator eval, StackFrame frame)
        {
            switch (frame.state.value)
            {
            case "-eval-sexp-body-":
                //  (Cond Body)
                (frame.temp1, frame.temp2) = (frame.args.atom, frame.args.next);
                frame.state = new Atom("-built-in-while-cond-");
                break;

            case "-built-in-while-cond-":
                if (eval.HaveReturn())
                {
                    var condition = eval.TakeReturn();
                    if (!condition.IsBool)
                    {
                        throw new ArgumentException($"Condition must return boolean atom, but found: {condition}!");
                    }
                    if (!(bool)condition.value)
                    {
                        frame.state = new Atom("-built-in-while-body-");
                    }
                    else
                    {
                        frame.state = new Atom("-eval-sexp-body-");
                        eval.Return(frame.temp3);
                    }
                }
                else
                {
                    eval.CreateFrame("-eval-", frame.temp1, frame.context);
                }

                break;

            case "-built-in-while-body-":
                if (eval.HaveReturn())
                {
                    frame.temp3 = eval.TakeReturn();
                    frame.state = new Atom("-built-in-while-cond-");
                }
                else
                {
                    eval.CreateFrame("-eval-block-", frame.temp2, frame.context);
                }

                break;
            }
        }
예제 #3
0
        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;
        }
예제 #4
0
        // 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;
            }
        }
예제 #5
0
        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();
        }
예제 #6
0
        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;
            }
        }
예제 #7
0
        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;
            }
        }
예제 #8
0
        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();
        }
예제 #9
0
        private static void EvalEach(Evaluator eval, StackFrame frame)
        {
            if (!eval.HaveReturn())
            {
                Atom expression = frame.args;
                Atom first      = frame.args?.atom;
                if (first?.value is Context ctx)
                {
                    expression = frame.args?.next;
                }
                else
                {
                    ctx = frame.context.value as Context;
                }
                eval.CreateFrame("-eval-block-", expression, ctx);
                return;
            }

            eval.CloseFrame();
        }
예제 #10
0
        private static void SetFirst(Evaluator eval, StackFrame frame)
        {
            var  args = frame.args;
            Atom sym  = (Atom)args?.value;

            if (sym.type != AtomType.Symbol)
            {
                throw new ArgumentException("Variable name must be symbol!");
            }

            if (eval.HaveReturn())
            {
                var result = eval.TakeReturn();
                var ctx    = frame.context.value as Context;
                ContextUtils.Set(ctx, result, (string)sym.value);
                eval.Return(result);
                return;
            }

            eval.CreateFrame("-eval-", args.next?.atom, frame.context);
            frame.state = Atoms.INTERNAL_STATE;
        }
예제 #11
0
        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;
            }
        }