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(); } } }
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); }
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); }
public Solver(ast.Node node, Solver context) : base(context) { limit = node; this.context = context; list = nillable; }
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); }