Example #1
0
 public ArrayNameNode(ArrayNameNode rhs) : base(rhs)
 {
     ArrayDimensions = null;
     if (null != rhs.ArrayDimensions)
     {
         ArrayDimensions = new ArrayNode(rhs.ArrayDimensions);
     }
 }
Example #2
0
 public ArrayNameNode(ArrayNameNode rhs)
     : base(rhs)
 {
     ArrayDimensions = null;
     if (null != rhs.ArrayDimensions)
     {
         ArrayDimensions = new ArrayNode(rhs.ArrayDimensions);
     }
 }
Example #3
0
        public ArrayNode(ArrayNode rhs)
            : base(rhs)
        {
            Expr = null;
            Type = null;
            if (null != rhs)
            {
                if (null != rhs.Expr)
                {
                    Expr = ProtoCore.Utils.NodeUtils.Clone(rhs.Expr);
                }

                if (null != rhs.Type)
                {
                    Type = ProtoCore.Utils.NodeUtils.Clone(rhs.Type);
                }
            }
        }
Example #4
0
        public ArrayNode(ArrayNode rhs)
            : base(rhs)
        {
            Expr = null;
            Type = null;
            if (null != rhs)
            {
                if (null != rhs.Expr)
                {
                    Expr = ProtoCore.Utils.NodeUtils.Clone(rhs.Expr);
                }

                if (null != rhs.Type)
                {
                    Type = ProtoCore.Utils.NodeUtils.Clone(rhs.Type);
                }
            }
        }
Example #5
0
        private void EmitVarDeclNode(ImperativeNode node, ref ProtoCore.Type inferedType)
        {
            VarDeclNode varNode = node as VarDeclNode;

            ProtoCore.Type type = BuildArgumentTypeFromVarDeclNode(varNode);
            type.IsIndexable = false;

            // TODO Jun: Create a class table for holding the primitive and custom data types
            const int primitivesize = 1;
            int datasize = primitivesize;

            int symindex = ProtoCore.DSASM.Constants.kInvalidIndex;
            IdentifierNode tVar = null;
            if (varNode.NameNode is IdentifierNode)
            {
                // Allocate with no initializer
                tVar = varNode.NameNode as IdentifierNode;
                ProtoCore.DSASM.SymbolNode symnode = Allocate(tVar.Value, globalProcIndex, type, datasize, datasize, tVar.ArrayDimensions, varNode.memregion);
                symindex = symnode.symbolTableIndex;
            }
            else if (varNode.NameNode is BinaryExpressionNode)
            {
                BinaryExpressionNode bNode = varNode.NameNode as BinaryExpressionNode;
                tVar = bNode.LeftNode as IdentifierNode;

                Debug.Assert(null != tVar, "Check generated AST");
                Debug.Assert(null != bNode.RightNode, "Check generated AST");

                ProtoCore.DSASM.SymbolNode symnode = null;

                // Is it an array
                if (null != tVar.ArrayDimensions)
                {
                    // Allocate an array with initializer
                    if (bNode.RightNode is ExprListNode)
                    {
                        ExprListNode exprlist = bNode.RightNode as ExprListNode;
                        int size = datasize * exprlist.list.Count;

                        symnode = Allocate(tVar.Value, globalProcIndex, type, size, datasize, tVar.ArrayDimensions, varNode.memregion);
                        symindex = symnode.symbolTableIndex;

                        for (int n = 0; n < exprlist.list.Count; ++n)
                        {
                            DfsTraverse(exprlist.list[n], ref inferedType);

                            ArrayNode array = new ArrayNode();
                            array.Expr = nodeBuilder.BuildIdentfier(n.ToString(), PrimitiveType.kTypeInt);
                            array.Type = null;

                            DfsEmitArrayIndex(array, symindex);

                            EmitInstrConsole(ProtoCore.DSASM.kw.pop, ProtoCore.DSASM.kw.regDX);
                            ProtoCore.DSASM.StackValue opRes = new ProtoCore.DSASM.StackValue();
                            opRes.optype = ProtoCore.DSASM.AddressType.Register;
                            opRes.opdata = (int)ProtoCore.DSASM.Registers.DX;
                            EmitPop(opRes, Constants.kGlobalScope);

                            EmitInstrConsole(ProtoCore.DSASM.kw.pop, tVar.Value);
                            EmitPopForSymbol(symnode);
                        }
                    }
                    else
                    {
                        buildStatus.LogSemanticError("array initializer must be an expression list", compileStateTracker.CurrentDSFileName, bNode.RightNode.line, bNode.RightNode.col);
                    }
                }
                else
                {
                    // Allocate a single variable with initializer

                    symnode = Allocate(tVar.Value, globalProcIndex, type, datasize, datasize, tVar.ArrayDimensions, varNode.memregion);
                    symindex = symnode.symbolTableIndex;
                    DfsTraverse(bNode.RightNode, ref inferedType);

                    EmitInstrConsole(ProtoCore.DSASM.kw.pop, tVar.Value);
                    EmitPopForSymbol(symnode);
                }
            }
            else
            {
                Debug.Assert(false, "Check generated AST");
            }

            if (ProtoCore.DSASM.Constants.kInvalidIndex == symindex)
            {
                throw new BuildHaltException("0CB5BD17");
            }
        }
