示例#1
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);
        }
示例#2
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);
        }
示例#3
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);
        }
示例#4
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);
        }
示例#5
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);
        }
示例#6
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);
        }
示例#7
0
 public static Object.Object Eval(Ast.Node node, Object.Environment env)
 {
     if (node is Ast.Program)
     {
         return(EvalProgram((Ast.Program)node, env));
     }
     if (node is Ast.ExpressionStatement)
     {
         return(Eval(((Ast.ExpressionStatement)node).Expression, env));
     }
     if (node is Ast.IntegerLiteral)
     {
         return(new Object.Integer {
             Value = ((Ast.IntegerLiteral)node).Value
         });
     }
     if (node is Ast.Boolean)
     {
         return(NativeBoolToBooleanObject(((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.BlockStatement)
     {
         return(EvalBlockStatement((Ast.BlockStatement)node, env));
     }
     if (node is Ast.IfExpression)
     {
         return(EvalIfExpression((Ast.IfExpression)node, 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);
     }
     if (node is Ast.Identifier)
     {
         return(EvalIdentifier((Ast.Identifier)node, env));
     }
     if (node is Ast.FunctionLiteral)
     {
         Ast.FunctionLiteral func = node as Ast.FunctionLiteral;
         return(new Object.Function {
             Parameters = func.Parameters, Env = env, Body = func.Body
         });
     }
     if (node is Ast.CallExpression)
     {
         Object.Object function = Eval(((Ast.CallExpression)node).Function, env);
         if (IsError(function))
         {
             return(function);
         }
         var args = EvalExpressions(((Ast.CallExpression)node).Arguments, env);
         if (args.Count() == 1 && IsError(args.First()))
         {
             return(args.First());
         }
         return(ApplyFunction(function, args));
     }
     if (node is StringLiteral)
     {
         return(new Object.Strings {
             Value = ((StringLiteral)node).Value
         });
     }
     if (node is ArrayLiteral)
     {
         var elements = EvalExpressions(((ArrayLiteral)node).Elements, env);
         if (elements.Count == 1 && IsError(elements[0]))
         {
             return(elements.First());
         }
         return(new Object.Array {
             Elements = elements
         });
     }
     if (node is IndexExpression)
     {
         Object.Object left = Eval(((IndexExpression)node).Left, env);
         if (IsError(left))
         {
             return(left);
         }
         Object.Object index = Eval(((IndexExpression)node).Index, env);
         if (IsError(index))
         {
             return(index);
         }
         return(EvalIndexExpression(left, index));
     }
     if (node is HashLiteral)
     {
         return(EvalHashLiteral(node as HashLiteral, env));
     }
     return(null);
 }
示例#8
0
        public static MonkeyObject Eval(AST.Node node, Object.Environment environment)
        {
            MonkeyObject left;
            MonkeyObject index;
            MonkeyObject val;

            switch (node)
            {
            case AST.Program p:
                return(evalProgram(p, environment));

            case AST.BlockStatement bs:
                return(evalBlockStatement(bs, environment));

            case AST.ExpressionStatement xs:
                return(Eval(xs.Expression, environment));

            case AST.LetStatement ls:
                val = Eval(ls.Value, environment);
                if (val?.Type == MonkeyObjectType.ERROR)
                {
                    return(val);
                }

                environment.Set(ls.Name.Value, val);
                break;

            case AST.ReturnStatement rs:
                val = Eval(rs.ReturnValue, environment);
                if (val?.Type == MonkeyObjectType.ERROR)
                {
                    return(val);
                }

                return(new MonkeyReturnValue {
                    Value = val
                });

            case AST.HashLiteral hl:
                return(evalHashLiteral(hl, environment));

            case AST.ArrayLiteral al:
                var elements = evalExpressions(al.Elements, environment);
                if (elements.Count == 1 && elements[0]?.Type == MonkeyObjectType.ERROR)
                {
                    return(elements[0]);
                }
                return(new MonkeyArray {
                    Elements = elements
                });

            case AST.FunctionLiteral fl:
                return(new Object.Function {
                    Parameters = fl.Parameters, Env = environment, Body = fl.Body
                });

            case AST.IfExpression ifx:
                return(evalIfExpression(ifx, environment));

            case AST.CallExpression cl:
                var function = Eval(cl.Function, environment);
                if (function?.Type == MonkeyObjectType.ERROR)
                {
                    return(function);
                }

                var args = evalExpressions(cl.Arguments, environment);
                if (args.Count == 1 && args[0]?.Type == MonkeyObjectType.ERROR)
                {
                    return(args[0]);
                }

                return(applyFunction(function, args));

            case AST.InfixExpression ix:
                left = Eval(ix.Left, environment);
                if (left?.Type == MonkeyObjectType.ERROR)
                {
                    return(left);
                }

                index = Eval(ix.Right, environment);
                if (index?.Type == MonkeyObjectType.ERROR)
                {
                    return(index);
                }

                return(evalInfixExpression(ix.Op, left, index));

            case AST.PrefixExpression px:
                index = Eval(px.Right, environment);
                if (index?.Type == MonkeyObjectType.ERROR)
                {
                    return(index);
                }

                return(evalPrefixExpression(px.Op, index));

            case AST.IndexExpression idx:
                left = Eval(idx.Left, environment);
                if (left?.Type == MonkeyObjectType.ERROR)
                {
                    return(left);
                }

                index = Eval(idx.Index, environment);
                if (index?.Type == MonkeyObjectType.ERROR)
                {
                    return(index);
                }
                return(evalIndexExpression(left, index));

            case AST.IntegerLiteral il:
                return(new MonkeyInteger {
                    Value = il.Value
                });

            case AST.BooleanExpression b:
                return(nativeBoolToMonkeyBoolean(b.Value));

            case AST.Identifier id:
                return(evalIdentifier(id, environment));

            case AST.StringLiteral sl:
                return(new MonkeyString {
                    Value = sl.Value
                });
            }

            return(null);
        }