예제 #1
0
 public static Object.Object quote(ast.Node node, Object.Environment env)
 {
     node = evalUnquoteCalls(node, env);
     return(new Object.Quote {
         Node = node
     });
 }
예제 #2
0
        public static void Start()
        {
            Object.Environment env      = Object.Environment.NewEnvironment();
            Object.Environment macroEnv = Object.Environment.NewEnvironment();

            for (;;)
            {
                System.Console.Write(PROMPT);
                string line = System.Console.ReadLine();

                lexer.Lexer   l = lexer.Lexer.New(line);
                parser.Parser p = parser.Parser.New(l);

                ast.Program program = p.ParseProgram();
                if (parser.Parser.Errors().Count != 0)
                {
                    printParserErrors(parser.Parser.Errors());
                    continue;
                }

                evaluator.macro_expansion.DefineMacros(program, macroEnv);
                ast.Node expanded = evaluator.macro_expansion.ExpandMacros(program, macroEnv);

                Object.Object evaluated = evaluator.evaluator.Eval(expanded, env);
                if (evaluated != null)
                {
                    System.Console.Write(evaluated.Inspect());
                    System.Console.WriteLine();
                }
            }
        }
예제 #3
0
        public static void Start(TextReader reader, TextWriter writer)
        {
            var env = new Object.Environment();

            while (true)
            {
                writer.Write(_PROMPT);
                var input = reader.ReadLine();
                if (string.IsNullOrWhiteSpace(input))
                {
                    return;
                }
                try
                {
                    var           lexer     = Lexer.Create(input);
                    var           parser    = new Parser(lexer);
                    var           program   = parser.ParseProgram();
                    Object.Object evaluated = Evaluator.Eval(program, env);
                    if (evaluated != null)
                    {
                        writer.Write(evaluated.Inspect());
                        writer.Write(Environment.NewLine);
                    }
                }
                catch (ParserException e)
                {
                    writer.Write(e.Message);
                    writer.Write(Environment.NewLine);
                }
            }
        }
예제 #4
0
        static ast.Node _ExpandMacros(ast.Node node)
        {
            if (!(node is ast.CallExpression))
            {
                return(node);
            }
            ast.CallExpression callExpression = (ast.CallExpression)node;

            Object.Macro macro = isMacroCall(callExpression, _env);
            if (macro == null)
            {
                return(node);
            }

            List <Object.Quote> args = quoteArgs(callExpression);

            Object.Environment evalEnv = extendMacroEnv(macro, args);

            Object.Object evaluated = evaluator.Eval(macro.Body, evalEnv);
            if (!(evaluated is Object.Quote))
            {
                System.Console.WriteLine("we only support returning AST-nodes from macros");
                System.Environment.Exit(-1);
            }
            Object.Quote quote = (Object.Quote)evaluated;

            return(quote.Node);
        }
예제 #5
0
        static Object.Object evalHashLiteral(ast.HashLiteral node, Object.Environment env)
        {
            Dictionary <Object.HashKey, Object.HashPair> pairs = new Dictionary <Object.HashKey, Object.HashPair>();

            foreach (KeyValuePair <ast.Expression, ast.Expression> _node_pair in node.Pairs)
            {
                Object.Object key = Eval(_node_pair.Key, env);
                if (isError(key))
                {
                    return(key);
                }

                if (!(key is Object.Hashable))
                {
                    return(newError("unusable as hash key: {0}", key.Type()));
                }
                Object.Hashable hashKey = (Object.Hashable)key;

                Object.Object value = Eval(_node_pair.Value, env);
                if (isError(value))
                {
                    return(value);
                }

                Object.HashKey hashed = hashKey.HashKey();
                pairs.Add(hashed, new Object.HashPair {
                    Key = key, Value = value
                });
            }

            return(new Object.Hash {
                Pairs = pairs
            });
        }
