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(); } }
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); }
public static Object.Object quote(ast.Node node, Object.Environment env) { node = evalUnquoteCalls(node, env); return(new Object.Quote { Node = node }); }
static bool isUnquoteCall(ast.Node node) { if (!(node is ast.CallExpression)) { return(false); } ast.CallExpression callExpression = (ast.CallExpression)node; return(callExpression.Function.TokenLiteral() == "unquote"); }
private static Object.Environment _env; // to pass the environment on the originally crammed-to-argument function definition static ast.Node _evalUnquotedCalss(ast.Node node) { if (!isUnquoteCall(node)) { return(node); } if (!(node is ast.CallExpression)) { return(node); } ast.CallExpression call = (ast.CallExpression)node; if (call.Arguments.Count != 1) { return(node); } Object.Object unquoted = evaluator.Eval(call.Arguments[0], _env); // env needs to reach this return(convertObjectToASTNode(unquoted)); }
public static ast.Node ExpandMacros(ast.Node program, Object.Environment env) { _env = env; return(ast.modify.Modify(program, _ExpandMacros)); }
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); }
public static ast.Node evalUnquoteCalls(ast.Node quoted, Object.Environment env) { _env = env; return(ast.modify.Modify(quoted, _evalUnquotedCalss)); }
public static ast.Node Modify(ast.Node node, MofifierFunc modifier) { if (node is ast.Program) { ast.Program _node = (ast.Program)node; for (int i = 0; i < _node.Statements.Count; i++) { _node.Statements[i] = (ast.Statement)Modify(_node.Statements[i], modifier); } node = _node; } if (node is ast.ExpressionStatement) { ast.ExpressionStatement _node = (ast.ExpressionStatement)node; _node.Expression = (ast.Expression)Modify(_node.Expression, modifier); node = _node; } if (node is ast.InfixExpression) { ast.InfixExpression _node = (ast.InfixExpression)node; _node.Left = (ast.Expression)Modify(_node.Left, modifier); _node.Right = (ast.Expression)Modify(_node.Right, modifier); node = _node; } if (node is ast.PrefixExpression) { ast.PrefixExpression _node = (ast.PrefixExpression)node; _node.Right = (ast.Expression)Modify(_node.Right, modifier); node = _node; } if (node is ast.IndexExpression) { ast.IndexExpression _node = (ast.IndexExpression)node; _node.Left = (ast.Expression)Modify(_node.Left, modifier); _node.Index = (ast.Expression)Modify(_node.Index, modifier); node = _node; } if (node is ast.IfExpression) { ast.IfExpression _node = (ast.IfExpression)node; _node.Condition = (ast.Expression)Modify(_node.Condition, modifier); _node.Consequence = (ast.BlockStatement)Modify(_node.Consequence, modifier); node = _node; if (_node.Alternative != null) { _node.Alternative = (ast.BlockStatement)Modify(_node.Alternative, modifier); } } if (node is ast.BlockStatement) { ast.BlockStatement _node = (ast.BlockStatement)node; for (int i = 0; i < _node.Statements.Count; i++) { _node.Statements[i] = (ast.Statement)Modify(_node.Statements[i], modifier); } node = _node; } if (node is ast.ReturnStatement) { ast.ReturnStatement _node = (ast.ReturnStatement)node; _node.ReturnValue = (ast.Expression)Modify(_node.ReturnValue, modifier); node = _node; } if (node is ast.LetStatement) { ast.LetStatement _node = (ast.LetStatement)node; _node.Value = (ast.Expression)Modify(_node.Value, modifier); node = _node; } if (node is ast.FunctionLiteral) { ast.FunctionLiteral _node = (ast.FunctionLiteral)node; for (int i = 0; i < _node.Parameters.Count; i++) { _node.Parameters[i] = (ast.Identifier)Modify(_node.Parameters[i], modifier); } _node.Body = (ast.BlockStatement)Modify(_node.Body, modifier); node = _node; } if (node is ast.ArrayLiteral) { ast.ArrayLiteral _node = (ast.ArrayLiteral)node; for (int i = 0; i < _node.Elements.Count; i++) { _node.Elements[i] = (ast.Expression)Modify(_node.Elements[i], modifier); } node = _node; } if (node is ast.HashLiteral) { ast.HashLiteral _node = (ast.HashLiteral)node; Dictionary <ast.Expression, ast.Expression> newPairs = new Dictionary <ast.Expression, ast.Expression>(); foreach (KeyValuePair <ast.Expression, ast.Expression> kv in _node.Pairs) { ast.Expression newKey = (ast.Expression)Modify(kv.Key, modifier); ast.Expression newVal = (ast.Expression)Modify(kv.Value, modifier); newPairs.Add(newKey, newVal); } _node.Pairs = newPairs; node = _node; } return(modifier(node)); }