Exemplo n.º 1
0
        static MalVal eval_ast(MalVal ast, Env env)
        {
            // TODO - handle malHashMap.
            // Switch on the type of the ast.
            switch ((Object)ast)
            {
            case MalSym malSym:
                return(env.Get(malSym));

            case MalList malList:
                // Return a new list that is the result of calling EVAL on each of the members of the list.
                MalList derivedList = new MalList();
                for (int i = 0; i < malList.Count(); i++)
                {
                    derivedList.Add(EVAL(malList.Get(i), env));
                }
                return(derivedList);

            case MalVector malVec:
                // Return a new vector that is the result of calling EVAL on each of the members of the vector.
                MalVector derivedVec = new MalVector();
                for (int i = 0; i < malVec.Count(); i++)
                {
                    derivedVec.Add(EVAL(malVec.Get(i), env));
                }
                return(derivedVec);

            case MalHashMap malHashMap:
                throw new MalInternalError("Can't evaluate a HashMap yet '" + malHashMap.ToString() + "'");

            default:
                // It's not a symbol or a list.
                return(ast);
            }
        }
Exemplo n.º 2
0
        // EVAL is handled by two functions - EVAL which decides whether or not the ast is a special
        // form or not and eval_ast which evaluates the remaining symbols, lists, etc.
        // EVAL is tail-call optimised, as per Mal guide step 5

        static MalVal eval_ast(MalVal ast, Env env)
        {
            // Switch on the type of the ast.
            switch ((Object)ast)
            {
            case MalSym malSym:
                return(env.Get(malSym));

            case MalList malList:
                // Return a new list that is the result of calling EVAL on each of the members of the list.
                MalList derivedList = new MalList();
                for (int i = 0; i < malList.Count(); i++)
                {
                    derivedList.Add(EVAL(malList.Get(i), env));
                }
                return(derivedList);

            case MalVector malVec:
                // Return a new vector that is the result of calling EVAL on each of the members of the vector.
                MalVector derivedVec = new MalVector();
                for (int i = 0; i < malVec.Count(); i++)
                {
                    derivedVec.Add(EVAL(malVec.Get(i), env));
                }
                return(derivedVec);

            case MalHashMap malHashMap:
                // Return a new hash-map which consists of key-value pairs where the key is a key from the hash-map
                // and the value is the result of calling EVAL on the corresponding value.
                if (malHashMap.Count() % 2 != 0)
                {
                    throw new MalEvalError("Hashmap requires an even number of elements forming key value pairs '" + malHashMap.ToString(true) + "'");
                }

                MalHashMap derivedHashMap = new MalHashMap();
                // Work through successive key value pairs.
                // Note - C#-Mal creates a dictionary, loads it and then passes the result to a Hashmap c'tor that takes a Dict.
                for (int i = 0; i < malHashMap.Count(); i += 2)
                {
                    MalVal key = malHashMap.Get(i);
                    if (key is MalString || key is MalKeyword)
                    {
                        derivedHashMap.Add(key);
                        derivedHashMap.Add(EVAL(malHashMap.Get(i + 1), env));
                    }
                    else
                    {
                        throw new MalEvalError("Expecting a keyword or string as a HashMap key but got '" + key.ToString(true) + "'");
                    }
                }
                return(derivedHashMap);

            default:
                // It's not a symbol or a list.
                return(ast);
            }
        }
Exemplo n.º 3
0
        static MalVal eval_ast(MalVal ast, Dictionary <string, MalFunc> replEnv)
        {
            // TODO - handle vectors
            // Switch on the type of the ast.
            switch ((Object)ast)
            {
            case MalSym malSym:
                // Lookup the symbol in the environment and return the value or raise an error.
                string malsymstring = malSym.ToString(true);
                Console.WriteLine("eval_ast - searching for symbol: '" + malsymstring + "'");

                if (replEnv.TryGetValue(malsymstring, out MalFunc func))
                {
                    Console.WriteLine("eval_ast - found function '" + func.ToString(true) + "'");
                    return(func);
                }
                else
                {
                    throw new MalEvalError("Undefined symbol '" + malSym.ToString(true) + "'");
                }

            case MalList malList:
                MalList derivedList = new MalList();
                Console.WriteLine("eval_ast - handling MalList");
                for (int i = 0; i < malList.Count(); i++)
                {
                    derivedList.Add(EVAL(malList.Get(i), replEnv));
                }
                return(derivedList);

            case MalVector malVec:
                MalVector derivedVec = new MalVector();
                Console.WriteLine("eval_ast - handling MalVector");
                // TODO - return a new list that is the result of calling EVAL on each of the members of the list.
                for (int i = 0; i < malVec.Count(); i++)
                {
                    derivedVec.Add(EVAL(malVec.Get(i), replEnv));
                }
                return(derivedVec);

            case MalHashMap malHashMap:
                throw new MalEvalError("INTERNAL - can't evaluate a HashMap yet '" + malHashMap.ToString() + "'");

            default:
                // It's not a symbol or a list.
                return(ast);
            }
        }
Exemplo n.º 4
0
        public void ReadForm_ReadsAVector()
        {
            var input = "[+ 1 1]";

            var reader = Reader.ReadStr(input);

            var expected = new MalVector();

            expected.Add(new MalAtom("+"));
            expected.Add(new MalAtom("1"));
            expected.Add(new MalAtom("1"));

            var result = Reader.ReadForm(reader);

            result.Should().BeOfType <MalVector>();
            result.Should().BeEquivalentTo(expected);
        }
Exemplo n.º 5
0
            // Non-destructively remove a target item from a supplied list.
            // This has CL-like semantics, do only removes the first target encountered.
            public MalSequence Remove(MalVal target)
            {
                // Create a list to which the non-target items will be copied.
                MalSequence RemoveSeq;
                bool        removedP = false;

                // Instantiate a sequence of the same type.
                if (this is MalList)
                {
                    RemoveSeq = new MalList();
                }
                else if (this is MalVector)
                {
                    RemoveSeq = new MalVector();
                }
                else
                {
                    throw new MalEvalError("remove expected list or vector but got '" + this.ToString() + "'");
                }
                for (var i = 0; i < MyElements.Count; i++)
                {
                    if (removedP)
                    {
                        // target already removed so always okay to keep this one.
                        RemoveSeq.Add(MyElements[i]);
                    }
                    else
                    {
                        if (EQ(MyElements[i], target) == malTrue)
                        {
                            // This is the target to remove, so don't copy it.
                            removedP = true;
                        }
                        else
                        {
                            RemoveSeq.Add(MyElements[i]);
                        }
                    }
                }
                return(RemoveSeq);
            }