Exemplo n.º 1
0
        /*
         * the operator == + - * / % are buildin
         * + - * / % only for int value
         */
        private static EnviromentNode ApplyBuildinFunction(EnviromentNode funcNode, EnviromentNode[] parameters, Enviroment enviroment)
        {
            EnviromentNode retNode = new EnviromentNode(enviroment);

            foreach (EnviromentNode node in parameters)
            {
                EvalDelayEvalBlock(node);
            }
            if (funcNode.Symbol == "==")
            {
                if (parameters.Length < 2 )
                    throw new Exception("invalid parameters for ==, different value type");
                retNode.ValueType = "int";
                retNode.IValue = (parameters[0].Equals(parameters[1])) ? 1 : 0;
            }
            else if( funcNode.Symbol == "+")
            {
                if (parameters.Length < 2 || parameters[0].ValueType != "int" || parameters[1].ValueType != "int")
                    throw new Exception("invalid parameters for ==, different value type");
                retNode.ValueType = "int";
                retNode.IValue = parameters[0].IValue + parameters[1].IValue;
            }
            else if( funcNode.Symbol == "-")
            {
                if (parameters.Length < 2 || parameters[0].ValueType != "int" || parameters[1].ValueType != "int")
                    throw new Exception("invalid parameters for ==, different value type");
                retNode.ValueType = "int";
                retNode.IValue = parameters[0].IValue - parameters[1].IValue;
            }
            else if( funcNode.Symbol == "*")
            {
                if (parameters.Length < 2 || parameters[0].ValueType != "int" || parameters[1].ValueType != "int")
                    throw new Exception("invalid parameters for ==, different value type");
                retNode.ValueType = "int";
                retNode.IValue = parameters[0].IValue * parameters[1].IValue;
            }
            else if( funcNode.Symbol == "/")
            {
                if (parameters.Length < 2 || parameters[0].ValueType != "int" || parameters[1].ValueType != "int")
                    throw new Exception("invalid parameters for ==, different value type");
                retNode.ValueType = "int";
                retNode.IValue = parameters[0].IValue / parameters[1].IValue;
            }
            else if( funcNode.Symbol == "%")
            {
                if (parameters.Length < 2 || parameters[0].ValueType != "int" || parameters[1].ValueType != "int")
                    throw new Exception("invalid parameters for ==, different value type");
                retNode.ValueType = "int";
                retNode.IValue = parameters[0].IValue % parameters[1].IValue;
            }
            else
            {
                throw new NotImplementedException();
            }

            retNode.Symbol = "__tmp__" + enviroment.TopCount().ToString();
            return retNode;
        }
Exemplo n.º 2
0
 public Enviroment(Enviroment src)
 {
     if (src != null)
     {
         envList.Clear();
         foreach (EnviromentBlock block in src.envList)
         {
             envList.Add(new EnviromentBlock(block));
         }
     }
 }
Exemplo n.º 3
0
 public DelayEvalBlock(ParseNode node, Enviroment env)
 {
     this.node = node;
     this.enviroment = new Enviroment(env);
 }
Exemplo n.º 4
0
        private static void EvalVarSentense(ParseNode node, Enviroment enviroment,
            EnviromentNode envNode)
        {
            envNode.Symbol = node.Nodes[1].Token.Text;
            if (node.Nodes[2].Token.Type == TokenType.FUNCTION)
            {
                EnviromentNode resultNode = EvalDirectFunctionCall(node.Nodes[2], enviroment, envNode.Enviroment);

                // before bind function result to a smbol, eval result node first
                EvalDelayEvalBlock(resultNode);
                if (resultNode.GrammerNode != null)
                {
                    ParseNode result = resultNode.GrammerNode;
                    if (resultNode.ValueType != "lambda")
                    {
                        envNode.Type = GetTypeString(result.Nodes[2], null);
                        envNode.Value = GetValueOfLambda(result.Nodes[2]);
                    }
                    envNode.GrammerNode = result;
                }
                envNode.Enviroment = resultNode.Enviroment;
                envNode.CopyValueFromNode(resultNode);
                return;
            }
            else if (node.Nodes[2].Token.Type == TokenType.IFTHENELSE)
            {
                DelayEvalBlock block = new DelayEvalBlock(node.Nodes[2], enviroment);
                envNode.AddDelayEvalBlock(block);
                EvalDelayEvalBlock(envNode);
            }
            else if (node.Nodes[2].Token.Type == TokenType.LAMBDA)
            {
                envNode.GrammerNode = node;
                envNode.Type = GetTypeString(node.Nodes[2], null);
                envNode.Value = GetValueOfLambda(node.Nodes[2]);
                envNode.ValueType = "lambda";
            }
            else if (node.Nodes[2].Token.Type == TokenType.DIGIT)
            {
                envNode.GrammerNode = null;
                envNode.ValueType = "int";
                envNode.IValue = Int32.Parse(node.Nodes[2].Token.Text);
            }
            else if (node.Nodes[2].Token.Type == TokenType.STRINGVAL)
            {
                envNode.GrammerNode = null;
                envNode.ValueType = "string";
                string tmp = node.Nodes[2].Token.Text;
                envNode.SValue = tmp.Substring(1, tmp.Length - 2);
            }
        }
