Esempio n. 1
0
        // Concatenate two literal strings
        ParseNode OptimiseConcatenation(ParseNode node)
        {
            BinaryOpParseNode tokenNode = (BinaryOpParseNode)node;
            tokenNode.Left = OptimiseExpressionTree(tokenNode.Left);
            tokenNode.Right = OptimiseExpressionTree(tokenNode.Right);

            if ((tokenNode.Left.ID == ParseID.STRING) && (tokenNode.Right.ID == ParseID.STRING)) {
                StringParseNode op1 = (StringParseNode)tokenNode.Left;
                StringParseNode op2 = (StringParseNode)tokenNode.Right;
                node = new StringParseNode(op1.Value + op2.Value);
            }
            return node;
        }
Esempio n. 2
0
 /// <summary>
 /// Implements the base code generator for the node to invoke a
 /// function implementation with a parse node value.
 /// </summary>
 /// <param name="cg">The code generator object</param>
 /// <param name="node">A parse node supplied to the generator function</param>
 /// <returns>The computed type</returns>
 public virtual void Generate(CodeGenerator cg, ParseNode node)
 {
     throw new InvalidOperationException("ParseNode does not implement Generate");
 }
Esempio n. 3
0
        // Block IF
        ParseNode KBlockIf(ParseNode expr)
        {
            ConditionalParseNode node = new ConditionalParseNode();
            TokenID id;

            do {
                ParseNode labelNode;

                CollectionParseNode statements = new CollectionParseNode();

                SimpleToken token = _ls.GetKeyword();
                ++_blockDepth;
                while (!IsEndOfIfBlock(token.ID)) {
                    labelNode = CheckLabel();
                    if (labelNode != null) {
                        statements.Add(labelNode);
                    }
                    ParseNode subnode = Statement(token);
                    if (subnode != null) {
                        statements.Add(MarkLine());
                        statements.Add(subnode);
                    }
                    ExpectEndOfLine();
                    token = _ls.GetKeyword();
                }
                --_blockDepth;

                // Labels on terminators are valid so we need
                // to check for and add those.
                labelNode = CheckLabel();
                if (labelNode != null) {
                    statements.Add(labelNode);
                }
                node.Add(expr, statements);

                id = token.ID;
                if (id == TokenID.KELSEIF) {
                    ExpectToken(TokenID.LPAREN);
                    expr = Expression();
                    ExpectToken(TokenID.RPAREN);
                    ExpectToken(TokenID.KTHEN);
                    ExpectEndOfLine();
                } else if (id == TokenID.KELSE) {
                    // We mark the end of the sequence of IF blocks with
                    // a null expression.
                    expr = null;
                    ExpectEndOfLine();
                }
            } while(id == TokenID.KELSEIF || id == TokenID.KELSE);
            _ls.BackToken();
            ExpectToken(TokenID.KENDIF);
            return node;
        }
Esempio n. 4
0
 // Given two parse nodes with types associated, this function returns the
 // largest type required for a consistent arithmetic operation between them.
 SymType TypePromotion(ParseNode p1, ParseNode p2)
 {
     return Symbol.LargestType(p1.Type, p2.Type);
 }
