Пример #1
0
        public void TestDivide()
        {
            var prim = PrimitiveFactory.Get("/");
            ScheminDecimal test_decimal = new ScheminDecimal(3.0m);
            ScheminInteger test_integer = new ScheminInteger(3);
            ScheminInteger test_divisor_int = new ScheminInteger(2);
            ScheminDecimal test_divisor_decimal = new ScheminDecimal(2);

            ScheminList decimal_args = new ScheminList(test_decimal);
            decimal_args.Append(test_divisor_decimal);

            ScheminList int_args = new ScheminList(test_integer);
            int_args.Append(test_divisor_int);

            ScheminList mixed_args = new ScheminList(test_integer);
            mixed_args.Append(test_divisor_decimal);

            ScheminDecimal decimal_result = (ScheminDecimal) prim.Execute(null, null, decimal_args);
            ScheminInteger int_result = (ScheminInteger) prim.Execute(null, null, int_args);
            ScheminDecimal mixed_result = (ScheminDecimal) prim.Execute(null, null, mixed_args);

            ScheminInteger expected = new ScheminInteger(1);

            Assert.AreEqual(1.5m, decimal_result.DecimalValue());
            Assert.AreEqual(expected.IntegerValue(), int_result.IntegerValue());
            Assert.AreEqual(1.5m, mixed_result.DecimalValue());
        }
Пример #2
0
        public override IScheminType Execute(Environment env, Evaluator eval, ScheminList args)
        {
            IScheminType head = args.Car();
            IScheminType rest = args.Cdr().Car();

            if ((rest as ScheminList) != null)
            {
                ScheminList temp = (ScheminList) rest;

                if (temp.Empty)
                {
                    return new ScheminList(head);
                }
                else
                {
                    ScheminList consd = new ScheminList(head);

                    foreach (IScheminType type in temp)
                    {
                        consd.Append(type);
                    }

                    return consd;
                }
            }

            var append = new ScheminList(head);
            append.Append(rest);
            return append;
        }
Пример #3
0
        public void TestStringRef()
        {
            var prim = PrimitiveFactory.Get("string-ref");
            ScheminString test = new ScheminString("test");

            ScheminList args = new ScheminList(test);
            args.Append(new ScheminInteger(0));

            ScheminChar result = (ScheminChar) prim.Execute(null, null, args);
            char expected = 't';

            Assert.AreEqual(result.Value, expected);
        }
Пример #4
0
        public override IScheminType Execute(Environment env, Evaluator eval, ScheminList args)
        {
            ScheminList conditions = (ScheminList) args;
            ScheminList builtIf = new ScheminList();
            builtIf.UnQuote();

            ScheminList firstCondition = (ScheminList) conditions.Car();
            if ((firstCondition.Car() as ScheminAtom) != null)
            {
                ScheminAtom atom = (ScheminAtom) firstCondition.Car();
                if (atom.Name == "else")
                {
                    ScheminList elseClause = firstCondition.Cdr();
                    elseClause.Cons(new ScheminPrimitive("begin"));

                    return elseClause;
                }
            }

            builtIf.Append(new ScheminPrimitive("if"));
            builtIf.Append(firstCondition.Car());

            ScheminList beginExpression = firstCondition.Cdr();
            beginExpression.Cons(new ScheminPrimitive("begin"));

            builtIf.Append(beginExpression);

            if (conditions.Cdr().Length > 0)
            {
                ScheminList nextConditions = conditions.Cdr();
                nextConditions.Cons(new ScheminPrimitive("cond"));

                builtIf.Append(nextConditions);
            }

            return builtIf;
        }
Пример #5
0
        public override IScheminType Execute(Environment env, Evaluator eval, ScheminList args)
        {
            IScheminType function = args.Car();
            ScheminList argList = args.Cdr();
            ScheminList toApply = (ScheminList) args.Cdr().Last();

            ScheminList list = new ScheminList();
            list.UnQuote();

            foreach (IScheminType type in toApply)
            {
                list.Append(type);
            }

            foreach (IScheminType type in argList)
            {
                if (type != toApply)
                    list.Cons(type);
            }

            list.Cons(function);

            return list;
        }
Пример #6
0
        public ScheminList ToList()
        {
            ScheminList list = new ScheminList();
            list.Quote();

            foreach (IScheminType type in List)
            {
                list.Append(type);
            }

            return list;
        }
