Пример #1
0
        public static DotFunc Equals()
        {
            return(DotFunc.From(
                       args =>
            {
                switch (args)
                {
                case DotSymbol _:
                    return DotBool.True();

                case DotList l:
                    {
                        // TODO: extend equality to objects!

                        var numbers = l.Expressions.Cast <DotNumber>().ToList();

                        if (numbers.Count == 0)
                        {
                            throw new EvaluatorException("Nothing to compare.");
                        }

                        var first = numbers[0];

                        var(_, result) = numbers.Skip(1).Aggregate(
                            seed: (first, true), func: (tuple, b) =>
                        {
                            var(a, resultSoFar) = tuple;

                            if (!resultSoFar)
                            {
                                return (b, false);
                            }

                            var predicateStillTrue =
                                a.GetValue() == b.GetValue();

                            return (b, predicateStillTrue);
                        });
                        return new DotBool(result);
                    }
                }

                return DotBool.False();
            }));
        }
Пример #2
0
        public static DotExpression Expand(DotExpression expression,
                                           bool topLevel = false)
        {
            if (!(expression is DotList l))
            {
                // constants can't be expanded
                return(expression);
            }

            if (l.Expressions.Count == 0)
            {
                throw new ParserException(
                          "An empty list needs to be quoted!", l.Line, l.Column);
            }

            var args = l.Expressions.Skip(1).ToList();

            // if (!(l.Expressions.First() is DotSymbol op))
            // {
            //     throw new EvaluatorException(
            //         "Function or special form expected!");
            // }

            if (l.Expressions.First() is DotSymbol op)
            {
                if (op.Name == "quote")
                {
                    return(expression);
                }

                // TODO Find a generic way to check function and procedure argument length and type

                if (op.Name == "def" || op.Name == "defmacro")
                {
                    if (args.Count != 2)
                    {
                        throw new ParserException("name and body expected!", op.Line,
                                                  op.Column);
                    }

                    var defBody = Expand(args.ElementAt(1));

                    if (op.Name == "defmacro")
                    {
                        if (!topLevel)
                        {
                            throw new ParserException(
                                      "'defmacro' only allowed at top level!", op.Line,
                                      op.Column);
                        }

                        var procedure = Evaluator.Eval(defBody);

                        if (!(procedure is DotProcedure dp))
                        {
                            throw new ParserException(
                                      "A macro must be a procedure", op.Line, op.Column);
                        }

                        // Add macro
                        GlobalEnvironment.MacroTable.Add(
                            (args.ElementAt(0) as DotSymbol).Name,
                            dp
                            );

                        return(DotBool.True());
                    }

                    var expandedDefinition = new LinkedList <DotExpression>();

                    expandedDefinition.AddLast(op);
                    expandedDefinition.AddLast(args.First());
                    expandedDefinition.AddLast(defBody);

                    return(new DotList()
                    {
                        Expressions = expandedDefinition
                    });
                }

                if (op.Name == "quasiquote")
                {
                    return(ExpandQuasiquote(args.First()));
                }

                if (GlobalEnvironment.MacroTable.ContainsKey(op.Name))
                {
                    // call macro
                    var macro     = GlobalEnvironment.MacroTable[op.Name];
                    var macroArgs = new DotList()
                    {
                        Expressions = args.ToLinkedList()
                    };

                    return(Expand(macro.Call(macroArgs), topLevel));
                }
            }

            l.Expressions = l.Expressions
                            .Select(exp => Expand(exp, false))
                            .ToLinkedList();
            return(l);
        }
Пример #3
0
 public static DotBool ToDotBool(this bool val)
 {
     return(val ? DotBool.True() : DotBool.False());
 }