Esempio n. 5
0
        /// <summary>
        /// Emit the code to generate a call to the READ library function. A
        /// parse node must be provided which evaluates to the address of the
        /// identifier into which the data is read.
        /// </summary>
        /// <param name="cg">A CodeGenerator object</param>
        /// <param name="node">A parse node for the READ identifier</param>
        public override void Generate(CodeGenerator cg, ParseNode node)
        {
            if (cg == null) {
                throw new ArgumentNullException("cg");
            }
            if (node is LoopParseNode) {
                LoopParseNode loopNode = (LoopParseNode)node;
                loopNode.Callback = this;
                loopNode.Generate(cg);
            } else {
                Type readManagerType = typeof(JComLib.ReadManager);
                List<Type> readParamTypes = new List<Type>();

                cg.Emitter.LoadLocal(ReadManagerIndex);
                readParamTypes.Add(readManagerType);

                readParamTypes.AddRange(ReadParamsNode.Generate(cg));

                if (node is IdentifierParseNode) {
                    IdentifierParseNode identNode = (IdentifierParseNode)node;
                    if (identNode.IsArrayBase) {
                        cg.Emitter.LoadInteger(identNode.Symbol.ArraySize);
                        identNode.Generate(cg);

                        readParamTypes.Add(typeof(int));
                        readParamTypes.Add(Symbol.SymTypeToSystemType(identNode.Symbol.Type).MakeArrayType());
                    } else if (identNode.HasSubstring) {
                        cg.GenerateExpression(SymType.INTEGER, identNode.SubstringStart);
                        if (identNode.SubstringEnd != null) {
                            cg.GenerateExpression(SymType.INTEGER, identNode.SubstringEnd);
                        } else {
                            cg.Emitter.LoadInteger(-1);
                        }
                        cg.LoadAddress(identNode);
                        readParamTypes.Add(typeof(int));
                        readParamTypes.Add(typeof(int));
                        readParamTypes.Add(Symbol.SymTypeToSystemType(identNode.Symbol.Type).MakeByRefType());
                    } else {
                        cg.LoadAddress(identNode);
                        readParamTypes.Add(Symbol.SymTypeToSystemType(identNode.Symbol.Type).MakeByRefType());
                    }
                }

                cg.Emitter.Call(cg.GetMethodForType(_libraryName, _name, readParamTypes.ToArray()));
                cg.Emitter.StoreLocal(ReturnIndex);

                if (EndLabel != null) {
                    cg.Emitter.LoadLocal(ReturnIndex);
                    cg.Emitter.LoadInteger(0);
                    cg.Emitter.BranchEqual((Label)EndLabel.Symbol.Info);
                }
                if (ErrLabel != null) {
                    cg.Emitter.LoadLocal(ReturnIndex);
                    cg.Emitter.LoadInteger(-1);
                    cg.Emitter.BranchEqual((Label)ErrLabel.Symbol.Info);
                }
            }
        }
Esempio n. 6
0
 // Add this node to list of initialisation nodes that are
 // executed when the method is loaded.
 void AddInit(ParseNode initNode)
 {
     Debug.Assert(_initList != null);
     _initList.Add(initNode);
 }
Esempio n. 7
0
        /// <summary>
        /// Emit the code to generate a call to the write library function. A
        /// parse node must be specified which evaluates to the value to be
        /// written.
        /// </summary>
        /// <param name="cg">A CodeGenerator object</param>
        /// <param name="node">A parse node for the WRITE identifier</param>
        public override void Generate(CodeGenerator cg, ParseNode node)
        {
            if (cg == null) {
                throw new ArgumentNullException("cg");
            }
            if (node is LoopParseNode) {
                LoopParseNode loopNode = (LoopParseNode)node;
                loopNode.Callback = this;
                loopNode.Generate(cg);
            } else {
                Type writeManagerType = typeof(JComLib.WriteManager);
                List<Type> writeParamTypes = new List<Type>();

                cg.Emitter.LoadLocal(WriteManagerIndex);
                writeParamTypes.Add(writeManagerType);

                if (WriteParamsNode != null) {
                    writeParamTypes.AddRange(WriteParamsNode.Generate(cg));
                }

                if (node != null) {
                    ParameterParseNode exprParam = new ParameterParseNode(node);
                    writeParamTypes.Add(exprParam.Generate(cg));
                }

                cg.Emitter.Call(cg.GetMethodForType(_libraryName, _name, writeParamTypes.ToArray()));
                cg.Emitter.StoreLocal(ReturnIndex);

                if (ErrLabel != null) {
                    cg.Emitter.LoadLocal(ReturnIndex);
                    cg.Emitter.LoadInteger(-1);
                    cg.Emitter.BranchEqual((Label)ErrLabel.Symbol.Info);
                }
            }
        }