Пример #7
0
        public void TestSubtract()
        {
            var prim = PrimitiveFactory.Get("-");
            ScheminDecimal test_decimal = new ScheminDecimal(8.5m);
            ScheminInteger test_integer = new ScheminInteger(20);
            ScheminDecimal test_decimal_2 = new ScheminDecimal(4.1m);
            ScheminInteger test_integer_2 = new ScheminInteger(6);

            ScheminList decimal_args = new ScheminList(test_decimal);
            decimal_args.Append(test_decimal_2);

            ScheminList int_args = new ScheminList(test_integer);
            int_args.Append(test_integer_2);

            ScheminList mixed_args = new ScheminList(test_integer);
            mixed_args.Append(test_decimal);

            ScheminDecimal decimal_result = (ScheminDecimal) prim.Execute(null, null, decimal_args);
            ScheminInteger int_result = (ScheminInteger) prim.Execute(null, null, int_args);
            ScheminDecimal mixed_result = (ScheminDecimal) prim.Execute(null, null, mixed_args);

            ScheminInteger expected = new ScheminInteger(14);

            Assert.AreEqual(4.4m, decimal_result.DecimalValue());
            Assert.AreEqual(expected.IntegerValue(), int_result.IntegerValue());
            Assert.AreEqual(11.5m, mixed_result.DecimalValue());
        }
Пример #8
0
        public void TestMultiply()
        {
            var prim = PrimitiveFactory.Get("*");
            ScheminDecimal test_decimal = new ScheminDecimal(1.5m);
            ScheminInteger test_integer = new ScheminInteger(2);
            ScheminInteger test_mult_int = new ScheminInteger(6);
            ScheminDecimal test_mult_decimal = new ScheminDecimal(0.8m);
            ScheminInteger test_large = new ScheminInteger(BigInteger.Parse("100000000000000000000000000000000"));
            ScheminInteger test_large_2nd = new ScheminInteger(BigInteger.Parse("400000000000000000000"));

            ScheminList decimal_args = new ScheminList(test_decimal);
            decimal_args.Append(test_mult_decimal);

            ScheminList int_args = new ScheminList(test_integer);
            int_args.Append(test_mult_int);

            ScheminList mixed_args = new ScheminList(test_integer);
            mixed_args.Append(test_mult_decimal);

            ScheminList large_args = new ScheminList(test_large);
            large_args.Append(test_large_2nd);

            ScheminDecimal decimal_result = (ScheminDecimal) prim.Execute(null, null, decimal_args);
            ScheminInteger int_result = (ScheminInteger) prim.Execute(null, null, int_args);
            ScheminDecimal mixed_result = (ScheminDecimal) prim.Execute(null, null, mixed_args);
            ScheminInteger large_result = (ScheminInteger) prim.Execute(null, null, large_args);

            ScheminInteger expected = new ScheminInteger(12);
            ScheminInteger exp_large = new ScheminInteger(BigInteger.Parse("40000000000000000000000000000000000000000000000000000"));

            Assert.AreEqual(1.2m, decimal_result.DecimalValue());
            Assert.AreEqual(expected.IntegerValue(), int_result.IntegerValue());
            Assert.AreEqual(1.6m, mixed_result.DecimalValue());
            Assert.AreEqual(exp_large.IntegerValue(), large_result.IntegerValue());
        }
Пример #9
0
        private ScheminList CombineStackFrame(ScheminList before, ScheminList after, IScheminType result)
        {
            ScheminList complete = new ScheminList();
            complete.UnQuote();

            if (before != null && !before.Empty)
            {
                complete.Append(before.Head);
                var restBefore = before.Rest;
                while (restBefore != null)
                {
                    complete.Append(restBefore.Head);
                    restBefore = restBefore.Rest;
                }
            }

            if (result != null)
            {
                complete.Append(result);
            }

            if (after != null && !after.Empty)
            {
                complete.Append(after.Head);
                var restAfter = after.Rest;
                while (restAfter != null)
                {
                    complete.Append(restAfter.Head);
                    restAfter = restAfter.Rest;
                }
            }

            return complete;
        }