Example #6
0
        private void EmitForLoopNode(ImperativeNode node, ref ProtoCore.Type inferredType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null)
        {
            if (IsParsingGlobal() || IsParsingGlobalFunctionBody())
            {
                /*
                x = 0;
                a = {10,20,30,40}
                for(val in a)
                {
                    x = x + val;
                }

                Compiles down to:

                x = 0;
                a = {10,20,30,40};
                val = null;
                __autogen_count = 0;
                __autogen_iterations = a.size;
                while( __autogen_count < __autogen_iterations)
                {
                    val = a[__autogen_count];
                    __autogen_count = __autogen_count + 1;
                    x = x + val;
                }
                */

                DebugProperties.BreakpointOptions oldOptions = compileStateTracker.DebugProps.breakOptions;
                DebugProperties.BreakpointOptions newOptions = oldOptions;
                newOptions |= DebugProperties.BreakpointOptions.EmitCallrForTempBreakpoint;
                compileStateTracker.DebugProps.breakOptions = newOptions;

                // TODO Jun: This compilation unit has many opportunities for optimization
                //      1. Compiling to while need not be necessary if 'expr' has exactly one element
                //      2. For-loop can have its own semantics without the need to convert to a while node

                ForLoopNode forNode = node as ForLoopNode;
                ++forloopCounter;   //new forloop beginning. increment loop counter

                // Generate the expression for ‘id’ initialized to null
                BinaryExpressionNode forIdentInit = new BinaryExpressionNode();
                forIdentInit.Optr = ProtoCore.DSASM.Operator.assign;
                IdentifierNode forIdent = nodeBuilder.BuildIdentfier(forNode.loopVar.Name) as IdentifierNode;
                forIdent.ArrayName = forNode.expression.Name;
                //IdentifierNode forLoopArrayIdent = nodeBuilder.BuildIdentfier(forNode.expression.Name) as IdentifierNode;
                ProtoCore.Utils.NodeUtils.CopyNodeLocation(forIdent, forNode.loopVar);

                forIdentInit.LeftNode = forIdent;
                forIdentInit.RightNode = new NullNode();

                ProtoCore.Type type = new ProtoCore.Type();
                type.UID = (int)PrimitiveType.kTypeVoid;
                type.IsIndexable = false;

                ProtoCore.Utils.NodeUtils.CopyNodeLocation(forIdentInit, forNode);
                forIdentInit.endLine = forIdentInit.line;
                forIdentInit.endCol = forIdentInit.col + 3;
                EmitBinaryExpressionNode(forIdentInit, ref type, isBooleanOp, graphNode);

                // Generate the expression for autogen counter initialized to 0
                string forCountIdent = GetForCountIdent();
                var nodeCounter = nodeBuilder.BuildIdentfier(forCountIdent);
                BinaryExpressionNode forcounterExpr = new BinaryExpressionNode();
                forcounterExpr.Optr = ProtoCore.DSASM.Operator.assign;
                forcounterExpr.LeftNode = nodeCounter;
                forcounterExpr.RightNode = new IntNode { value = "0" };

                type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid;
                EmitBinaryExpressionNode(forcounterExpr, ref type, isBooleanOp, graphNode);

                // Generate the expression for autogen iterations initialized to 0
                string forIterCountVar = GetForIterationVar();
                var nodeIterCount = nodeBuilder.BuildIdentfier(forIterCountVar);

                BinaryExpressionNode forIterations = new BinaryExpressionNode();
                forIterations.Optr = ProtoCore.DSASM.Operator.assign;
                forIterations.LeftNode = nodeIterCount;
                forIterations.RightNode = new IntNode { value = "0" };

                type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid;
                EmitBinaryExpressionNode(forIterations, ref type, isBooleanOp, graphNode);

                // Generate the expression for autogen iteration count assigned to the size of ‘expr’

                // Create a temp array variable if 'expr' is an array
                string identName = GetForExprIdent();
                var exprIdent = nodeBuilder.BuildIdentfier(identName);
                NodeUtils.CopyNodeLocation(exprIdent, forNode.expression);

                BinaryExpressionNode arrayexprAssignment = new BinaryExpressionNode();
                arrayexprAssignment.Optr = ProtoCore.DSASM.Operator.assign;
                arrayexprAssignment.LeftNode = exprIdent;
                arrayexprAssignment.RightNode = forNode.expression;
                NodeUtils.UpdateBinaryExpressionLocation(arrayexprAssignment);

                bool shouldBreakOnTemporary = false;
                switch (forNode.expression.GetType().ToString())
                {
                    case "ProtoCore.AST.ImperativeAST.IdentifierNode":
                    case "ProtoCore.AST.ImperativeAST.ExprListNode":
                        shouldBreakOnTemporary = true;
                        break;
                }

                if (false == shouldBreakOnTemporary)
                {
                    type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid;
                    EmitBinaryExpressionNode(arrayexprAssignment, ref type, isBooleanOp, graphNode);
                }
                else
                {
                    newOptions |= DebugProperties.BreakpointOptions.EmitPopForTempBreakpoint;
                    compileStateTracker.DebugProps.breakOptions = newOptions;

                    type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid;
                    EmitBinaryExpressionNode(arrayexprAssignment, ref type, isBooleanOp, graphNode);
                }
                compileStateTracker.DebugProps.breakOptions = oldOptions; // Restore breakpoint behaviors.

                // Comment Jun: Compile such that the the forloop 'expr' is always assumed to be an array
                // If it was passed a singleton, the runtime will handle it accordingly

                ////if ((int)PrimitiveType.kTypeArray != type)
                //if (false)
                //{

                //    // 'expr' is not an array so it can be assigned directly to 'id'
                //    BinaryExpressionNode exprToIdent = new BinaryExpressionNode();
                //    exprToIdent.Optr = ProtoCore.DSASM.Operator.assign;
                //    exprToIdent.LeftNode = forIdent;
                //    exprToIdent.RightNode = forNode.expression;

                //    forNode.body.Insert(0, exprToIdent);

                //    // There is no loop since 'expr' is a single element. Traverse the for loop body directly
                //    type = (int)ProtoCore.PrimitiveType.kTypeVoid;
                //    if (null != forNode.body)
                //    {
                //        foreach (ImperativeNode bodyNode in forNode.body)
                //        {
                //            DfsTraverse(bodyNode, ref type);
                //        }
                //    }
                //}
                //else
                //{
                // 'expr' is an array

                // Get the size of expr and assign it to the autogen iteration var

                int symbolIndex = Constants.kInvalidIndex;
                SymbolNode symbol = null;
                if (ProtoCore.DSASM.Constants.kInvalidIndex != globalClassIndex && !IsInLanguageBlockDefinedInFunction())
                {
                    symbolIndex = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].symbols.IndexOf(identName);
                    if (symbolIndex != Constants.kInvalidIndex)
                    {
                        symbol = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList[symbolIndex];
                    }
                }
                else
                {
                    symbolIndex = codeBlock.symbolTable.IndexOf(identName);
                    if (symbolIndex != Constants.kInvalidIndex)
                    {
                        symbol = codeBlock.symbolTable.symbolList[symbolIndex];
                    }
                }

                EmitInstrConsole(ProtoCore.DSASM.kw.pushvarsize, identName);
                EmitPushVarSize(symbolIndex, codeBlock.symbolTable.runtimeIndex, (symbol == null) ? globalClassIndex : symbol.classScope);

                // Push the identifier local block information
                // Push the array dimensions
                int dimensions = 0;
                EmitPushVarData(codeBlock.symbolTable.runtimeIndex, dimensions);

                ProtoCore.DSASM.StackValue opDest = new ProtoCore.DSASM.StackValue();
                opDest.optype = ProtoCore.DSASM.AddressType.VarIndex;
                if (ProtoCore.DSASM.Constants.kInvalidIndex != globalClassIndex && !IsInLanguageBlockDefinedInFunction())
                {
                    symbolIndex = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].symbols.IndexOf(forIterCountVar);
                    if (symbolIndex != Constants.kInvalidIndex)
                    {
                        symbol = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList[symbolIndex];
                    }
                }
                else
                {
                    symbolIndex = codeBlock.symbolTable.IndexOf(forIterCountVar);
                    if (symbolIndex != Constants.kInvalidIndex)
                    {
                        symbol = codeBlock.symbolTable.symbolList[symbolIndex];
                    }
                }
                opDest.opdata = symbolIndex;
                EmitInstrConsole(ProtoCore.DSASM.kw.pop, forIterCountVar);
                EmitPop(opDest, (symbol == null) ? globalClassIndex : symbol.classScope);

                // Generate the comparison expression between the autogen counter and the autogen iteration count
                BinaryExpressionNode iterCondition = new BinaryExpressionNode();
                iterCondition.Optr = ProtoCore.DSASM.Operator.lt;
                iterCondition.LeftNode = nodeCounter;
                iterCondition.RightNode = nodeIterCount;

                iterCondition.line = forNode.KwInLine;
                iterCondition.col = forNode.KwInCol;
                iterCondition.endLine = forNode.KwInLine;
                iterCondition.endCol = forNode.KwInCol + 2; // 2 character for keyword "in".

                // Generate the assignment statement from where lhs is ‘id’ and rhs is ‘expr’ indexed into the autogen count
                BinaryExpressionNode IndexedExprToId = new BinaryExpressionNode();
                IndexedExprToId.Optr = ProtoCore.DSASM.Operator.assign;
                IndexedExprToId.LeftNode = forIdent;

                // Array index into the expr ident
                ArrayNode arrayIndex = new ArrayNode();
                arrayIndex.Expr = nodeCounter;
                arrayIndex.Type = null;
                (exprIdent as IdentifierNode).ArrayDimensions = arrayIndex;

                IndexedExprToId.RightNode = exprIdent;

                IndexedExprToId.line = forIdent.line;
                IndexedExprToId.col = forIdent.col;
                IndexedExprToId.endLine = forIdent.endLine;
                IndexedExprToId.endCol = forIdent.endCol;

                // Generate the expression for increment by 1 of the autogen count
                var countIncrement = nodeBuilder.BuildBinaryExpression(nodeCounter, new IntNode { value = "1" }, Operator.add);
                var countIncrementAssign = nodeBuilder.BuildBinaryExpression(nodeCounter, countIncrement);

                // Append the array indexing and increment expressions into the for-loop body
                forNode.body.Insert(0, IndexedExprToId);
                forNode.body.Insert(1, countIncrementAssign);

                // Construct and populate the equivalent while node
                WhileStmtNode whileNode = new WhileStmtNode();
                whileNode.Expr = iterCondition;
                whileNode.Body = forNode.body;
                whileNode.endLine = node.endLine;
                whileNode.endCol = node.endCol;

                type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid;
                EmitWhileStmtNode(whileNode, ref type, isBooleanOp, graphNode);
                //}

                // Comment Jun: The for loop counter must be unique and does not need to reset
                //forloopCounter--;   //for loop ended. decrement counter
            }
        }