Esempio n. 8
0
 /// <summary>
 /// Retrieve the label value of a SymbolParseNode.
 /// </summary>
 /// <param name="node">A Label parse node</param>
 /// <returns>A symbol entry representing the label</returns>
 public Symbol GetLabel(ParseNode node)
 {
     if (node == null) {
         return null;
     }
     Debug.Assert(node is SymbolParseNode);
     SymbolParseNode identNode = (SymbolParseNode)node;
     return identNode.Symbol;
 }
Esempio n. 9
0
 // Optimise a negation expression where both nodes are literal
 // values. Substitute the node with the result of the negation.
 ParseNode OptimiseMinus(ParseNode node)
 {
     UnaryOpParseNode tokenNode = (UnaryOpParseNode)node;
     tokenNode.Operand = OptimiseExpressionTree(tokenNode.Operand);
     if (tokenNode.Operand.IsNumber) {
         NumberParseNode op1 = (NumberParseNode)tokenNode.Operand;
         node = new NumberParseNode(-op1.Value);
     }
     return node;
 }
Esempio n. 10
0
        // Optimise a subtraction expression where both nodes are literal
        // values. Substitute the node with the result of the subtraction.
        ParseNode OptimiseSubtraction(ParseNode node)
        {
            BinaryOpParseNode tokenNode = (BinaryOpParseNode)node;
            tokenNode.Left = OptimiseExpressionTree(tokenNode.Left);
            tokenNode.Right = OptimiseExpressionTree(tokenNode.Right);

            if (tokenNode.IsNumber) {
                NumberParseNode op1 = (NumberParseNode)tokenNode.Left;
                NumberParseNode op2 = (NumberParseNode)tokenNode.Right;
                node = new NumberParseNode(op1.Value - op2.Value);
            }

            // Check for zero simplification
            if (tokenNode.Right.IsNumber) {
                if (tokenNode.Right.Value.IsZero) {
                    return tokenNode.Left;
                }
            }
            return node;
        }
Esempio n. 11
0
 // Optimise the parse tree generated by parsing an expression in order to collapse
 // arithmetic operations with constant operands.
 ParseNode OptimiseExpressionTree(ParseNode node)
 {
     if (node != null) {
         switch (node.ID) {
             case ParseID.MINUS:     return OptimiseMinus(node);
             case ParseID.ADD:       return OptimiseAddition(node);
             case ParseID.MULT:      return OptimiseMultiplication(node);
             case ParseID.DIVIDE:    return OptimiseDivision(node);
             case ParseID.SUB:       return OptimiseSubtraction(node);
             case ParseID.EXP:       return OptimiseExponentation(node);
             case ParseID.CONCAT:    return OptimiseConcatenation(node);
         }
     }
     return node;
 }
Esempio n. 12
0
        // Optimise an exponentation expression where both nodes are literal
        // values. Substitute the node with the result of the exponentation.
        ParseNode OptimiseExponentation(ParseNode node)
        {
            BinaryOpParseNode tokenNode = (BinaryOpParseNode)node;
            tokenNode.Left = OptimiseExpressionTree(tokenNode.Left);
            tokenNode.Right = OptimiseExpressionTree(tokenNode.Right);

            if (tokenNode.IsNumber) {
                NumberParseNode op1 = (NumberParseNode)tokenNode.Left;
                NumberParseNode op2 = (NumberParseNode)tokenNode.Right;
                node = new NumberParseNode(op1.Value.Pow(op2.Value));
            }

            // x raised to the powers of -1, 0 and 1 all yield constant expressions
            // so we can simplify that right now.
            if (tokenNode.Right.IsNumber) {
                Variant rightValue = tokenNode.Right.Value;
                if (rightValue.Compare(-1)) {
                    BinaryOpParseNode divNode = new BinaryOpParseNode(ParseID.DIVIDE);
                    divNode.Left = new NumberParseNode(new Variant(1));
                    divNode.Right = tokenNode.Left;
                    divNode.Type = tokenNode.Left.Type;
                    return divNode;
                }
                if (rightValue.IsZero) {
                    return new NumberParseNode(1);
                }
                if (rightValue.Compare(1)) {
                    return tokenNode.Left;
                }
            }
            return node;
        }