예제 #6
0
        private static Object.Object EvalHashLiteral(HashLiteral node, Object.Environment env)
        {
            var pairs = new Dictionary <HashKey, HashPair>();

            foreach (KeyValuePair <Expression, Expression> pair in node.Pairs)
            {
                Object.Object key = Eval(pair.Key, env);
                if (IsError(key))
                {
                    return(key);
                }
                var hashKey = key as IHash;
                if (hashKey == null)
                {
                    return(new Error {
                        Message = $"unusable as hash key: {key.Type()}"
                    });
                }
                var value = Eval(pair.Value, env);
                if (IsError(value))
                {
                    return(value);
                }
                var hashed = hashKey.HashKey();
                pairs.Add(hashed, new HashPair {
                    Key = key, Value = value
                });
            }
            return(new Hash {
                Pairs = pairs
            });
        }
예제 #7
0
        private static void runFile(string path) // REPL without the loop
        {
            Object.Environment env      = Object.Environment.NewEnvironment();
            Object.Environment macroEnv = Object.Environment.NewEnvironment();

            string source = readFile(path);

            lexer.Lexer   l = lexer.Lexer.New(source);
            parser.Parser p = parser.Parser.New(l);

            ast.Program program = p.ParseProgram();
            if (parser.Parser.Errors().Count != 0)
            {
                repl.printParserErrors(parser.Parser.Errors());
                System.Environment.Exit(77);
            }

            evaluator.macro_expansion.DefineMacros(program, macroEnv);
            ast.Node expanded = evaluator.macro_expansion.ExpandMacros(program, macroEnv);

            Object.Object evaluated = evaluator.evaluator.Eval(expanded, env);
            if (evaluated != null)
            {
                System.Console.Write(evaluated.Inspect());
                System.Console.WriteLine();
            }
        }
예제 #8
0
        private static Object.Environment extendFunctionEnv(Function fn, IImmutableList <MonkeyObject> args)
        {
            var env = new Object.Environment(fn.Env);

            for (int i = 0; i < fn.Parameters.Count; i++)
            {
                env.Set(fn.Parameters[i].Value, args[i]);
            }

            return(env);
        }
예제 #9
0
        static Object.Environment extendFunctionEnv(Object.Function fn, List <Object.Object> args)
        {
            Object.Environment env = Object.Environment.NewEnclosedEnvironment(fn.Env);

            for (int paramIdx = 0; paramIdx < args.Count; paramIdx++)
            {
                env.Set(fn.Parameters[paramIdx].Value, args[paramIdx]);
            }

            return(env);
        }
예제 #10
0
        private static Object.Environment ExtendFuncitonEnv(Object.Function function, IEnumerable <Object.Object> args)
        {
            var env = new Object.Environment(function.Env);
            var idx = 0;

            foreach (var arg in args)
            {
                env.Set(function.Parameters[idx].Value, arg);
                idx++;
            }
            return(env);
        }
예제 #11
0
        static Object.Environment extendMacroEnv(Object.Macro macro, List <Object.Quote> args)
        {
            Object.Environment extended = Object.Environment.NewEnclosedEnvironment(macro.Env);

            int paramIdx = 0;

            foreach (ast.Identifier param in macro.Parameters)
            {
                extended.Set(param.Value, args[paramIdx++]);
            }

            return(extended);
        }
예제 #12
0
        static void addMacro(ast.Statement stmt, Object.Environment env)
        {
            ast.LetStatement letStatement = (ast.LetStatement)stmt;
            ast.MacroLiteral macroLiteral = (ast.MacroLiteral)letStatement.Value;

            Object.Macro macro = new Object.Macro
            {
                Parameters = macroLiteral.Parameters,
                Env        = env,
                Body       = macroLiteral.Body
            };

            env.Set(letStatement.Name.Value, macro);
        }
예제 #13
0
 private static Object.Object EvalIdentifier(Ast.Identifier node, Object.Environment env)
 {
     if (env.Exist(node.Value))
     {
         return(env.Get(node.Value));
     }
     if (builtins.ContainsKey(node.Value))
     {
         return(builtins[node.Value]);
     }
     return(new Object.Error {
         Message = $"identifier not found: {node.Value}"
     });
 }
