public void AddEnviroment(EnviromentBlock env) { envList.Insert(0, env); }
public EnviromentBlock(EnviromentBlock block) { if (block != null) { symbolTable.Clear(); foreach (var pair in block.symbolTable) { symbolTable.Add(pair.Key, pair.Value); } } }
/* * apply parameters to a lambda * create a new enviroment block, add all parameter symbol into this enviroment * then bind parameters with these symbol * for example we have symbols in upper table: TRUE = \(x,y).x; FALSE = \(x,y).y; AND = \(p,q).p q FALSE; * then we want to eval "a = AND TRUE FALSE"; we call ApplyToLambda( AND, {TRUE, FALSE}, env) * what should be done in ApplyToLambda is * 1. create new enviroment block * 2. p bind to TRUE; q bind to FALSE * 3. call ApplyToLambda(p, {q, FALSE}) which is equal to ApplyToLambda(TRUE, {FALSE, FALSE}) * do 1-3 until we meet a terminal symbol * */ private static EnviromentNode ApplyToLambda(string lambdaSymbol, EnviromentNode[] parameters, Enviroment enviroment, Enviroment closure) { EnviromentNode lambda = enviroment.LookupSymbol(lambdaSymbol); if (lambda == null) throw new Exception("unknow symbol: " + lambdaSymbol); EvalDelayEvalBlock(lambda); // bind parameter to enviroment Enviroment newEnviro = new Enviroment(enviroment); EnviromentBlock block = new EnviromentBlock(); newEnviro.AddEnviroment(block); ParseNode paramNodes = null; if (lambda.GrammerNode.Token.Type != TokenType.LAMBDA) { paramNodes = lambda.GrammerNode.Nodes[2]; } else { paramNodes = lambda.GrammerNode; } BindParameterToEnviroment(parameters, newEnviro, paramNodes.Nodes[0]); return EvalDirectFunctionCall(paramNodes.Nodes[1], newEnviro, closure); }
static void Main(string[] args) { if (!CheckInput(args)) { Die("Invalid parameters"); } if (args[0] == "-t") printGrammerTree = true; if (args[0] == "-s") printSymbolTable = true; Scanner scaner = new Scanner(); Parser parser = new Parser(scaner); ParseTree tree = parser.Parse(GetInput(args[args.Length - 1])); tree = SimplyTree(tree); if (printGrammerTree) { Console.WriteLine(tree.PrintTree()); return; } EnviromentBlock globalSymbol = new EnviromentBlock(); globalEnviroment.AddEnviroment(globalSymbol); AddIoFunctionToGlobal("return"); AddIoFunctionToGlobal("print"); AddIoFunctionToGlobal("readline"); AddBuildinFunctionToGlobal("=="); AddBuildinFunctionToGlobal("+"); AddBuildinFunctionToGlobal("-"); AddBuildinFunctionToGlobal("*"); AddBuildinFunctionToGlobal("/"); AddBuildinFunctionToGlobal("%"); EvalTree(tree, globalEnviroment); if (printSymbolTable) { Console.WriteLine(globalEnviroment.Print()); } else { RunMainFunction(); } return; }
/* * when ApplyFunction, do parameter bind like eval lambda, then eval every sentense in function body * until we met "return" * if every parameter in parameters[] occures in current enviroment, no need to create new enviroment */ static EnviromentNode ApplyFunction(EnviromentNode func, EnviromentNode[] parameters, Enviroment enviroment) { // nodes[0] == Symbol // node[1] == parameters // node[2] == function body Enviroment newEnviro = null; ParseNode paraNode = func.GrammerNode.Nodes[1]; newEnviro = new Enviroment(globalEnviroment); EnviromentBlock block = new EnviromentBlock(); newEnviro.AddEnviroment(block); // bind parameter to enviroment BindParameterToEnviroment(parameters, newEnviro, paraNode); // eval all body sentense ParseNode body = func.GrammerNode.Nodes[2]; foreach (ParseNode sentense in body.Nodes) { EnviromentNode ret = EvalSentense(sentense, newEnviro); if (ret != null && ret.Terminate) { return ret; } } return null; }