Ejemplo n.º 1
0
        /// <summary>
        /// Evalues an AST in the environment.
        ///
        /// TODO: refactor to move to <see cref="OpenLisp.Core.StaticClasses.CoreNameSpace"/>.
        /// </summary>
        /// <param name="abstractSyntaxTree"></param>
        /// <param name="environment"></param>
        /// <returns></returns>
        public static OpenLispVal EvalAst(OpenLispVal abstractSyntaxTree, Env environment)
        {
            var key = abstractSyntaxTree as OpenLispSymbol;

            if (key != null)
            {
                return(environment.Get(key));
            }

            var list = abstractSyntaxTree as OpenLispList;

            if (list == null)
            {
                var map = abstractSyntaxTree as OpenLispHashMap;
                if (map == null)
                {
                    return(abstractSyntaxTree);
                }
                var newDictionary =
                    map.Value.ToDictionary(
                        entry => entry.Key, entry => Eval(entry.Value, environment));
                return(new OpenLispHashMap(newDictionary));
            }

            OpenLispList oldList = list;
            OpenLispList newList = abstractSyntaxTree.ListQ() ? new OpenLispList()
                : (OpenLispList) new OpenLispVector();

            foreach (OpenLispVal movedValue in oldList.Value)
            {
                newList.Conj(Eval(movedValue, environment));
            }
            return(newList);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Constructor accepting an outer <see cref="Env"/> with binds and expressions.
        /// </summary>
        /// <param name="outer"><see cref="Env"/></param>
        /// <param name="binds"><see cref="OpenLispList"/></param>
        /// <param name="expressions"><see cref="OpenLispList"/></param>
        public Env(Env outer, OpenLispList binds, OpenLispList expressions)
        {
            _outer = outer;

            for (int i = 0; i < binds.Size; i++)
            {
                string symbol = ((OpenLispSymbol)binds.Nth(i)).Value;

                if (symbol == "&")
                {
                    _data[((OpenLispSymbol)binds.Nth(i + 1)).Value] = expressions.Slice(i);
                    break;
                }

                _data[symbol] = expressions.Nth(i);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Reads an OpenLisp.NET list expression.
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="openLispList"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        public static OpenLispVal ReadList(TokensReader reader, OpenLispList openLispList, char start, char end)
        {
            string token = reader.Next();

            if (token[0] == start)
            {
                while ((token = reader.Peek()) != null && token[0] != end)
                {
                    openLispList.Conj(ReadForm(reader));
                }

                if (token == null)
                {
                    throw new ParseError("expected '" + end + "', got EOF");
                }
                reader.Next();

                return(openLispList);
            }

            throw new ParseError("expected '" + start + "'");
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Evaluate an <see cref="OpenLispVal"/> inside an <seealso cref="Env"/>.
        ///
        /// The core namespace is defined in <seealso cref="OpenLisp.Core.StaticClasses.CoreNameSpace"/>.
        ///
        /// TODO: refactor the switch over treeHeadSymbol.  All symbols of the core language should be defined in the same place.
        /// </summary>
        /// <param name="originalAbstractSyntaxTree"></param>
        /// <param name="environment"></param>
        /// <returns></returns>
        public static OpenLispVal Eval(OpenLispVal originalAbstractSyntaxTree, Env environment)
        {
            while (true)
            {
                //Console.WriteLine("EVAL: " + printer._pr_str(orig_ast, true));
                if (!originalAbstractSyntaxTree.ListQ())
                {
                    return(EvalAst(originalAbstractSyntaxTree, environment));
                }

                // apply list
                OpenLispVal expanded = MacroExpand(originalAbstractSyntaxTree, environment);
                if (!expanded.ListQ())
                {
                    return(expanded);
                }

                OpenLispList abstractSyntaxTree = (OpenLispList)expanded;
                if (abstractSyntaxTree.Size == 0)
                {
                    return(abstractSyntaxTree);
                }

                var treeHead = abstractSyntaxTree[0];

                var    symbol         = treeHead as OpenLispSymbol;
                String treeHeadSymbol = symbol?.ToString() ?? "__<*fn*>__";

                // Let's get alchemical in our metaphors:
                OpenLispVal caputPrimus;    // The First Head.  Here's a vector: [1 lol 2 3 apple].  caputPrimus should be: 1.
                OpenLispVal caputSecundus;  // The Second Head.  Here's a list: `(1 lol 2 3 apple).  caputSecundus should be: lol.
                OpenLispVal solutio;

                switch (treeHeadSymbol)
                {
                // TODO: extract this switch out of the REPL and consolidate in the core NS.
                case "def!":
                    caputPrimus   = abstractSyntaxTree[1];
                    caputSecundus = abstractSyntaxTree[2];
                    solutio       = Eval(caputSecundus, environment);
                    environment.Set((OpenLispSymbol)caputPrimus, solutio);
                    return(solutio);

                case "let*":
                    caputPrimus   = abstractSyntaxTree[1];
                    caputSecundus = abstractSyntaxTree[2];
                    OpenLispSymbol key;
                    OpenLispVal    value;
                    Env            letEnvironment = new Env(environment); // TODO: explain ramifications to memory allocation and protection by creating a new Env object this way.
                    for (int i = 0; i < ((OpenLispList)caputPrimus).Size; i += 2)
                    {
                        key   = (OpenLispSymbol)((OpenLispList)caputPrimus)[i];
                        value = ((OpenLispList)caputPrimus)[i + 1];
                        letEnvironment.Set(key, Eval(value, letEnvironment));
                    }
                    originalAbstractSyntaxTree = caputSecundus;
                    environment = letEnvironment;
                    break;

                case "quote":
                    return(abstractSyntaxTree[1]);

                case "quasiquote":
                    originalAbstractSyntaxTree = QuasiQuote(abstractSyntaxTree[1]);
                    break;

                case "defmacro!":
                    caputPrimus   = abstractSyntaxTree[1];
                    caputSecundus = abstractSyntaxTree[2];
                    solutio       = Eval(caputSecundus, environment);
                    ((OpenLispFunc)solutio).Macro = true;
                    environment.Set(((OpenLispSymbol)caputPrimus), solutio);
                    return(solutio);

                case "macroexpand":
                    caputPrimus = abstractSyntaxTree[1];
                    return(MacroExpand(caputPrimus, environment));

                case "try*":
                    try
                    {
                        return(Eval(abstractSyntaxTree[1], environment));
                    }
                    catch (Exception caught)
                    {
                        if (abstractSyntaxTree.Size <= 2)
                        {
                            throw caught;
                        }

                        OpenLispVal openLispException;

                        caputSecundus = abstractSyntaxTree[2];
                        OpenLispVal caputSecundusHead = ((OpenLispList)caputSecundus)[0];
                        if (((OpenLispSymbol)caputSecundusHead).ToString() != "catch*")
                        {
                            throw caught;
                        }

                        var exception = caught as OpenLispException;
                        openLispException = exception != null
                                ? (OpenLispVal)exception.Value
#if TRACE
                                : new OpenLispString(caught.StackTrace);
#elif !TRACE
                                            : new OpenLispString("Stack Trace not yet available in OS.");
#endif
                        return(Eval(((OpenLispList)caputSecundus)[2],
                                    new Env(environment, ((OpenLispList)caputSecundus).Slice(1, 2),
                                            new OpenLispList(openLispException))));
                    }
 /// <summary>
 /// Initializes a new instance of the <see cref="T:OpenLisp.Core.DataTypes.Concurrent.OpenLispSkipList"/> class.
 /// </summary>
 /// <param name="value">Value.</param>
 public OpenLispSkipList(OpenLispList value)
     : this(value.Value)
 {
 }
Ejemplo n.º 6
0
        /// <summary>
        /// Reads a hash map using an instance of <see cref="TokensReader"/>.
        /// </summary>
        /// <param name="reader"></param>
        /// <returns></returns>
        public static OpenLispVal ReadHashMap(TokensReader reader)
        {
            OpenLispList openLispList = (OpenLispList)ReadList(reader, new OpenLispList(), '{', '}');

            return(new OpenLispHashMap(openLispList));
        }
Ejemplo n.º 7
0
 /// <summary>
 /// pr-str arguments.
 /// </summary>
 /// <param name="args"></param>
 /// <param name="separator"></param>
 /// <param name="printReadably"></param>
 /// <returns></returns>
 public static string PrStrArgs(OpenLispList args, String separator, bool printReadably)
 {
     return(Join(args.Value, separator, printReadably));
 }