Example #7
0
        private void EmitVarDeclNode(ImperativeNode node, ref ProtoCore.Type inferedType)
        {
            VarDeclNode varNode = node as VarDeclNode;

            ProtoCore.Type type = new ProtoCore.Type();
            type.UID = compileState.TypeSystem.GetType(varNode.ArgumentType.Name);
            type.IsIndexable = false;

            // TODO Jun: Create a class table for holding the primitive and custom data types
            const int primitivesize = 1;
            int datasize = primitivesize;

            int symindex = ProtoCore.DSASM.Constants.kInvalidIndex;
            IdentifierNode tVar = null;
            if (varNode.NameNode is IdentifierNode)
            {
                // Allocate with no initializer
                tVar = varNode.NameNode as IdentifierNode;
                ProtoCore.DSASM.SymbolNode symnode = Allocate(tVar.Value, globalProcIndex, type, datasize, datasize, tVar.ArrayDimensions, varNode.memregion);
                IdentLocation.AddEntry(symnode, tVar.line, tVar.col, compileState.CurrentDSFileName);
                symindex = symnode.symbolTableIndex;
            }
            else if (varNode.NameNode is BinaryExpressionNode)
            {
                BinaryExpressionNode bNode = varNode.NameNode as BinaryExpressionNode;
                tVar = bNode.LeftNode as IdentifierNode;

                Debug.Assert(null != tVar, "Check generated AST");
                Debug.Assert(null != bNode.RightNode, "Check generated AST");

                ProtoCore.DSASM.SymbolNode symnode = null;

                // Is it an array
                if (null != tVar.ArrayDimensions)
                {
                    // Allocate an array with initializer
                    if (bNode.RightNode is ExprListNode)
                    {
                        ExprListNode exprlist = bNode.RightNode as ExprListNode;
                        int size = datasize * exprlist.list.Count;

                        symnode = Allocate(tVar.Value, globalProcIndex, type, size, datasize, tVar.ArrayDimensions, varNode.memregion);
                        symindex = symnode.symbolTableIndex;
                        IdentLocation.AddEntry(symnode, tVar.line, tVar.col, compileState.CurrentDSFileName);
                        for (int n = 0; n < exprlist.list.Count; ++n)
                        {
                            DfsTraverse(exprlist.list[n], ref inferedType);

                            IdentifierNode t = new IdentifierNode();
                            t.Value = n.ToString();
                            t.datatype = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeInt, false);

                            ArrayNode array = new ArrayNode();
                            array.Expr = t;
                            array.Type = null;

                            DfsEmitArrayIndex(array, symindex);

                        }
                    }
                }
                else
                {
                    // Allocate a single variable with initializer

                    symnode = Allocate(tVar.Value, globalProcIndex, type, datasize, datasize, tVar.ArrayDimensions, varNode.memregion);
                    IdentLocation.AddEntry(symnode, tVar.line, tVar.col, compileState.CurrentDSFileName);
                    symindex = symnode.symbolTableIndex;
                    DfsTraverse(bNode.RightNode, ref inferedType);
                }
            }
            else
            {
                Debug.Assert(false, "Check generated AST");
            }

            if (ProtoCore.DSASM.Constants.kInvalidIndex == symindex)
            {
                throw new BuildHaltException();
            }
        }
