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 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);
        }
        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));
        }
Exemple #4
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;
            }
        }
        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));
        }
Exemple #6
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;
            }
        }
        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 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));
        }
        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;
            }
        }