Esempio n. 13
0
        // Optimise a division expression where both nodes are literal
        // values. Substitute the node with the result of the division.
        ParseNode OptimiseDivision(ParseNode node)
        {
            BinaryOpParseNode tokenNode = (BinaryOpParseNode)node;
            tokenNode.Left = OptimiseExpressionTree(tokenNode.Left);
            tokenNode.Right = OptimiseExpressionTree(tokenNode.Right);

            if (tokenNode.IsNumber) {
                NumberParseNode op1 = (NumberParseNode)tokenNode.Left;
                NumberParseNode op2 = (NumberParseNode)tokenNode.Right;
                try {
                    node = new NumberParseNode(op1.Value / op2.Value);
                } catch (DivideByZeroException) {
                    _messages.Error(MessageCode.DIVISIONBYZERO, "Constant division by zero");
                }
            }
            return node;
        }
Esempio n. 14
0
 /// <summary>
 /// Adds a case statement and target label.
 /// </summary>
 /// <param name="expr">Case expression node</param>
 /// <param name="label">Parsenode for the target label</param>
 public void Add(ParseNode expr, ParseNode label)
 {
     _caseList.Add(expr);
     _labelList.Add(label);
 }
Esempio n. 15
0
        // Scan the expression tree and adjust the node type to the type
        // determined by the arithmetic operation on its operators.
        void AdjustNodeType(ParseNode node)
        {
            if (node == null) {
                return;
            }
            switch (node.ID) {
                case ParseID.IDENT: {
                    IdentifierParseNode identNode = (IdentifierParseNode)node;
                    node.Type = identNode.Symbol.Type;
                    break;
                }

                case ParseID.ADD:
                case ParseID.SUB:
                case ParseID.MULT:
                case ParseID.EXP:
                case ParseID.DIVIDE: {
                    BinaryOpParseNode tokenNode = (BinaryOpParseNode)node;
                    AdjustNodeType(tokenNode.Left);
                    AdjustNodeType(tokenNode.Right);

                    SymType type1 = tokenNode.Left.Type;
                    SymType type2 = tokenNode.Right.Type;

                    node.Type = Symbol.LargestType(type1, type2);
                    break;
                }
            }
        }
Esempio n. 16
0
 /// <summary>
 /// Generate code for an expression tree.
 /// </summary>
 /// <param name="typeNeeded">The type to which the expression should be converted if it
 /// does not evaluate to that type natively.</param>
 /// <param name="rootNode">The ParseNode of the root of the expression tree.</param>
 /// <returns>The type of the generated expression</returns>
 public SymType GenerateExpression(SymType typeNeeded, ParseNode rootNode)
 {
     if (rootNode == null) {
         throw new ArgumentNullException("rootNode");
     }
     SymType thisType = rootNode.Generate(this, SymType.GENERIC);
     return _em.ConvertType(thisType, typeNeeded);
 }
Esempio n. 17
0
 /// <summary>
 /// Adds the given parameter to this set of parameters.
 /// </summary>
 /// <param name="node">The Parsenode to add</param>
 public void Add(ParseNode node)
 {
     if (node == null) {
         throw new ArgumentNullException("node");
     }
     Add(node, false);
 }
Esempio n. 18
0
 /// <summary>
 /// Adds the given parsenode as a child of this token node.
 /// </summary>
 /// <param name="node">The Parsenode to add</param>
 public void Add(ParseNode node)
 {
     Nodes.Add(node);
 }