Пример #10
0
        public IScheminType EvaluateList(ScheminList list)
        {
            StackFrame start = new StackFrame();
            start.WaitingOn = list;
            start.CurrentEnv = this.GlobalEnv;

            Stack.Clear();
            Stack.Push(start);

            StackStart:
            while (Stack.Count > 0)
            {
                StackFrame current = Stack.Pop();
                Environment CurrentEnv = current.CurrentEnv;

                ScheminList before = current.Before;
                ScheminList after = current.After;
                IScheminType WaitingOn = current.WaitingOn;

                if ((WaitingOn as ScheminList) == null || WaitingOn.Quoted() == true || IsEmptyList(WaitingOn))
                {
                    StackFrame next = new StackFrame();

                    if (before == null && after == null)
                    {
                        if ((WaitingOn as ScheminAtom) != null && !WaitingOn.Quoted())
                        {
                            WaitingOn = EvalAtom(WaitingOn, CurrentEnv);
                        }

                        if (Stack.Count < 1)
                        {
                            return WaitingOn;
                        }

                        StackFrame previous = Stack.Pop();
                        if (previous.Before == null && previous.After == null)
                        {
                            next.WaitingOn = WaitingOn;
                        }
                        else
                        {
                            next.WaitingOn = CombineStackFrame(previous.Before, previous.After, WaitingOn);
                        }

                        // Use the previous environment in this case as well
                        if (Stack.Count > 0)
                        {
                            next.CurrentEnv = Stack.Peek().CurrentEnv;
                        }
                        else
                        {
                            next.CurrentEnv = previous.CurrentEnv;
                        }

                        Stack.Push(next);
                        continue;
                    }

                    // We need to use the PREVIOUS environment here, so peek it.. otherwise we're re-using the same environment for the previous context.
                    StackFrame peeked = Stack.Peek();
                    next.WaitingOn = CombineStackFrame(before, after, WaitingOn);
                    next.CurrentEnv = peeked.CurrentEnv;
                    Stack.Push(next);
                    continue;
                }

                StackFrame completeFrame = new StackFrame();
                ScheminPrimitive currentPrimitive = null;

                ScheminList rest = (ScheminList) WaitingOn;
                ScheminList pendingBefore = new ScheminList();
                pendingBefore.UnQuote();

                if ((rest.Car() as ScheminPrimitive) != null)
                {
                    if (rest.Car().Quoted() == false)
                    {
                        currentPrimitive = (ScheminPrimitive) rest.Car();
                    }
                }

                int currentArg = 0;

                while (!rest.Empty)
                {
                    IScheminType type = rest.Car();

                    if (currentPrimitive != null)
                    {
                        if (!EvaluateNextArg(currentPrimitive, currentArg, ((ScheminList) WaitingOn).Cdr()))
                        {
                            pendingBefore.Append(type);
                            rest = rest.Cdr();
                            currentArg++;
                            continue;
                        }
                    }

                    if ((type as ScheminAtom) != null)
                    {
                        if (type.Quoted())
                        {
                            pendingBefore.Append(type);
                        }
                        else
                        {
                            IScheminType atomResult = EvalAtom(type, CurrentEnv);
                            if ((atomResult as ScheminRewriter) != null)
                            {
                                // if we get a quoted rewriter here, we're going to apply it :(
                                pendingBefore.Append(atomResult);
                                QuoteAll(rest.Cdr());
                            }
                            else
                            {
                                pendingBefore.Append(atomResult);
                            }
                        }
                    }
                    else if ((type as ScheminList) != null)
                    {
                        ScheminList tempList = (ScheminList) type;

                        if (tempList.Quoted() || tempList.Empty)
                        {
                            pendingBefore.Append(type);
                            rest = rest.Cdr();
                            currentArg++;
                            continue;
                        }

                        StackFrame next = new StackFrame();
                        next.WaitingOn = type;
                        next.After = rest.Cdr();
                        next.Before = pendingBefore;
                        next.CurrentEnv = CurrentEnv;

                        Stack.Push(current);
                        Stack.Push(next);

                        goto StackStart;
                    }
                    else
                    {
                        pendingBefore.Append(type);
                    }

                    rest = rest.Cdr();
                    currentArg++;
                }

                IScheminType functionPosition = pendingBefore.Car();
                ScheminList functionArgs = pendingBefore.Cdr();

                if ((functionPosition as ScheminPrimitive) != null)
                {
                    ScheminPrimitive prim = (ScheminPrimitive) functionPosition;
                    completeFrame.Before = before;
                    completeFrame.After = after;

                    // Need to pass push the previous frame back on so we can get access to the current continuation via the evaluator's Stack field.
                    // also adding the primitive's name to the exception if it gets thrown.
                    try
                    {
                        Stack.Push(current);
                        completeFrame.WaitingOn = prim.Evaluate(functionArgs, CurrentEnv, this);
                        Stack.Pop();
                    }
                    catch (BadArgumentsException ba)
                    {
                        Token sourceToken = prim.SourceToken;
                        string line = String.Empty;
                        if (sourceToken != null)
                        {
                            line = " line: " + sourceToken.LineNumber.ToString() + " col: " + sourceToken.ColNumber.ToString();
                        }
                        throw new BadArgumentsException(prim.ToString() + " " + ba.Message + line);
                    }

                    completeFrame.CurrentEnv = CurrentEnv;

                    Stack.Push(completeFrame);
                    continue;
                }
                else if ((functionPosition as ScheminLambda) != null)
                {
                    ScheminLambda lam = (ScheminLambda) functionPosition;
                    completeFrame.Before = before;
                    completeFrame.After = after;

                    Environment args = lam.MakeEnvironment(functionArgs, this);
                    completeFrame.WaitingOn = lam.Definition;
                    completeFrame.CurrentEnv = args;

                    Stack.Push(completeFrame);
                    continue;
                }
                else if ((functionPosition as ScheminContinuation) != null)
                {
                    ScheminContinuation con = (ScheminContinuation) functionPosition;
                    this.Stack = new Stack<StackFrame>(con.PreviousStack);
                    this.Stack.Peek().WaitingOn = functionArgs.Car();
                    continue;
                }
                else if ((functionPosition as ScheminRewriter) != null)
                {
                    ScheminRewriter rewriter = (ScheminRewriter) functionPosition;

                    QuoteAll(functionArgs);
                    IScheminType result = rewriter.Rewrite(functionArgs);

                    completeFrame.Before = before;
                    completeFrame.After = after;
                    completeFrame.WaitingOn = result;
                    completeFrame.CurrentEnv = CurrentEnv;

                    this.Stack.Push(completeFrame);
                    continue;
                }
                else
                {
                    throw new InvalidOperationException("Non-function in function position: " + functionPosition.ToString());
                }
            }

            throw new InvalidOperationException("Control escaped list evaluator...");
        }