Example #8
0
        private void EmitForLoopNode(ImperativeNode node)
        {
            if (IsParsingGlobal() || IsParsingGlobalFunctionBody())
            {
                /*
                 *
                x = 0;
                a = {10,20,30,40}
                for(val in a)
                {
                    x = x + val;
                }

                Compiles down to:

                x = 0;
                a = {10,20,30,40};
                val = null;
                __autogen_count = 0;
                __autogen_iterations = a.size;
                while( __autogen_count < __autogen_iterations)
                {
                    val = a[__autogen_count];
                    __autogen_count = __autogen_count + 1;
                    x = x + val;
                }

                */

                // TODO Jun: This compilation unit has many opportunities for optimization
                //      1. Compiling to while need not be necessary if 'expr' has exactly one element
                //      2. For-loop can have its own semantics without the need to convert to a while node

                ForLoopNode forNode = node as ForLoopNode;
                ++forloopCounter;   //new forloop beginning. increment loop counter

                // Generate the expression for ‘id’ initialized to null
                BinaryExpressionNode forIdentInit = new BinaryExpressionNode();
                forIdentInit.Optr = ProtoCore.DSASM.Operator.assign;
                IdentifierNode forIdent = new IdentifierNode()
                {
                    Value = forNode.loopVar.Name,
                    Name = forNode.loopVar.Name,
                    datatype = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, false),
                    line = forNode.loopVar.line,
                    col = forNode.loopVar.col,
                    endLine = forNode.loopVar.line,
                    endCol = forNode.loopVar.col + forNode.loopVar.Name.Length - 1
                };

                forIdentInit.LeftNode = forIdent;
                forIdentInit.RightNode = new NullNode();

                ProtoCore.Type type = new ProtoCore.Type();
                type.UID = (int)PrimitiveType.kTypeVoid;
                type.IsIndexable = false;

                forIdentInit.line = forNode.KwForLine;
                forIdentInit.col = forNode.KwForCol;
                forIdentInit.endLine = forNode.KwForLine;
                forIdentInit.endCol = forNode.KwForCol + 2;

                EmitBinaryExpressionNode(forIdentInit, ref type);

                // Generate the expression for autogen counter initialized to 0
                string forCountIdent = GetForCountIdent();
                IdentifierNode nodeCounter = new IdentifierNode()
                {
                    Value = forCountIdent,
                    Name = forCountIdent,
                    datatype = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, false)
                };

                BinaryExpressionNode forcounterExpr = new BinaryExpressionNode();
                forcounterExpr.Optr = ProtoCore.DSASM.Operator.assign;
                forcounterExpr.LeftNode = nodeCounter;
                forcounterExpr.RightNode = new IntNode() { value = "0" };

                type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid;
                EmitBinaryExpressionNode(forcounterExpr, ref type);

                // Generate the expression for autogen iterations initialized to 0
                string forIterCountVar = GetForIterationVar();
                IdentifierNode nodeIterCount = new IdentifierNode()
                {
                    Value = forIterCountVar,
                    Name = forIterCountVar,
                    datatype = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, false)
                };

                BinaryExpressionNode forIterations = new BinaryExpressionNode();
                forIterations.Optr = ProtoCore.DSASM.Operator.assign;
                forIterations.LeftNode = nodeIterCount;
                forIterations.RightNode = new IntNode() { value = "0" };

                type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid;
                EmitBinaryExpressionNode(forIterations, ref type);

                /*
                                // Generate the expression for autogen iteration count assigned to the size of ‘expr’
                                string identName = null;
                                IdentifierNode exprIdent = null;
                                if (forNode.expression is IdentifierNode)
                                {
                                    exprIdent = forNode.expression as IdentifierNode;
                                    identName = exprIdent.Value;
                                }
                                else if (forNode.expression is ExprListNode)
                                {
                                    // Create a temp array variable if 'expr' is an array
                                    identName = GetForExprIdent();
                                    exprIdent = new IdentifierNode()
                                    {
                                        Value = identName,
                                        Name = identName,
                                        type = (int)ProtoCore.PrimitiveType.kTypeVar,
                                        datatype = ProtoCore.PrimitiveType.kTypeVar
                                    };

                                    BinaryExpressionNode arrayexprAssignment = new BinaryExpressionNode();
                                    arrayexprAssignment.Optr = ProtoCore.DSASM.Operator.assign;
                                    arrayexprAssignment.LeftNode = exprIdent;
                                    arrayexprAssignment.RightNode = forNode.expression as ExprListNode;

                                    type = (int)ProtoCore.PrimitiveType.kTypeVoid;
                                    EmitBinaryExpressionNode(arrayexprAssignment, ref type);
                                }
                                */

                // Generate the expression for autogen iteration count assigned to the size of ‘expr’

                // Create a temp array variable if 'expr' is an array
                string identName = GetForExprIdent();
                IdentifierNode exprIdent = new IdentifierNode()
                {
                    Value = identName,
                    Name = identName,
                    datatype = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, false)
                };

                BinaryExpressionNode arrayexprAssignment = new BinaryExpressionNode();
                arrayexprAssignment.Optr = ProtoCore.DSASM.Operator.assign;
                arrayexprAssignment.LeftNode = exprIdent;
                arrayexprAssignment.RightNode = forNode.expression;

                arrayexprAssignment.line = forNode.expression.line;
                arrayexprAssignment.col = forNode.expression.col;
                arrayexprAssignment.endLine = forNode.expression.endLine;
                arrayexprAssignment.endCol = forNode.expression.endCol;

                type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid;
                EmitBinaryExpressionNode(arrayexprAssignment, ref type);

                // Comment Jun: Compile such that the the forloop 'expr' is always assumed to be an array
                // If it was passed a singleton, the runtime will handle it accordingly

                ////if ((int)PrimitiveType.kTypeArray != type)
                //if (false)
                //{

                //    // 'expr' is not an array so it can be assigned directly to 'id'
                //    BinaryExpressionNode exprToIdent = new BinaryExpressionNode();
                //    exprToIdent.Optr = ProtoCore.DSASM.Operator.assign;
                //    exprToIdent.LeftNode = forIdent;
                //    exprToIdent.RightNode = forNode.expression;

                //    forNode.body.Insert(0, exprToIdent);

                //    // There is no loop since 'expr' is a single element. Traverse the for loop body directly
                //    type = (int)ProtoCore.PrimitiveType.kTypeVoid;
                //    if (null != forNode.body)
                //    {
                //        foreach (ImperativeNode bodyNode in forNode.body)
                //        {
                //            DfsTraverse(bodyNode, ref type);
                //        }
                //    }
                //}
                //else
                //{
                // 'expr' is an array

                // Get the size of expr and assign it to the autogen iteration var
                int symbol = ProtoCore.DSASM.Constants.kInvalidIndex;
                if (ProtoCore.DSASM.Constants.kInvalidIndex != globalClassIndex)
                {
                    symbol = compileState.ClassTable.ClassNodes[globalClassIndex].symbols.IndexOf(identName);
                }
                else
                {
                    symbol = codeBlock.symbolTable.IndexOf(identName);
                }

                // Generate the comparison expression between the autogen counter and the autogen iteration count
                BinaryExpressionNode iterCondition = new BinaryExpressionNode();
                iterCondition.Optr = ProtoCore.DSASM.Operator.lt;
                iterCondition.LeftNode = nodeCounter;
                iterCondition.RightNode = nodeIterCount;

                iterCondition.line = forNode.KwInLine;
                iterCondition.col = forNode.KwInCol;
                iterCondition.endLine = forNode.KwInLine;
                iterCondition.endCol = forNode.KwInCol + 1;

                // Generate the assignment statement from where lhs is ‘id’ and rhs is ‘expr’ indexed into the autogen count
                BinaryExpressionNode IndexedExprToId = new BinaryExpressionNode();
                IndexedExprToId.Optr = ProtoCore.DSASM.Operator.assign;
                IndexedExprToId.LeftNode = forIdent;

                // Array index into the expr ident
                ArrayNode arrayIndex = new ArrayNode();
                arrayIndex.Expr = nodeCounter;
                arrayIndex.Type = null;
                exprIdent.ArrayDimensions = arrayIndex;

                IndexedExprToId.RightNode = exprIdent;

                IndexedExprToId.line = forIdent.line;
                IndexedExprToId.col = forIdent.col;
                IndexedExprToId.endLine = forIdent.endLine;
                IndexedExprToId.endCol = forIdent.endCol;

                // Generate the expression for increment by 1 of the autogen count
                BinaryExpressionNode countIncrement = new BinaryExpressionNode();
                countIncrement.Optr = ProtoCore.DSASM.Operator.add;
                countIncrement.LeftNode = nodeCounter;
                countIncrement.RightNode = new IntNode() { value = "1" };

                BinaryExpressionNode countIncrementAssign = new BinaryExpressionNode();
                countIncrementAssign.Optr = ProtoCore.DSASM.Operator.assign;
                countIncrementAssign.LeftNode = nodeCounter;
                countIncrementAssign.RightNode = countIncrement;

                // Append the array indexing and increment expressions into the for-loop body
                forNode.body.Insert(0, IndexedExprToId);
                forNode.body.Insert(1, countIncrementAssign);

                // Construct and populate the equivalent while node
                WhileStmtNode whileNode = new WhileStmtNode();
                whileNode.Expr = iterCondition;
                whileNode.Body = forNode.body;
                whileNode.line = forNode.line;
                whileNode.col = forNode.col;
                whileNode.endLine = forNode.endLine;
                whileNode.endCol = forNode.endCol;

                type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid;
                EmitWhileStmtNode(whileNode, ref type);
                //}

                // Comment Jun: The for loop counter must be unique and does not need to reset
                //forloopCounter--;   //for loop ended. decrement counter
            }
        }
