/* * 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); }
/* * 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; }