Exemplo n.º 1
0
        /*
         * eval sentense like " AND TRUE FALSE"
         * parameters can be another function call, like AND (AND TRUE TRUE) FALSE
         * currently eval all parameters before apply to functor
         * if parameter ( and after eval function all ) does not exist in enviroment, just leave a symbol in it
         * in order to support IO, add special functor type __io__, which evals special, need to do IOs internally
         * and in order to support function, add special functor type __function__
         * when eval __function__, eval sentenses inside this function until we met a "return"
         * if a lambda like \(x,y).x , say only one element in body, it's a terminal symbol
         * else treate first elememt in body as a functor and eval it
         */
        private static EnviromentNode EvalDirectFunctionCall(ParseNode node, Enviroment enviroment, Enviroment closure)
        {
            // nodes[0] == 'var'
            // nodes[1] == symbol
            // nodes[2] == function body
            if (node.Nodes.Count < 1)
                throw new Exception("invalid direct function call");
            ParseNode funcBody = node;
            string lambdaSymbol = funcBody.Nodes[0].Token.Text;

            EnviromentNode funcNode = closure.LookupSymbol(lambdaSymbol);
            if (funcNode == null)
                funcNode = enviroment.LookupSymbol(lambdaSymbol);

            // before apply parameters to a lambda, eval functor to get a result
            EvalDelayEvalBlock(funcNode);

            /*
             * sentense like
             * var a = \(x,y).x TRUE FALSE
             * FIXME
             */

            EnviromentNode[] parameters = new EnviromentNode[funcBody.Nodes.Count - 1];
            for (int index = 1; index < funcBody.Nodes.Count; index++)
            {

                ParseNode paramNode = funcBody.Nodes[index];
                if (paramNode.Token.Type == TokenType.FUNCTION || paramNode.Token.Type == TokenType.IFTHENELSE )
                {
                    // parameters[index - 1] = EvalDirectFunctionCall(funcBody.Nodes[index], enviroment, null);
                    DelayEvalBlock block = new DelayEvalBlock(funcBody.Nodes[index], enviroment);
                    parameters[index - 1] = new EnviromentNode(enviroment);
                    parameters[index - 1].AddDelayEvalBlock(block);
                }
                else
                {
                    Token token = funcBody.Nodes[index].Token;
                    EnviromentNode tmp = null;
                    if (token.Type == TokenType.DIGIT)
                    {
                        // like foo 12;
                        tmp = new EnviromentNode(enviroment);
                        tmp.IValue = Int32.Parse(token.Text);
                        tmp.ValueType = "int";
                    }
                    else if (token.Type == TokenType.STRINGVAL)
                    {
                        // like foo "hello";
                        tmp = new EnviromentNode(enviroment);
                        tmp.SValue = token.Text.Substring(1, token.Text.Length - 2);
                        tmp.ValueType = "string";
                    }
                    else if (token.Type == TokenType.LAMBDA)
                    {
                        /*
                         * sentense like
                         * return \(x,y).x
                         * foo \(x,y).x FALSE
                         */
                        tmp = new EnviromentNode(enviroment);
                        tmp.Type = GetTypeString(funcBody.Nodes[index], null);
                        tmp.Value = GetValueOfLambda(funcBody.Nodes[index]);
                        tmp.GrammerNode = funcBody.Nodes[index];
                        tmp.ValueType = "lambda";
                    }
                    else
                    {
                        // like foo a b;
                        tmp = enviroment.LookupSymbol(token.Text);
                        if (tmp == null)
                        {
                            tmp = new EnviromentNode(null);
                            tmp.Symbol = token.Text;
                        }
                    }

                    parameters[index - 1] = tmp;
                }
            }
            EnviromentNode result = null;

            if (funcNode.Type == "__io__")
            {
                result = ApplyIO(funcNode, parameters, enviroment);
            }
            else if (funcNode.Type == "__function__")
            {
                result = ApplyFunction(funcNode, parameters, enviroment);
            }
            else if (funcNode.Type == "__buildin__")
            {
                result = ApplyBuildinFunction(funcNode, parameters, enviroment);
            }
            else // lambda
            {
                if (parameters.Length == 0)
                {
                    result = closure.LookupSymbol(lambdaSymbol);
                    if (result == null)
                        result = enviroment.LookupSymbol(lambdaSymbol);
                }
                else
                    result = ApplyToLambda(lambdaSymbol, parameters, enviroment, funcNode.Enviroment);
            }

            return result;
        }
Exemplo n.º 2
0
        /*
         * 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);
        }