Esempio n. 19
0
 /// <summary>
 /// Adds the given parameter to this set of parameters and specify how the
 /// parameter should be passed to the function.
 /// </summary>
 /// <param name="node">The Parsenode to add</param>
 /// <param name="useByRef">Whether the parameter should be passed by value or reference</param>
 public void Add(ParseNode node, bool useByRef)
 {
     if (node == null) {
         throw new ArgumentNullException("node");
     }
     ParameterParseNode paramNode = new ParameterParseNode(node);
     paramNode.Type = node.Type;
     paramNode.IsByRef = useByRef;
     Nodes.Add(paramNode);
 }
Esempio n. 20
0
 /// <summary>
 /// Adds a conditional and body.
 /// </summary>
 /// <param name="expr">Conditional expression node</param>
 /// <param name="body">Statements to be executed</param>
 public void Add(ParseNode expr, CollectionParseNode body)
 {
     _exprList.Add(expr);
     _bodyList.Add(body);
 }
Esempio n. 21
0
 /// <summary>
 /// Adds the given parameter to this set of parameters.
 /// </summary>
 /// <param name="node">The Parsenode to add</param>
 /// <param name="symbol">The symbol associated with the parameter</param>
 public void Add(ParseNode node, Symbol symbol)
 {
     if (node == null) {
         throw new ArgumentNullException("node");
     }
     ParameterParseNode paramNode = new ParameterParseNode(node, symbol);
     paramNode.Type = node.Type;
     Nodes.Add(paramNode);
 }
Esempio n. 22
0
 // Arithmetic IF
 ParseNode KArithmeticIf(ParseNode expr)
 {
     ArithmeticConditionalParseNode node = new ArithmeticConditionalParseNode();
     node.ValueExpression = expr;
     node.Add(ParseLabel());
     ExpectToken(TokenID.COMMA);
     node.Add(ParseLabel());
     ExpectToken(TokenID.COMMA);
     node.Add(ParseLabel());
     return node;
 }
Esempio n. 23
0
 /// <summary>
 /// Creates a subroutine or function parameters parse node.
 /// </summary>
 /// <param name="paramNode">A ParseNode object that contains the parameter value</param>
 public ParameterParseNode(ParseNode paramNode)
 {
     _paramNode = paramNode;
 }
Esempio n. 24
0
 // Logical IF
 ParseNode KLogicalIf(ParseNode expr)
 {
     ConditionalParseNode node = new ConditionalParseNode();
     _parsingIf = true;
     CollectionParseNode body = new CollectionParseNode();
     body.Add(Statement(_ls.GetKeyword()));
     _parsingIf = false;
     node.Add(expr, body);
     return node;
 }
Esempio n. 25
0
 /// <summary>
 /// Creates a subroutine or function parameters parse node using the
 /// given symbol as the parameter type.
 /// </summary>
 /// <param name="paramNode">A ParseNode object that contains the parameter value</param>
 /// <param name="symbol">A Symbol table item that represents the parameter name</param>
 public ParameterParseNode(ParseNode paramNode, Symbol symbol)
 {
     _paramNode = paramNode;
     _symbol = symbol;
 }
Esempio n. 26
0
        /// <summary>
        /// Generate and return an XmlDocument that represents the
        /// parse tree from the given root node down.
        /// </summary>
        /// <param name="rootNode">Parse tree root node</param>
        /// <returns>The XmlDocument for the root node</returns>
        public static XmlDocument Tree(ParseNode rootNode)
        {
            XmlDocument doc = new XmlDocument();

            XmlNode docNode = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
            doc.AppendChild(docNode);

            rootNode.Dump(new ParseNodeXML(doc, "Root"));
            return doc;
        }
Esempio n. 27
0
 // Return whether the node is a possible complex part
 bool IsComplexPart(ParseNode node)
 {
     return node.ID == ParseID.NUMBER && (node.Type == SymType.INTEGER || node.Type == SymType.FLOAT);
 }