コード例 #1
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();
                }
            }
        }
コード例 #2
0
 public ast.Node EvaluateNode(ast.Node node)
 {
     if (node is ast.Path)
     {
         var path   = node as ast.Path;
         var part   = path.partList[0];
         var solver = new Solver(node, this);
         while (!solver.EvaluatePart(part))
         {
             if (0 == solver.Level)
             {
                 return(solver.Error(part));
             }
             solver.Leave();
         }
         for (var i = 1; i < path.partList.Count; i++)
         {
             part = path.partList[i];
             if (!solver.EvaluatePart(part))
             {
                 return(solver.Error(part));
             }
         }
         return(solver);
     }
     return(node);
 }
コード例 #3
0
ファイル: evaluator.cs プロジェクト: drewbanas/Monkey-CSI
        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);
            }

            // Expressions
            if (node is ast.IntegerLiteral) // Go can use a switch here!
            {
                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)
            {
                if (((ast.CallExpression)node).Function.TokenLiteral() == "quote")
                {
                    return(quote_unquote.quote(((ast.CallExpression)node).Arguments[0], env));
                }

                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);
        }
コード例 #4
0
 public Solver(ast.Node node, Solver context) : base(context)
 {
     limit        = node;
     this.context = context;
     list         = nillable;
 }