Пример #11
0
        public override IScheminType Execute(Environment env, Evaluator eval, ScheminList args)
        {
            bool isNamed = false;
                if ((args.Car() as ScheminAtom) != null)
                {
                    isNamed = true;
                }

                ScheminList bindings;
                ScheminList expression;

                if (!isNamed)
                {
                    expression = args.Cdr();
                    bindings = (ScheminList) args.Car();
                }
                else
                {
                    expression = args.Cdr().Cdr();
                    bindings = (ScheminList) args.Cdr().Car();
                }

                ScheminList letArgs = new ScheminList();
                ScheminList argExps = new ScheminList();

                letArgs.UnQuote();
                argExps.UnQuote();

                foreach (ScheminList bindingPair in bindings)
                {
                    letArgs.Append(bindingPair.Car());
                    argExps.Append(bindingPair.Cdr().Car());
                }

                ScheminList lambdaDef = new ScheminList(letArgs);
                lambdaDef.UnQuote();

                foreach (IScheminType type in expression)
                {
                    lambdaDef.Append(type);
                }

                Environment closure = env;
                if (isNamed)
                {
                    closure = new Environment();
                    closure.parent = env;
                }

                ScheminLambda lam = new ScheminLambda(lambdaDef, closure);

                if (isNamed)
                {
                    ScheminAtom name = (ScheminAtom) args.Car();
                    closure.AddBinding(name, lam);
                }

                ScheminList toEvaluate = new ScheminList(lam);
                toEvaluate.UnQuote();

                foreach (IScheminType arg in argExps)
                {
                    toEvaluate.Append(arg);
                }

                return toEvaluate;
        }