Exemplo n.º 5
0
 private static void EvalVariableSentense(ParseNode node, Enviroment enviroment,
     EnviromentNode envNode)
 {
     /*
      * node[0] == 'let' | 'set'
      * node[1] == symbol name
      * node[2] == body
      */
     if (node.Nodes.Count < 3)
         return;
     if (node.Nodes[1].Token.Type != TokenType.DEFINITION)
         return;
     EvalVarSentense(node, enviroment, envNode);
 }
Exemplo n.º 6
0
 private static void EvalTree(ParseTree tree, Enviroment enviroment)
 {
     /*
      * for each sentence, eval it
      * 1. every sentence has an enviroment to eval itself
      * 2. when enter into a function body, or apply parameter to a lambda object,
      *    create new enviroment for this block
      *  2.1 scan symbol from buttom of the enviroment list to top
      *  2.2 every symbol has a reference of the it's enviroment, so when a function
      *      returns a lambda object, this object has it's own enviroment
      * 3. when eval direct function call, change it into lambda first, then apply
      * 4. when eval function define, change it into lambda define
      */
     ParseNode starter = tree.Nodes[0];
     ParseNode sentences = starter.Nodes[0];
     EvalSentenses(sentences, enviroment);
 }
Exemplo n.º 7
0
 static void EvalSentenses(ParseNode sentences, Enviroment enviroment)
 {
     foreach (ParseNode node in sentences.Nodes)
     {
         EnviromentNode result = EvalSentense(node, enviroment);
         if (result != null && result.Terminate)
             break;
     }
 }
Exemplo n.º 8
0
        /*
         * IO need special support
         */
        static EnviromentNode ApplyIO(EnviromentNode func, EnviromentNode[] parameters, Enviroment enviroment)
        {
            EnviromentNode retNode = null;
            if (parameters.Length > 0)
            {
                EnviromentNode paramNode = parameters[0];
                retNode = new EnviromentNode(enviroment, paramNode);
            }
            else
            {
                retNode = new EnviromentNode(enviroment);
            }

            retNode.Terminate = false;
            if (func.Symbol == "return")
            {
                if (parameters.Length == 0)
                    throw new Exception("invalid IO: return without parameters");
                retNode.Terminate = true;
            }
            else if (func.Symbol == "print")
            {
                StringBuilder printString = new StringBuilder();
                foreach (EnviromentNode node in parameters)
                {
                    EvalDelayEvalBlock(node);
                    if( node.ValueType == "string" )
                    {
                        printString.Append(node.SValue);
                    }
                    else if( node.ValueType == "int")
                    {
                        printString.Append(node.IValue.ToString());
                    }
                    else if( node.ValueType == "lambda")
                    {
                        printString.Append(node.Type);
                    }
                    else
                    {
                        printString.Append(node.Symbol);
                    }
                }
                Console.WriteLine(printString.ToString());

            }
            else if (func.Symbol == "readline")
            {
                retNode.SValue = Console.ReadLine();
            }
            retNode.Symbol = "__tmp__" + enviroment.TopCount().ToString();
            return retNode;
        }
Exemplo n.º 9
0
 public void CopyFullFromNode(EnviromentNode node)
 {
     this.Symbol = node.Symbol;
     this.Type = node.Type;
     this._value = node.Value;
     this.grammerNode = node.GrammerNode;
     this.CopyValueFromNode(node);
     this.enviroment = node.enviroment;
     this.terminate = node.terminate;
 }
Exemplo n.º 10
0
 static void EvalFunctionDefineSentense(ParseNode node, Enviroment enviroment, EnviromentNode envNode)
 {
     // node[0] == symbol name
     // node[1] == parameters
     // node[2] == function body
     envNode.GrammerNode = node;
     envNode.Symbol = node.Nodes[0].Token.Text;
     envNode.Type = "__function__";
     envNode.Value = "1";
 }