예제 #14
0
        private static MonkeyObject evalIdentifier(Identifier id, Object.Environment environment)
        {
            if (environment.Get(id.Value, out var value))
            {
                return(value);
            }

            if (Builtins.builtins.TryGetValue(id.Value, out var builtin))
            {
                return(builtin);
            }

            return(new MonkeyError {
                Message = $"identifier not found: {id.Value}"
            });
        }
예제 #15
0
        static Object.Object evalIdentifier(ast.Identifier node, Object.Environment env)
        {
            Object.Object val = env.Get(node.Value);
            if (val != null)
            {
                return(val);
            }

            Object.Builtin builtin;
            if (evaluator_builtins.builtins.TryGetValue(node.Value, out builtin))
            {
                return(builtin);
            }

            return(newError("identifier not found: " + node.Value));;
        }
예제 #16
0
        static Object.Object applyFunction(Object.Object fn, List <Object.Object> args)
        {
            if (fn is Object.Function)
            {
                Object.Environment extendedEnv = extendFunctionEnv(((Object.Function)fn), args);
                Object.Object      evaluated   = Eval(((Object.Function)fn).Body, extendedEnv);
                return(unwrapReturnValue(evaluated));
            }

            if (fn is Object.Builtin)
            {
                return(((Object.Builtin)fn).Fn(args));
            }

            // default:
            return(newError("not a function {0}", fn.Type()));
        }
예제 #17
0
 private static Object.Object EvalProgram(Ast.Program program, Object.Environment env)
 {
     Object.Object result = null;
     foreach (var statement in program.Statements)
     {
         result = Eval(statement, env);
         if (result is Object.ReturnValue)
         {
             return((result as Object.ReturnValue).Value);
         }
         if (result is Object.Error)
         {
             return(result as Object.Error);
         }
     }
     return(result);
 }
예제 #18
0
 private static Object.Object EvalBlockStatement(Ast.BlockStatement block, Object.Environment env)
 {
     Object.Object result = null;
     foreach (var statement in block.Statements)
     {
         result = Eval(statement, env);
         if (result != null)
         {
             var rt = result.Type();
             if (rt == Object.ObjectType.RETURN_VALUE_OBJ || rt == Object.ObjectType.ERROR_OBJ)
             {
                 return(result);
             }
         }
     }
     return(result);
 }
예제 #19
0
        static List <Object.Object> evalExpressions(List <ast.Expression> exps, Object.Environment env)
        {
            List <Object.Object> result = new List <Object.Object>();

            foreach (ast.Node e in exps)
            {
                Object.Object evaluated = Eval(e, env);
                if (isError(evaluated))
                {
                    return(new List <Object.Object> {
                        evaluated
                    });
                }
                result.Add(evaluated);
            }

            return(result);
        }
예제 #20
0
        static Object.Object evalBlockStatement(ast.BlockStatement block, Object.Environment env)
        {
            Object.Object result = null;

            foreach (ast.Statement statement in block.Statements)
            {
                result = Eval(statement, env);

                if (result != null)
                {
                    string rt = result.Type();
                    if (rt == Object._ObjType.RETURN_VALUE_OBJ || rt == Object._ObjType.ERROR_OBJ)
                    {
                        return(result);
                    }
                }
            }

            return(result);
        }
예제 #21
0
        public static void DefineMacros(ast.Program program, Object.Environment env)
        {
            List <int> defenitions = new List <int>();

            for (int i = 0; i < program.Statements.Count; i++)
            {
                ast.Statement statement = program.Statements[i];
                if (isMacroDefenition(statement))
                {
                    addMacro(statement, env);
                    defenitions.Add(i++);
                }
            }

            for (int i = defenitions.Count - 1; i >= 0; i--)
            {
                int defenitionIndex = defenitions[i];
                program.Statements.RemoveAt(defenitionIndex);
            }
        }