Пример #12
0
        private void TransformQuotes(ScheminList ast)
        {
            ScheminList c = ast;

            while (c != null)
            {
                IScheminType type = c.Head;

                if ((type as ScheminAtom) != null)
                {
                    ScheminAtom atom = (ScheminAtom) type;
                    if (atom.Name == "'")
                    {
                        // This pass replaces a list like (' a b) with ((quote a) b)
                        // and ''a with (quote (quote a))
                        ScheminList newhead = new ScheminList(new ScheminPrimitive("quote"));
                        TransformQuotes(c.Rest);

                        newhead.Append(c.Rest.Head);

                        c.Head = newhead;
                        c.Rest = c.Rest.Rest;
                    }
                }
                else if ((type as ScheminList) != null)
                {
                    TransformQuotes((ScheminList) type);
                }

                c = c.Rest;
            }
        }
Пример #13
0
        private void TransformQuasiQuotes(ScheminList ast)
        {
            // this horrible code transforms quasiquoted literals into their expanded form
            // eg: `(a ,b) becomes (quasiquote a (unquote b))

            ScheminList c = ast;

            while (c != null)
            {
                IScheminType type = c.Head;

                if ((type as ScheminAtom) != null)
                {
                    ScheminAtom atom = (ScheminAtom) type;
                    if (atom.Name == "`")
                    {
                        ScheminList newhead = new ScheminList(new ScheminPrimitive("quasiquote"));
                        TransformQuasiQuotes(c.Rest);
                        newhead.Append(c.Rest.Head);

                        c.Head = newhead;
                        c.Rest = c.Rest.Rest;
                        continue;
                    }
                    else if (atom.Name == ",@")
                    {
                        ScheminList newhead = new ScheminList(new ScheminPrimitive("unquote-splicing"));
                        TransformQuasiQuotes(c.Rest);
                        newhead.Append(c.Rest.Head);

                        c.Head = newhead;
                        c.Rest = c.Rest.Rest;
                    }
                    else if (atom.Name == ",")
                    {
                        ScheminList newhead = new ScheminList(new ScheminPrimitive("unquote"));
                        TransformQuasiQuotes(c.Rest);
                        newhead.Append(c.Rest.Head);

                        c.Head = newhead;
                        c.Rest = c.Rest.Rest;
                    }
                }
                else if ((type as ScheminList) != null)
                {
                    TransformQuasiQuotes((ScheminList) type);
                }

                c = c.Rest;
            }
        }
Пример #14
0
        private KeyValuePair<ScheminList, int> ParseInternal(List<Token> tokens, int startIndex)
        {
            ScheminList parsed = new ScheminList();

            while (startIndex < tokens.Count)
            {
                if (tokens[startIndex].Type == TokenType.VectorLiteral)
                {
                    if (tokens[startIndex + 1].Type == TokenType.OpenParen)
                    {
                        KeyValuePair<ScheminList, int> descended = ParseInternal(tokens, startIndex + 2);
                        ScheminVector vec = new ScheminVector();
                        foreach (IScheminType type in descended.Key)
                        {
                            type.Quote();
                            vec.List.Add(type);
                        }

                        parsed.Append(vec);
                        startIndex = descended.Value;
                    }

                }
                else if (tokens[startIndex].Type == TokenType.OpenParen)
                {
                    KeyValuePair<ScheminList, int> descended = ParseInternal(tokens, startIndex + 1);
                    parsed.Append(descended.Key);

                    startIndex = descended.Value;
                }
                else if (tokens[startIndex].Type == TokenType.CloseParen)
                {
                    break;
                }
                else if (tokens[startIndex].Type == TokenType.Quote)
                {
                    parsed.Append(new ScheminAtom("'"));
                }
                else if (tokens[startIndex].Type == TokenType.BackQuote)
                {
                    parsed.Append(new ScheminAtom("`"));
                }
                else if (tokens[startIndex].Type == TokenType.AtComma)
                {
                    parsed.Append(new ScheminAtom(",@"));
                }
                else if (tokens[startIndex].Type == TokenType.Comma)
                {
                    parsed.Append(new ScheminAtom(","));
                }
                else
                {
                    IScheminType converted = ConvertToken(tokens[startIndex]);
                    parsed.Append(converted);
                }

                startIndex++;
            }

            return new KeyValuePair<ScheminList, int>(parsed, startIndex);
        }