public static Object.Object quote(ast.Node node, Object.Environment env) { node = evalUnquoteCalls(node, env); return(new Object.Quote { Node = node }); }
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 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); } } }
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); }
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 }); }
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 }); }
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(); } }
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); }
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); }
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); }
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); }
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); }
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}" }); }
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}" }); }
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));; }
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())); }
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); }
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); }
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); }
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); }
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); } }
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); } }
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); }
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); } }
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); }
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); }
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); }
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 }); }
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 ExpandMacros(ast.Node program, Object.Environment env) { _env = env; return(ast.modify.Modify(program, _ExpandMacros)); }