Example #9
0
        private void EmitForLoopNode(ImperativeNode node, ref ProtoCore.Type inferredType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null)
        {
            if (core.IsParsingCodeBlockNode || core.IsParsingPreloadedAssembly)
            {
                return;
            }

            if (IsParsingGlobal() || IsParsingGlobalFunctionBody())
            {
                /*
                x = 0;
                a = {10,20,30,40}
                for(val in a)
                {
                    x = x + val;
                }

                Compiles down to:

                x = 0;
                a = {10,20,30,40};
                val = null;
                %forloop_key = a.key;
                %forloop_expr = a;

                while( %forloop_key != null)
                {
                    val = %forloop_expr[%forloop_key];
                    %forloop_key = %forloop_key + 1;
                    x = x + val;
                }
                */
                DebugProperties.BreakpointOptions oldOptions = core.DebuggerProperties.breakOptions;
                DebugProperties.BreakpointOptions newOptions = oldOptions;
                newOptions |= DebugProperties.BreakpointOptions.EmitCallrForTempBreakpoint;
                core.DebuggerProperties.breakOptions = newOptions;

                // TODO Jun: This compilation unit has many opportunities for optimization 
                //      1. Compiling to while need not be necessary if 'expr' has exactly one element
                //      2. For-loop can have its own semantics without the need to convert to a while node

                ForLoopNode forNode = node as ForLoopNode;
                ++core.ForLoopBlockIndex;   //new forloop beginning. increment loop counter 

                // Insert a dummy block for for-loop so that loopvar is in scope.
                ProtoCore.DSASM.CodeBlock localCodeBlock = new ProtoCore.DSASM.CodeBlock(
                        context.guid,
                        ProtoCore.DSASM.CodeBlockType.kConstruct,
                        Language.kInvalid,
                        core.CodeBlockIndex++,
                        new ProtoCore.DSASM.SymbolTable(GetConstructBlockName("dummy"), core.RuntimeTableIndex++),
                        null,
                        true,
                        core);

                core.CodeBlockIndex++;
                localCodeBlock.instrStream = codeBlock.instrStream;
                localCodeBlock.parent = codeBlock;

                codeBlock.children.Add(localCodeBlock);
                codeBlock = localCodeBlock;
                EmitPushBlockID(localCodeBlock.codeBlockId);


                ProtoCore.Type type = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVoid, 0);

                // val = null; 
                IdentifierNode loopvar = nodeBuilder.BuildIdentfier(forNode.loopVar.Name) as IdentifierNode;
                {
                    loopvar.ArrayName = forNode.expression.Name;
                    ProtoCore.Utils.NodeUtils.CopyNodeLocation(loopvar, forNode.loopVar);
                    BinaryExpressionNode loopvarInit = new BinaryExpressionNode();
                    loopvarInit.Optr = ProtoCore.DSASM.Operator.assign;
                    loopvarInit.LeftNode = loopvar;
                    loopvarInit.RightNode = new NullNode();
 
                    ProtoCore.Utils.NodeUtils.CopyNodeLocation(loopvarInit, forNode);
                    loopvarInit.endLine = loopvarInit.line;
                    loopvarInit.endCol = loopvarInit.col + 3;
                    EmitBinaryExpressionNode(loopvarInit, ref type, isBooleanOp, graphNode);
                }

                // %key = null;
                string keyIdent = GetForLoopKeyIdent();
                Allocate(keyIdent, globalProcIndex, TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVoid, 0));
                var key = nodeBuilder.BuildIdentfier(keyIdent);

                // %array = complicated expr in for...in loop, so that we could
                // index into it. 
                string identName = GetForExprIdent();
                var arrayExpr = nodeBuilder.BuildIdentfier(identName);
                NodeUtils.CopyNodeLocation(arrayExpr, forNode.expression);
                BinaryExpressionNode arrayexprAssignment = new BinaryExpressionNode();
                arrayexprAssignment.Optr = ProtoCore.DSASM.Operator.assign;
                arrayexprAssignment.LeftNode = arrayExpr;
                arrayexprAssignment.RightNode = forNode.expression;
                NodeUtils.UpdateBinaryExpressionLocation(arrayexprAssignment);

                switch (forNode.expression.GetType().ToString())
                {
                    case "ProtoCore.AST.ImperativeAST.IdentifierNode":
                    case "ProtoCore.AST.ImperativeAST.ExprListNode":
                        newOptions |= DebugProperties.BreakpointOptions.EmitPopForTempBreakpoint;
                        core.DebuggerProperties.breakOptions = newOptions;
                        break;
                }

                type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid;
                EmitBinaryExpressionNode(arrayexprAssignment, ref type, isBooleanOp, graphNode);
                core.DebuggerProperties.breakOptions = oldOptions; // Restore breakpoint behaviors.

                // Get the size of expr and assign it to the autogen iteration var
                int symbolIndex = Constants.kInvalidIndex;
                SymbolNode symbol = null;
                if (ProtoCore.DSASM.Constants.kInvalidIndex != globalClassIndex && !IsInLanguageBlockDefinedInFunction())
                {
                    symbolIndex = core.ClassTable.ClassNodes[globalClassIndex].symbols.IndexOf(identName);
                    if (symbolIndex != Constants.kInvalidIndex)
                    {
                        symbol = core.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList[symbolIndex];
                    }
                }
                else
                {
                    symbolIndex = codeBlock.symbolTable.IndexOf(identName);
                    if (symbolIndex != Constants.kInvalidIndex)
                    {
                        symbol = codeBlock.symbolTable.symbolList[symbolIndex];
                    }
                }
                EmitInstrConsole(ProtoCore.DSASM.kw.pushvarsize, identName);
                EmitPushArrayKey(symbolIndex, codeBlock.symbolTable.RuntimeIndex, (symbol == null) ? globalClassIndex : symbol.classScope);

                // Push the identifier local block information 
                // Push the array dimensions
                int dimensions = 0;
                EmitPushVarData(dimensions);

                if (ProtoCore.DSASM.Constants.kInvalidIndex != globalClassIndex && !IsInLanguageBlockDefinedInFunction())
                {
                    symbolIndex = core.ClassTable.ClassNodes[globalClassIndex].symbols.IndexOf(keyIdent);
                    if (symbolIndex != Constants.kInvalidIndex)
                    {
                        symbol = core.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList[symbolIndex];
                    }
                }
                else
                {
                    symbolIndex = codeBlock.symbolTable.IndexOf(keyIdent);
                    if (symbolIndex != Constants.kInvalidIndex)
                    {
                        symbol = codeBlock.symbolTable.symbolList[symbolIndex];
                    }
                }
                StackValue opDest = StackValue.BuildVarIndex(symbolIndex);
                EmitInstrConsole(ProtoCore.DSASM.kw.pop, keyIdent);
                EmitPop(opDest, (symbol == null) ? globalClassIndex : symbol.classScope, symbol.runtimeTableIndex);

                // key == null ?
                BinaryExpressionNode condition = new BinaryExpressionNode();
                {
                    condition.Optr = ProtoCore.DSASM.Operator.nq;
                    condition.LeftNode = key;
                    condition.RightNode = new NullNode();
                    condition.line = forNode.KwInLine;
                    condition.col = forNode.KwInCol;
                    condition.endLine = forNode.KwInLine;
                    condition.endCol = forNode.KwInCol + 2; // 2 character for keyword "in".
                }

                // val = array[key];
                BinaryExpressionNode arrayIndexing = new BinaryExpressionNode();
                {
                    arrayIndexing.Optr = ProtoCore.DSASM.Operator.assign;
                    arrayIndexing.LeftNode = loopvar;

                    // Array index into the expr ident
                    ArrayNode arrayIndex = new ArrayNode();
                    arrayIndex.Expr = key;
                    arrayIndex.Type = null;
                    (arrayExpr as IdentifierNode).ArrayDimensions = arrayIndex;
                    arrayIndexing.RightNode = arrayExpr;

                    arrayIndexing.line = loopvar.line;
                    arrayIndexing.col = loopvar.col;
                    arrayIndexing.endLine = loopvar.endLine;
                    arrayIndexing.endCol = loopvar.endCol;
                }

                // key = key + 1;
                BinaryExpressionNode nextKey = new BinaryExpressionNode();
                {
                    nextKey.LeftNode = key;
                    nextKey.Optr = Operator.assign;
                    nextKey.RightNode = nodeBuilder.BuildBinaryExpression(key,
                                                    new IntNode(1),
                                                    Operator.add);
                }

                // Append the array indexing and key increment expressions into 
                // the for-loop body
                forNode.body.Insert(0, arrayIndexing);
                forNode.body.Insert(1, nextKey);

                // Construct and populate the equivalent while node
                WhileStmtNode whileStatement = new WhileStmtNode();
                whileStatement.Expr = condition;
                whileStatement.Body = forNode.body;
                whileStatement.endLine = node.endLine;
                whileStatement.endCol = node.endCol;

                type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid;
                EmitWhileStmtNode(whileStatement, ref type, isBooleanOp, graphNode);

                // As we add a dummy code block around forloop node, RETCN 
                // instruction will get debugging information from 
                // localCodeBlockNode, which is forloop node. We temporarily set
                // lcoalCodeBlockNode to a dummy node so that RETCN won't have 
                // debugging information.
                var dummyCodeBlockNode = new CodeBlockNode();
                var backUpLocalCodeBlockNode = localCodeBlockNode;
                localCodeBlockNode = dummyCodeBlockNode;

                EmitInstrConsole(ProtoCore.DSASM.kw.retcn);
                EmitRetcn(localCodeBlock.codeBlockId);

                codeBlock = localCodeBlock.parent;
                localCodeBlockNode = backUpLocalCodeBlockNode;
                //}

                // Comment Jun: The for loop counter must be unique and does not need to reset
                //forloopCounter--;   //for loop ended. decrement counter 
            }
        }
Example #10
0
 public ArrayNameNode()
 {
     ArrayDimensions = null;
 }
Example #11
0
 public ArrayNameNode()
 {
     ArrayDimensions = null;
 }