예제 #22
0
 private static Object.Object EvalIfExpression(Ast.IfExpression exp, Object.Environment env)
 {
     Object.Object condition = Eval(exp.Condition, env);
     if (IsError(condition))
     {
         return(condition);
     }
     if (IsTruthy(condition))
     {
         return(Eval(exp.Consequence, env));
     }
     else if (exp.Alternative != null)
     {
         return(Eval(exp.Alternative, env));
     }
     else
     {
         return(NULL);
     }
 }
예제 #23
0
        private static MonkeyObject evalIfExpression(IfExpression ifx, Object.Environment environment)
        {
            var condition = Eval(ifx.Condition, environment);

            if (condition?.Type == MonkeyObjectType.ERROR)
            {
                return(condition);
            }

            if (condition.IsTruthy())
            {
                return(Eval(ifx.Consequence, environment));
            }

            if (ifx.Alternative != null)
            {
                return(Eval(ifx.Alternative, environment));
            }

            return(NULL);
        }
예제 #24
0
        static Object.Object evalIfExpression(ast.IfExpression ie, Object.Environment env)
        {
            Object.Object contion = Eval(ie.Condition, env);
            if (isError(contion))
            {
                return(contion);
            }

            if (isTruthy(contion))
            {
                return(Eval(ie.Consequence, env));
            }
            else if (ie.Alternative != null)
            {
                return(Eval(ie.Alternative, env));
            }
            else
            {
                return(NULL);
            }
        }
예제 #25
0
        static Object.Object evalProgram(ast.Program program, Object.Environment env)
        {
            Object.Object result = null;

            foreach (ast.Statement statement in program.Statements)
            {
                result = Eval(statement, env);

                if (result is Object.ReturnValue)
                {
                    return(((Object.ReturnValue)result).Value);
                }

                if (result is Object.Error)
                {
                    return(result);
                }
            }

            return(result);
        }
예제 #26
0
        static Object.Macro isMacroCall(ast.CallExpression exp, Object.Environment env)
        {
            if (!(exp.Function is ast.Identifier))
            {
                return(null);
            }
            ast.Identifier identifier = (ast.Identifier)exp.Function;

            Object.Object obj = env.Get(identifier.Value);
            if (obj == null)
            {
                return(null);
            }

            if (!(obj is Object.Macro))
            {
                return(null);
            }
            Object.Macro macro = (Object.Macro)obj;

            return(macro);
        }
예제 #27
0
        private static MonkeyObject evalProgram(Program p, Object.Environment environment)
        {
            MonkeyObject result = NULL;

            foreach (var statement in p.Statements)
            {
                result = Eval(statement, environment);

                switch (result)
                {
                case MonkeyReturnValue rv:
                    return(rv.Value);

                case MonkeyError:
                    return(result);

                default:
                    break;
                }
            }

            return(result);
        }
예제 #28
0
        private static MonkeyObject evalHashLiteral(HashLiteral hl, Object.Environment environment)
        {
            var pairs = new Dictionary <HashKey, HashPair>();

            foreach (var(keyNode, valueNode) in hl.Pairs)
            {
                var key = Eval(keyNode, environment);
                if (key?.Type == MonkeyObjectType.ERROR)
                {
                    return(key);
                }

                if (!(key is Hashable))
                {
                    return(new MonkeyError {
                        Message = $"unusable as hash key: {key.Type}"
                    });
                }

                var hashKey = key as Hashable;
                var value   = Eval(valueNode, environment);
                if (value?.Type == MonkeyObjectType.ERROR)
                {
                    return(value);
                }

                var hashed = hashKey.HashKey();
                pairs.Add(hashed, new HashPair {
                    Key = key, Value = value
                });
            }

            return(new MonkeyHash {
                Pairs = pairs
            });
        }
