示例#1
0
        public object Apply(ProcedureNode procedure, IList<object> arguments, Environment environment)
        {
            if (arguments.Count != procedure.Parameters.Count() && !procedure.Parameters.Select(x => x.Name).Contains("&"))
            {
                throw new ArgumentException("Wrong number of arguments given to procedure! Expected: " + procedure.Parameters.Count());
            }

            var localEnv = procedure.Environment.CreateChildEnvironment();

            for (int i = 0; i < procedure.Parameters.Count(); ++i)
            {
                object evaluatedArgument;
                bool finished = false;
                var parameterSymbol = procedure.Parameters.ElementAt(i);

                if (parameterSymbol.Name == "&")
                {
                    parameterSymbol = procedure.Parameters.ElementAt(i + 1);

                    evaluatedArgument =
                        procedure.IsMacro ? arguments.Skip(i).ToList()
                        : arguments.Skip(i).Select(arg => evaluator.Evaluate(arg, environment)).ToList();

                    localEnv.DefineSymbol(parameterSymbol, evaluatedArgument);

                    finished = true;
                }
                else
                {
                    evaluatedArgument =
                        procedure.IsMacro
                            ? arguments.ElementAt(i)
                            : evaluator.Evaluate(arguments.ElementAt(i), environment);
                }

                localEnv.DefineSymbol(parameterSymbol, evaluatedArgument);

                if (finished)
                {
                    break;
                }
            }

            var res = evaluator.Evaluate(procedure.Body, localEnv);

            if (procedure.IsMacro)
            {
                return evaluator.Evaluate(res, environment);
            }

            return res;
        }
示例#2
0
 private void PrettyPrintSub(ProcedureNode node)
 {
     stringWriter.Write("<procedure: " + node.Symbol + ">");
 }
示例#3
0
        public object ApplyDefMacro(IList<object> arguments, Environment environment)
        {
            if (arguments.Count != 3)
            {
                throw new ArgumentException("Wrong number of arguments given to defmacro! Expected: " + 3);
            }

            var symbol = arguments.ElementAt(0) as SymbolNode;
            if (symbol == null)
            {
                throw new ArgumentException("First argument to defmacro not a symbol!");
            }

            var parameterList = arguments.ElementAt(1) as IList<object>;
            if (parameterList == null)
            {
                throw new ArgumentException("Second argument to defmacro not a parameterlist!");
            }

            var body = arguments.ElementAt(2);

            var macro = new ProcedureNode(parameterList.Cast<SymbolNode>(), new[] { body }, environment.CreateChildEnvironment(), true);

            environment.DefineSymbol(symbol, macro);

            return symbol;
        }