Exemplo n.º 11
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.º 12
0
 static void BindParameterToEnviroment(EnviromentNode[] parameters, Enviroment newEnviro, ParseNode paraNode)
 {
     if (paraNode.Nodes.Count > 0)
     {
         int index = 0;
         foreach (ParseNode paramNode in paraNode.Nodes)
         {
             string symbol = paramNode.Token.Text;
             BindParameter(parameters, newEnviro, index, symbol);
             index++;
         }
     }
     else
     {
         string symbol = paraNode.Token.Text;
         if (!string.IsNullOrEmpty(symbol))
             BindParameter(parameters, newEnviro, 0, symbol);
     }
 }
Exemplo n.º 13
0
 private static void BindParameter(EnviromentNode[] parameters, Enviroment newEnviro, int index, string symbol)
 {
     EnviromentNode applyTo = parameters.Length < index ? null : parameters[index];
     EnviromentNode newNode = null;
     if (applyTo == null)
     {
         newNode = new EnviromentNode(newEnviro);
         newNode.Symbol = symbol;
     }
     else
     {
         EnviromentNode applyEnvNode = applyTo;
         newNode = new EnviromentNode(newEnviro, applyEnvNode);
         newNode.Symbol = symbol;
     }
     newEnviro.AddEnviromentNode(newNode);
 }
Exemplo n.º 14
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);
        }
Exemplo n.º 15
0
 public EnviromentNode(Enviroment env, EnviromentNode node)
 {
     CopyFullFromNode(node);
     this.enviroment = new Enviroment(env);
 }
Exemplo n.º 16
0
 public EnviromentNode(Enviroment env)
 {
     enviroment = new Enviroment(env);
     terminate = false;
     this.delayEvalBlock = null;
     this.valueType = "unknow";
 }
Exemplo n.º 17
0
 /*
  * eval if (a) then {b} else {c};
  * block a,b,c are all function,
  * block a return a int value node,
  * run b if a is not 0, run c else
  */
 private static EnviromentNode EvalIfThenElse(ParseNode parseNode, Enviroment enviroment, Enviroment closure)
 {
     EnviromentNode a = EvalDirectFunctionCall(parseNode.Nodes[0], enviroment, closure);
     if (a.ValueType != "int")
         throw new Exception("invalid result in if block");
     EnviromentNode ret = null;
     ParseNode b = null;
     if (a.IValue != 0)
         b = parseNode.Nodes[1];
     else
         b = parseNode.Nodes[2];
     if (b.Token.Type == TokenType.IFTHENELSE)
         ret = EvalIfThenElse(b, enviroment, closure);
     else if (b.Token.Type == TokenType.DIGIT || b.Token.Type == TokenType.STRINGVAL ||
         b.Token.Type == TokenType.DOUBLE)
     {
         ret = new EnviromentNode(enviroment);
         switch (b.Token.Type)
         {
             case TokenType.DIGIT:
                 ret.ValueType = "int";
                 ret.IValue = Int32.Parse(b.Token.Text);
                 break;
             case TokenType.STRINGVAL:
                 ret.ValueType = "string";
                 ret.SValue = b.Token.Text;
                 break;
             case TokenType.DOUBLE:
                 ret.ValueType = "double";
                 ret.DValue = Double.Parse(b.Token.Text);
                 break;
             default:
                 break;
         }
     }
     else
         ret = EvalDirectFunctionCall(b, enviroment, closure);
     return ret;
 }
Exemplo n.º 18
0
        private static EnviromentNode EvalSentense(ParseNode node, Enviroment enviroment)
        {
            EnviromentNode envNode = new EnviromentNode(enviroment);
            if (node.Token.Type == TokenType.LET)
            {
                EvalVariableSentense(node, enviroment, envNode);

                if (!string.IsNullOrEmpty(envNode.Symbol))
                    enviroment.AddEnviromentNode(envNode);
            }
            else if (node.Token.Type == TokenType.SET)
            {
                EvalVariableSentense(node, enviroment, envNode);
                if (!string.IsNullOrEmpty(envNode.Symbol))
                    enviroment.UpdateEnviromentNode(envNode);
            }
            else if (node.Token.Type == TokenType.FUNCDEF)
            {
                EvalFunctionDefineSentense(node, enviroment, envNode);

                if (!string.IsNullOrEmpty(envNode.Symbol))
                    enviroment.AddEnviromentNode(envNode);
            }
            else if (node.Token.Type == TokenType.FUNCTION)
            {
                // if a direct call occures in eval sentense, it must be an IO, or return
                envNode = EvalDirectFunctionCall(node, enviroment, envNode.Enviroment);

                if (!string.IsNullOrEmpty(envNode.Symbol))
                    enviroment.AddEnviromentNode(envNode);
            }

            return envNode;
        }
Exemplo n.º 19
0
        /*
         * 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;
        }