コード例 #5
0
ファイル: compiler.cs プロジェクト: drewbanas/Monkey-CSC
        public static error Compile(ast.Node node)
        {
            if (node is ast.Program)
            {
                foreach (ast.Statement s in ((ast.Program)node).Statements)
                {
                    error err = Compile(s);
                    if (err != null)
                    {
                        return(err);
                    }
                }

                return(null);
            }

            if (node is ast.ExpressionStatement)
            {
                error err = Compile(((ast.ExpressionStatement)node).Expression);
                if (err != null)
                {
                    return(err);
                }
                emit(code.OpPop);

                return(null);
            }

            if (node is ast.InfixExpression)
            {
                ast.InfixExpression _node = (ast.InfixExpression)node;
                error err;
                if (_node.Operator == "<")
                {
                    err = Compile(_node.Right);
                    if (err != null)
                    {
                        return(err);
                    }

                    err = Compile(_node.Left);
                    if (err != null)
                    {
                        return(err);
                    }

                    emit(code.OpGreaterThan);
                    return(null);
                }

                err = Compile(_node.Left);
                if (err != null)
                {
                    return(err);
                }

                err = Compile(_node.Right);
                if (err != null)
                {
                    return(err);
                }

                switch (_node.Operator)
                {
                case "+":
                    emit(code.OpAdd);
                    break;

                case "-":
                    emit(code.OpSub);
                    break;

                case "*":
                    emit(code.OpMul);
                    break;

                case "/":
                    emit(code.OpDiv);
                    break;

                case ">":
                    emit(code.OpGreaterThan);
                    break;

                case "==":
                    emit(code.OpEqual);
                    break;

                case "!=":
                    emit(code.OpNotEqual);
                    break;

                default:
                    return(string.Format("unknown operator {0}", _node.Operator));
                }

                return(null);
            }

            if (node is ast.IntegerLiteral)
            {
                Object.Integer integer = new Object.Integer {
                    Value = ((ast.IntegerLiteral)node).Value
                };
                emit(code.OpConstant, (Opcode)addConstant(integer));

                return(null);
            }

            if (node is ast.Boolean)
            {
                if (((ast.Boolean)node).Value)
                {
                    emit(code.OpTrue);
                }
                else
                {
                    emit(code.OpFalse);
                }

                return(null);
            }

            if (node is ast.PrefixExpression)
            {
                ast.PrefixExpression _node = (ast.PrefixExpression)node;
                error err = Compile(_node.Right);
                if (err != null)
                {
                    return(err);
                }

                switch (_node.Operator)
                {
                case "!":
                    emit(code.OpBang);
                    break;

                case "-":
                    emit(code.OpMinus);
                    break;

                default:
                    return(string.Format("unknown operator {0}", _node.Operator));
                }

                return(null);
            }

            if (node is ast.IfExpression)
            {
                ast.IfExpression _node = (ast.IfExpression)node;
                error            err   = Compile(_node.Condition);
                if (err != null)
                {
                    return(err);
                }

                //Emit an 'OpJumpNotTruthy' with bogus value
                int jumpNotTruthyPos = emit(code.OpJumpNotTruthy, 9999);

                err = Compile(_node.Consequence);
                if (err != null)
                {
                    return(err);
                }

                if (lastInstructionIs(code.OpPop))
                {
                    removeLastPop();
                }

                // Emit an 'OpJump' with a bogus value
                int jumpPos = emit(code.OpJump, 9999);

                int afterConsequencePos = currentInstructions().Count;
                changeOperand(jumpNotTruthyPos, afterConsequencePos);

                if (_node.Alternative == null)
                {
                    emit(code.OpNull);
                }
                else
                {
                    err = Compile(_node.Alternative);
                    if (err != null)
                    {
                        return(err);
                    }

                    if (lastInstructionIs(code.OpPop))
                    {
                        removeLastPop();
                    }
                }

                int afterAlternativePos = currentInstructions().Count;
                changeOperand(jumpPos, afterAlternativePos);

                return(null);
            }

            if (node is ast.BlockStatement)
            {
                foreach (ast.Statement s in ((ast.BlockStatement)node).Statements)
                {
                    error err = Compile(s);
                    if (err != null)
                    {
                        return(err);
                    }
                }

                return(null);
            }

            if (node is ast.LetStatement)
            {
                ast.LetStatement _node = (ast.LetStatement)node;

                symbol_table.Symbol symbol = symbol_table.Define(ref c.symbolTable, _node.Name.Value);
                error err = Compile(_node.Value);
                if (err != null)
                {
                    return(err);
                }

                if (symbol.Scope == symbol_table.GlobalScope)
                {
                    emit(code.OpSetGlobal, symbol.Index);
                }
                else
                {
                    emit(code.OpSetLocal, symbol.Index);
                }

                return(null);
            }

            if (node is ast.Identifier)
            {
                ast.Identifier _node = (ast.Identifier)node;

                symbol_table.Symbol symbol = symbol_table.Resolve(ref c.symbolTable, _node.Value);
                if (symbol == null)
                {
                    return(string.Format("undefined variable {0}", _node.Value));
                }

                loadSymbols(symbol);

                return(null);
            }

            if (node is ast.StringLiteral)
            {
                ast.StringLiteral _node = (ast.StringLiteral)node;
                Object.String     str   = new Object.String {
                    Value = _node.Value
                };
                emit(code.OpConstant, addConstant(str));

                return(null);
            }

            if (node is ast.ArrayLiteral)
            {
                ast.ArrayLiteral _node = (ast.ArrayLiteral)node;
                foreach (ast.Expression el in _node.Elements)
                {
                    error err = Compile(el);
                    if (err != null)
                    {
                        return(err);
                    }
                }

                emit(code.OpArray, _node.Elements.Count);

                return(null);
            }

            if (node is ast.HashLiteral)
            {
                ast.HashLiteral _node = (ast.HashLiteral)node;

                // the sorting is not strictly needed and was only done to pass the test
                // since the test assumes a specific order for the keys

                foreach (KeyValuePair <Expression, Expression> k in _node.Pairs)
                {
                    error err = Compile(k.Key);
                    if (err != null)
                    {
                        return(err);
                    }
                    err = Compile(_node.Pairs[k.Key]);
                    if (err != null)
                    {
                        return(err);
                    }
                }

                emit(code.OpHash, _node.Pairs.Count * 2);

                return(null);
            }

            if (node is ast.IndexExpression)
            {
                ast.IndexExpression _node = (ast.IndexExpression)node;
                error err = Compile(_node.Left);
                if (err != null)
                {
                    return(err);
                }

                err = Compile(_node.Index);
                if (err != null)
                {
                    return(err);
                }

                emit(code.OpIndex);

                return(null);
            }

            if (node is ast.FunctionLiteral)
            {
                ast.FunctionLiteral _node = (ast.FunctionLiteral)node;

                enterScope();

                if (_node.Name != null && _node.Name != "")
                {
                    symbol_table.DefineFunctionName(ref c.symbolTable, _node.Name);
                }

                foreach (ast.Identifier p in _node.Parameters)
                {
                    symbol_table.Define(ref c.symbolTable, p.Value);
                }

                error err = Compile(_node.Body);
                if (err != null)
                {
                    return(err);
                }

                if (lastInstructionIs(code.OpPop))
                {
                    replaceLastPopWithReturn();
                }
                if (!lastInstructionIs(code.OpReturnValue))
                {
                    emit(code.OpReturn);
                }

                List <symbol_table.Symbol> freeSymbols = c.symbolTable.FreeSymbols;
                int          numLocals    = c.symbolTable.numDefinitions;
                Instructions instructions = leaveScope();

                foreach (symbol_table.Symbol s in freeSymbols)
                {
                    loadSymbols(s);
                }

                Object.CompiledFunction compiledFn = new Object.CompiledFunction
                {
                    Instructions  = instructions,
                    NumLocals     = numLocals,
                    NumParameters = _node.Parameters.Count,
                };

                int fnIndex = addConstant(compiledFn);
                emit(code.OpClosure, fnIndex, freeSymbols.Count);

                return(null);
            }

            if (node is ast.ReturnStatement)
            {
                ast.ReturnStatement _node = (ast.ReturnStatement)node;
                error err = Compile(_node.ReturnValue);
                if (err != null)
                {
                    return(err);
                }

                emit(code.OpReturnValue);

                return(null);
            }

            if (node is ast.CallExpression)
            {
                ast.CallExpression _node = (ast.CallExpression)node;

                error err = Compile(_node.Function);
                if (err != null)
                {
                    return(err);
                }

                foreach (Expression a in _node.Arguments)
                {
                    err = Compile(a);
                    if (err != null)
                    {
                        return(err);
                    }
                }

                emit(code.OpCall, _node.Arguments.Count);
                return(null);
            }

            return(null);
        }