Пример #1
0
        public void TestScripts()
        {
            var path  = Path.GetDirectoryName(typeof(ScriptTests).GetTypeInfo().Assembly.Location);
            var tests = File.ReadAllText(Path.Combine(path, "tests.scm"));

            var def = AtomHelper.CreateList(
                AtomHelper.SymbolFromString("define"),
                AtomHelper.SymbolFromString("test"),
                AtomHelper.CreateList(AtomHelper.SymbolFromString("lambda"), AtomHelper.Nil, AtomHelper.CreateProcedure("test", Test, false))
                );

            Eval(def);

            var errors = "";
            var exprs  = EvalAll(tests).ToArray();

            for (var i = 0; i < exprs.Count(); i++)
            {
                var result = exprs[i];
                if (result == null)
                {
                    continue;
                }

                if (result.IsString())
                {
                    errors += result.String() + "\n";
                }
            }
            if (errors != "")
            {
                Assert.Fail(errors);
            }
        }
Пример #2
0
        private ISExpression RewriteLetStar(ISchemeVM vm, ISExpression expr)
        {
            var x = expr as Cons;
            var c = x.ListCount();

            if (c < 3)
            {
                ThrowErr("let*", "invalid number of arguments", expr.String());
            }

            var bindings = x.Get(1);
            var body     = x.Get(2);

            if (!bindings.IsList())
            {
                ThrowErr("let*", "invalid argument 'bindings'", expr.String());
            }

            if (bindings == AtomHelper.Nil || bindings.GetUnsafeCdr() == AtomHelper.Nil)
            {
                return(RewriteLet(vm, expr));
            }

            var first  = bindings.GetUnsafeCar();
            var remain = bindings.GetUnsafeCdr();

            return(RewriteLet(vm, AtomHelper.CreateList(CompilerConstants.Let, AtomHelper.CreateList(Compile(vm, first)),
                                                        AtomHelper.CreateList(CompilerConstants.LetStar, Compile(vm, remain), Compile(vm, body)))));
        }
Пример #3
0
        public override ISExpression Compile(ISchemeVM vm, ISExpression expr)
        {
            if (!expr.IsList() || expr == AtomHelper.Nil)
            {
                return(expr);
            }

            var c  = (Cons)expr;
            var op = c.Get(0);

            if (op == CompilerConstants.If)
            {
                var count = c.ListCount();

                if (count < 3 || count > 4)
                {
                    ThrowErr("if", "invalid number of arguments", expr.String());
                }

                if (count == 3)
                {
                    var test = Compile(vm, c.Get(1));
                    var then = Compile(vm, c.Get(2));
                    return(AtomHelper.CreateList(CompilerConstants.If, test, then, AtomHelper.Nil));
                }
            }

            return(expr);
        }
Пример #4
0
        protected ISExpression Continuation(Stack <IFrame> s, ISchemeVM vm)
        {
            var v = AtomHelper.SymbolFromString("v");

            return(Closure(new NuateInstruction(s, v), AtomHelper.CreateEnvironment(),
                           AtomHelper.CreateList(v)));
        }
Пример #5
0
        public override IInstruction Execute(ISchemeVM vm)
        {
            IEnvironment e = vm.E;

            if (vm.A.IsClosure())
            {
                var c = vm.A as Closure;

                if (c.Body.Name != "native")
                {
                    if (c.Vars.IsSymbol())
                    {
                        e = Extend(vm.E, CreateMap(AtomHelper.CreateList(c.Vars), vm.R));
                    }
                    else if (c.Vars.IsList())
                    {
                        e = Extend(vm.E, CreateMap(c.Vars, vm.R));
                    }
                    else if (!c.Vars.IsNil())
                    {
                        ThrowErr("apply", "attempted application with invalid binding parameter", $"parameter vars: {c.Vars.String()}");
                    }
                }

                SetE(vm, e);
                return(c.Body);
            }
            ThrowErr("apply", "attempted application of non-function", $"({vm.A.String()})");
            return(null);
        }
Пример #6
0
        private ISExpression RewriteLet(ISchemeVM vm, ISExpression expr)
        {
            List <ISExpression> vars = new List <ISExpression>(), vals = new List <ISExpression>();
            ISExpression        defs;
            var x = expr as Cons;
            var c = x.ListCount();

            if (c < 3)
            {
                ThrowErr("let", "invalid number of arguments", expr.String());
            }

            //  (let name ((var val) ...) body)
            if (x.Get(1).IsSymbol())
            {
                var sym = x.Get(1);
                defs = x.Get(2);
                while (defs != AtomHelper.Nil)
                {
                    var n = defs.GetUnsafeCar().GetUnsafeCar();
                    var v = defs.GetUnsafeCar().GetUnsafeCdr().GetUnsafeCar();

                    if (!n.IsSymbol())
                    {
                        ThrowErr("let", "invalid argument 'bindings'", x.String());
                    }

                    vars.Add(n);
                    vals.Add(v);
                    defs = defs.GetUnsafeCdr();
                }

                // ((lambda ()
                //   (define name (lambda (vars) body))
                //   (name vals)))
                var body        = x.GetUnsafeCdr().GetUnsafeCdr().GetUnsafeCdr();
                var innerLambda = AtomHelper.CreateCons(
                    CompilerConstants.Lambda,
                    AtomHelper.CreateCons(vars.Unflatten(),
                                          Compile(vm, body))
                    );
                var define      = AtomHelper.CreateList(CompilerConstants.Define, sym, innerLambda);
                var loopCall    = AtomHelper.CreateCons(sym, Compile(vm, vals.Unflatten()));
                var outerLambda = AtomHelper.CreateList(CompilerConstants.Lambda, AtomHelper.Nil, define, loopCall);

                return(AtomHelper.CreateList(outerLambda));
            }
            // (let ((var val) ...) body)
            else if (x.Get(1).IsList())
            {
                defs = x.Get(1);

                while (defs != AtomHelper.Nil)
                {
                    var d = defs.GetUnsafeCar();

                    if (!d.IsList() || d.ListCount() != 2)
                    {
                        ThrowErr("let", "invalid argument 'bindings'", x.String());
                    }

                    var n = d.GetUnsafeCar();
                    var v = d.GetUnsafeCdr().GetUnsafeCar();

                    if (!n.IsSymbol())
                    {
                        ThrowErr("let", "invalid argument 'bindings'", x.String());
                    }

                    vars.Add(n);
                    vals.Add(v);
                    defs = defs.GetUnsafeCdr();
                }
                // ((lambda (vars) body) vals)
                var body = x.GetUnsafeCdr().GetUnsafeCdr();

                var lambda = AtomHelper.CreateCons(CompilerConstants.Lambda,
                                                   AtomHelper.CreateCons(vars.Unflatten(), Compile(vm, body)));
                return(AtomHelper.CreateCons(lambda, Compile(vm, vals.Unflatten())));
            }

            ThrowErr("let", "invalid argument 'bindings'", x.String());
            return(null);
        }