Ejemplo n.º 1
0
        static int Main(string[] args)
        {
            Env env = CreateTopLevelEnv();

            List <Value> malArgs = new List <Value>();

            for (int i = 1; i < args.Length; i++)
            {
                malArgs.Add(new Str(args[i]));
            }

            env.Set(Reader.AddSymbol("*ARGV*") as Symbol, new List(malArgs));

            Rep("(try* (load-file \".malrc\"))", env);

            if (args.Length == 0)
            {
                return(Repl(env));
            }

#if NATIVE_LOAD_FILE
            FileInfo fi = new FileInfo(args[0]);
            if (fi.Exists)
            {
                using (Stream stream = fi.OpenRead())
                    LoadStream(stream, env);
            }
            else
            {
                Console.Error.WriteLine("ERROR: unable open file '{0}'", args[0]);
                return(1);
            }
#else
            List loaderArgs = new List(new List <Value>()
            {
                new Str(args[0])
            });
            try
            {
                var val = env.Get(Reader.Load_file);
                if (val is Closure cls)
                {
                    EVAL(cls.Body, cls.CreateEnv(loaderArgs));
                }
                else
                if (val is Func_Native fn)
                {
                    fn.Apply(loaderArgs);
                }
                else
                {
                    throw new MalException("unknown function to evaluate file");
                }
            }
            catch (MalException ex)
            {
                Console.Error.WriteLine("ERROR: {0}", ex.Message);
                return(1);
            }
            catch (MalQuitExc)
            { }
#endif
            return(0);
        }
Ejemplo n.º 2
0
        // A helper function for EVAL that handles symbols (it looks them up) and
        // sequences (it EVAL's their elements by mutual recursion with EVAL).

        static MalVal eval_ast(MalVal ast, Env env)
        {
            // Switch on the type of the ast.
            switch ((Object)ast)
            {
            case MalSym malSym:
                // Simplest case - look up and return a symbol's value.
                return(env.Get(malSym));

            case MalList malList:
                // Build and return a new list that contains the result of calling EVAL
                // on each member of the original 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:
                // Build and return a new 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();
                // Build and return a new HashMap. it checks that keys are in fact keys and
                // evaluates the values before storing them.
                // 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);
            }
        }
Ejemplo n.º 3
0
        static Value Eval_ast(Value arg, Env env)
        {
            if (env == null)
            {
                return(arg);
            }

            if (arg == null)
            {
                return(arg);
            }

            if (arg is Symbol sym)
            {
                Value val = env.Get(sym);

                if (val == null)
                {
                    throw new MalException(string.Format("'{0}' not found", sym.Name));
                }

                return(val);
            }
            else if (arg is List lst)
            {
                if (lst.Elements == null)
                {
                    return(arg);
                }

                List <Value> elms = new List <Value>();
                for (List.Node elm = lst.Elements; elm != null; elm = elm.cdr)
                {
                    elms.Add(EVAL(elm.car, env));
                }

                return(new List(elms));
            }
            else if (arg is Vector vec)
            {
                List <Value> elms = new List <Value>();

                foreach (Value v in vec.Elements)
                {
                    elms.Add(EVAL(v, env));
                }

                return(new Vector(elms));
            }
            else if (arg is HashMap map)
            {
                HashMap hm = new HashMap();
                Dictionary <Value, Value> elms = hm.Elements;

                foreach (var kv in map.Elements)
                {
                    elms[kv.Key] = EVAL(kv.Value, env);
                }

                return(hm);
            }

            return(arg);
        }