예제 #29
0
        public static Object.Object Eval(ast.Node node, Object.Environment env)
        {
            // Statements
            if (node is ast.Program)
            {
                return(evalProgram((ast.Program)node, env));
            }

            if (node is ast.BlockStatement)
            {
                return(evalBlockStatement((ast.BlockStatement)node, env));
            }

            if (node is ast.ExpressionStatement)
            {
                return(Eval(((ast.ExpressionStatement)node).Expression, env));
            }

            if (node is ast.ReturnStatement)
            {
                Object.Object val = Eval(((ast.ReturnStatement)node).ReturnValue, env);
                if (isError(val))
                {
                    return(val);
                }
                return(new Object.ReturnValue {
                    Value = val
                });
            }

            if (node is ast.LetStatement)
            {
                Object.Object val = Eval(((ast.LetStatement)node).Value, env);
                if (isError(val))
                {
                    return(val);
                }
                env.Set(((ast.LetStatement)node).Name.Value, val);

                return(null);
            }

            // Expressions
            if (node is ast.IntegerLiteral)
            {
                return new Object.Integer {
                           Value = ((ast.IntegerLiteral)node).Value
                }
            }
            ;

            if (node is ast.StringLiteral)
            {
                return new Object.String {
                           Value = ((ast.StringLiteral)node).Value
                }
            }
            ;

            if (node is ast.Boolean)
            {
                return(nativeToBooleanObject(((ast.Boolean)node).Value));
            }

            if (node is ast.PrefixExpression)
            {
                Object.Object right = Eval(((ast.PrefixExpression)node).Right, env);
                if (isError(right))
                {
                    return(right);
                }
                return(evalPrefixExpression(((ast.PrefixExpression)node).Operator, right));
            }

            if (node is ast.InfixExpression)
            {
                Object.Object left = Eval(((ast.InfixExpression)node).Left, env);
                if (isError(left))
                {
                    return(left);
                }

                Object.Object right = Eval(((ast.InfixExpression)node).Right, env);
                if (isError(right))
                {
                    return(right);
                }

                return(evalInfixExpression(((ast.InfixExpression)node).Operator, left, right));
            }


            if (node is ast.IfExpression)
            {
                return(evalIfExpression((ast.IfExpression)node, env));
            }


            if (node is ast.Identifier)
            {
                return(evalIdentifier((ast.Identifier)node, env));
            }

            if (node is ast.FunctionLiteral)
            {
                List <ast.Identifier> params_ = ((ast.FunctionLiteral)node).Parameters;
                ast.BlockStatement    body    = ((ast.FunctionLiteral)node).Body;
                return(new Object.Function {
                    Parameters = params_, Env = env, Body = body
                });
            }

            if (node is ast.CallExpression)
            {
                Object.Object function = Eval(((ast.CallExpression)node).Function, env);
                if (isError(function))
                {
                    return(function);
                }

                List <Object.Object> args = evalExpressions(((ast.CallExpression)node).Arguments, env);
                if (args.Count == 1 && isError(args[0]))
                {
                    return(args[0]);
                }

                return(applyFunction(function, args));
            }

            if (node is ast.ArrayLiteral)
            {
                List <Object.Object> elements = evalExpressions(((ast.ArrayLiteral)node).Elements, env);
                if (elements.Count == 1 && isError(elements[0]))
                {
                    return(elements[0]);
                }
                return(new Object.Array {
                    Elements = elements
                });
            }

            if (node is ast.IndexExpression)
            {
                Object.Object left = Eval(((ast.IndexExpression)node).Left, env);
                if (isError(left))
                {
                    return(left);
                }
                Object.Object index = Eval(((ast.IndexExpression)node).Index, env);
                if (isError(index))
                {
                    return(index);
                }
                return(evalIndexExpression(left, index));
            }

            if (node is ast.HashLiteral)
            {
                return(evalHashLiteral((ast.HashLiteral)node, env));
            }

            return(null);
        }
예제 #30
0
 public static ast.Node ExpandMacros(ast.Node program, Object.Environment env)
 {
     _env = env;
     return(ast.modify.Modify(program, _ExpandMacros));
 }