Пример #1
0
        /// <summary>
        /// </summary>
        /// <param name="codeBlock"></param>
        /// <param name="inferedType"></param>
        /// <param name="subPass"></param>
        private void EmitCodeBlock(
            List<ImperativeNode> codeBlock, 
            ref ProtoCore.Type inferedType, 
            bool isBooleanOp = false, 
            ProtoCore.AssociativeGraph.GraphNode graphNode = null)
        {
            foreach (ImperativeNode bodyNode in codeBlock)
            {
                inferedType = new ProtoCore.Type();
                inferedType.UID = (int)PrimitiveType.Var;

                if (bodyNode is LanguageBlockNode)
                {
                    BinaryExpressionNode langBlockNode = new BinaryExpressionNode();
                    langBlockNode.LeftNode = nodeBuilder.BuildIdentfier(core.GenerateTempLangageVar());
                    langBlockNode.Optr = ProtoCore.DSASM.Operator.assign;
                    langBlockNode.RightNode = bodyNode;
                    DfsTraverse(langBlockNode, ref inferedType, isBooleanOp, graphNode);
                }
                else
                {
                    DfsTraverse(bodyNode, ref inferedType, isBooleanOp, graphNode);
                }
            }
        }
Пример #2
0
 public ImperativeNode BuildBinaryExpression(ImperativeNode leftNode, ImperativeNode rightNode, Operator op = Operator.assign)
 {
     var binaryExpr = new BinaryExpressionNode();
     binaryExpr.LeftNode = leftNode;
     binaryExpr.Optr = op;
     binaryExpr.RightNode = rightNode;
     return binaryExpr;
 }
Пример #3
0
        private void EmitPostFixNode(ImperativeNode node, ref ProtoCore.Type inferedType)
        {
            bool parseGlobal = null == localProcedure && ProtoCore.DSASM.ImperativeCompilePass.kAll == compilePass;
            bool parseGlobalFunction = null != localProcedure && ProtoCore.DSASM.ImperativeCompilePass.kGlobalFuncBody == compilePass;

            if (parseGlobal || parseGlobalFunction)
            {
                PostFixNode pfNode = node as PostFixNode;

                //convert post fix operation to a binary operation
                BinaryExpressionNode binRight = new BinaryExpressionNode();
                BinaryExpressionNode bin = new BinaryExpressionNode();

                binRight.LeftNode = pfNode.Identifier;
                binRight.RightNode = new IntNode() { value = "1" };
                binRight.Optr = (ProtoCore.DSASM.UnaryOperator.Increment == pfNode.Operator) ? ProtoCore.DSASM.Operator.add : ProtoCore.DSASM.Operator.sub;
                bin.LeftNode = pfNode.Identifier;
                bin.RightNode = binRight;
                bin.Optr = ProtoCore.DSASM.Operator.assign;
                EmitBinaryExpressionNode(bin, ref inferedType);
            }
        }
Пример #4
0
        private void EmitWhileStmtNode(ImperativeNode node, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null)
        {
            if (IsParsingGlobal() || IsParsingGlobalFunctionBody())
            {
                /*

                while(E)	->	entry = pc
                                traverse E
                                emit(pop,cx)
                                L1 = pc + 1
                                L2 = null
                                bp = pc
                                emit(jmp, _cx, L1, L2)

                 * */

                int bp = (int)ProtoCore.DSASM.Constants.kInvalidIndex;
                int L1 = (int)ProtoCore.DSASM.Constants.kInvalidIndex;
                int L2 = (int)ProtoCore.DSASM.Constants.kInvalidIndex;
                int entry = (int)ProtoCore.DSASM.Constants.kInvalidIndex;

                entry = pc;

                WhileStmtNode whileNode = node as WhileStmtNode;
                DfsTraverse(whileNode.Expr, ref inferedType);

                ProtoCore.DSASM.StackValue opCX = new ProtoCore.DSASM.StackValue();
                EmitInstrConsole(ProtoCore.DSASM.kw.pop, ProtoCore.DSASM.kw.regCX);
                opCX.optype = ProtoCore.DSASM.AddressType.Register;
                opCX.opdata = (int)ProtoCore.DSASM.Registers.CX;
                EmitPop(opCX, Constants.kGlobalScope);

                L1 = pc + 1;
                L2 = ProtoCore.DSASM.Constants.kInvalidIndex;
                bp = pc;
                EmitCJmp(L1, L2, whileNode.Expr.line, whileNode.Expr.col, whileNode.Expr.endLine, whileNode.Expr.endCol);

                EmitSetExpressionUID(compileStateTracker.ExpressionUID++);

                /*
                {
                    S		->	traverse S
                                bptable.append(pc)
                                emit(jmp, entry)
                }
                            ->  backpatch(bp, pc)
                */
                if (null != whileNode.Body)
                {
                    // Create a new symboltable for this block
                    // Set the current table as the parent of the new table
                    // Set the new table as a new child of the current table
                    // Set the new table as the current table
                    // Create a new codeblock for this block
                    // Set the current codeblock as the parent of the new codeblock
                    // Set the new codeblock as a new child of the current codeblock
                    // Set the new codeblock as the current codeblock
                    ProtoCore.DSASM.CodeBlock localCodeBlock = new ProtoCore.DSASM.CodeBlock(
                        ProtoCore.DSASM.CodeBlockType.kConstruct,
                        Language.kInvalid,
                        compileStateTracker.CodeBlockIndex++,
                        new ProtoCore.DSASM.SymbolTable(GetConstructBlockName("while"), compileStateTracker.RuntimeTableIndex++),
                        null,
                        true);

                    localCodeBlock.instrStream = codeBlock.instrStream;
                    localCodeBlock.parent = codeBlock;
                    codeBlock.children.Add(localCodeBlock);
                    codeBlock = localCodeBlock;
                    compileStateTracker.CompleteCodeBlockList.Add(localCodeBlock);
                    backpatchMap.EntryTable[localCodeBlock.codeBlockId] = entry;
                    backpatchMap.BreakTable[localCodeBlock.codeBlockId] = new BackpatchTable();

                    EmitPushBlockID(localCodeBlock.codeBlockId);
                    foreach (ImperativeNode bodyNode in whileNode.Body)
                    {
                        inferedType = new ProtoCore.Type();
                        inferedType.UID = (int)PrimitiveType.kTypeVar;

                        if (bodyNode is LanguageBlockNode)
                        {
                            BinaryExpressionNode langBlockNode = new BinaryExpressionNode();
                            langBlockNode.LeftNode = nodeBuilder.BuildIdentfier(compileStateTracker.GenerateTempLangageVar());
                            langBlockNode.Optr = ProtoCore.DSASM.Operator.assign;
                            langBlockNode.RightNode = bodyNode;
                            DfsTraverse(langBlockNode, ref inferedType, isBooleanOp, graphNode);
                        }
                        else
                        {
                            DfsTraverse(bodyNode, ref inferedType, isBooleanOp, graphNode);
                        }
                    }

                    ProtoCore.AST.Node oldBlockNode = localCodeBlockNode;
                    localCodeBlockNode = node;
                    EmitInstrConsole(ProtoCore.DSASM.kw.retcn);
                    EmitRetcn(localCodeBlock.codeBlockId);
                    localCodeBlockNode = oldBlockNode;

                    // Restore - Set the local codeblock parent to be the current codeblock
                    codeBlock = localCodeBlock.parent;

                    EmitJmp(entry);
                    EmitPopBlockID();
                    Backpatch(backpatchMap.BreakTable[localCodeBlock.codeBlockId].backpatchList, pc);
                }
                Backpatch(bp, pc);
            }
        }
Пример #5
0
        private void EmitUnaryExpressionNode(ImperativeNode node, ref ProtoCore.Type inferedType, ProtoCore.AST.ImperativeAST.BinaryExpressionNode parentNode)
        {
            if (IsParsingGlobal() || IsParsingGlobalFunctionBody())
            {
                UnaryExpressionNode u = node as UnaryExpressionNode;
                bool isPrefixOperation = ProtoCore.DSASM.UnaryOperator.Increment == u.Operator || ProtoCore.DSASM.UnaryOperator.Decrement == u.Operator;
                //(Ayush) In case of prefix, apply prefix operation first
                if (isPrefixOperation)
                {
                    if (u.Expression is IdentifierListNode || u.Expression is IdentifierNode)
                    {
                        BinaryExpressionNode binRight = new BinaryExpressionNode();
                        BinaryExpressionNode bin = new BinaryExpressionNode();
                        binRight.LeftNode = u.Expression;
                        binRight.RightNode = new IntNode { value = "1" };
                        binRight.Optr = (ProtoCore.DSASM.UnaryOperator.Increment == u.Operator) ? ProtoCore.DSASM.Operator.add : ProtoCore.DSASM.Operator.sub;
                        bin.LeftNode = u.Expression; bin.RightNode = binRight; bin.Optr = ProtoCore.DSASM.Operator.assign;
                        EmitBinaryExpressionNode(bin, ref inferedType);
                    }
                    else
                        throw new BuildHaltException("Invalid use of prefix operation (15BB9C10).");
                }

                DfsTraverse(u.Expression, ref inferedType, false, null, AssociativeSubCompilePass.kNone, parentNode);

                if (!isPrefixOperation)
                {
                    EmitInstrConsole(ProtoCore.DSASM.kw.pop, ProtoCore.DSASM.kw.regAX);
                    ProtoCore.DSASM.StackValue opAX = new ProtoCore.DSASM.StackValue();
                    opAX.optype = ProtoCore.DSASM.AddressType.Register;
                    opAX.opdata = (int)ProtoCore.DSASM.Registers.AX;
                    EmitPop(opAX, Constants.kGlobalScope);

                    string op = opKwData.unaryOpStringTable[u.Operator];
                    EmitInstrConsole(op, ProtoCore.DSASM.kw.regAX);
                    EmitUnary(opKwData.unaryOpCodeTable[u.Operator], opAX);

                    EmitInstrConsole(ProtoCore.DSASM.kw.push, ProtoCore.DSASM.kw.regAX);
                    ProtoCore.DSASM.StackValue opRes = new ProtoCore.DSASM.StackValue();
                    opRes.optype = ProtoCore.DSASM.AddressType.Register;
                    opRes.opdata = (int)ProtoCore.DSASM.Registers.AX;
                    EmitPush(opRes);
                }
            }
        }
Пример #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
            }
        }
Пример #7
0
        protected void EmitThrowNode(ProtoCore.AST.Node node, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone)
        {
            if (!IsParsingGlobal() && !IsParsingGlobalFunctionBody())
            {
                return;
            }

            ThrowNode throwNode = node as ThrowNode;
            if (throwNode == null)
            {
                return;
            }

            BinaryExpressionNode tempAssignmentNode = new BinaryExpressionNode()
            {
                LeftNode = new IdentifierNode()
                {
                    Name = ProtoCore.DSASM.Constants.kTempExceptionVar,
                    Value = ProtoCore.DSASM.Constants.kTempExceptionVar,
                    datatype = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, false),
                },
                Optr = ProtoCore.DSASM.Operator.assign,
                RightNode = throwNode.expression
            };

            ProtoCore.Type inferedType = new ProtoCore.Type();
            inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeVar;
            inferedType.IsIndexable = false;
            DfsTraverse(tempAssignmentNode, ref inferedType, false, graphNode, subPass);
        }
Пример #8
0
        protected void EmitExceptionHandlingNode(ProtoCore.AST.Node node, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone)
        {
            if (!IsParsingGlobal() && !IsParsingGlobalFunctionBody())
            {
                return;
            }

            ExceptionHandlingNode exceptionNode = node as ExceptionHandlingNode;
            if (exceptionNode == null)
                return;

            ExceptionRegistration registration = compileState.ExceptionHandlingManager.ExceptionTable.GetExceptionRegistration(codeBlock.codeBlockId, globalProcIndex, globalClassIndex);
            if (registration == null)
            {
                registration = compileState.ExceptionHandlingManager.ExceptionTable.Register(codeBlock.codeBlockId, globalProcIndex, globalClassIndex);
                Debug.Assert(registration != null);
            }

            tryLevel++;

            ExceptionHandler exceptionHandler = new ExceptionHandler();
            exceptionHandler.TryLevel = tryLevel;
            registration.Add(exceptionHandler);
            TryBlockNode tryNode = exceptionNode.tryBlock;
            Debug.Assert(tryNode != null);
            foreach (var subnode in tryNode.body)
            {
                ProtoCore.Type inferedType = new ProtoCore.Type();
                inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeVar;
                inferedType.IsIndexable = false;
                DfsTraverse(subnode, ref inferedType, false, graphNode, subPass);
            }

            // Jmp to code after catch block

            foreach (var catchBlock in exceptionNode.catchBlocks)
            {
                CatchHandler catchHandler = new CatchHandler();
                exceptionHandler.AddCatchHandler(catchHandler);

                CatchFilterNode filterNode = catchBlock.catchFilter;
                Debug.Assert(filterNode != null);
                catchHandler.FilterTypeUID = compileState.TypeSystem.GetType(filterNode.type.Name);

                // For filter expression catch(e:int), generate an assignment
                //    e = %tmpExp;
                BinaryExpressionNode exceptionAssignmentNode = new BinaryExpressionNode()
                {
                    LeftNode = filterNode.var,
                    Optr = ProtoCore.DSASM.Operator.assign,
                    RightNode = new IdentifierNode()
                    {
                        Name = ProtoCore.DSASM.Constants.kTempExceptionVar,
                        Value = ProtoCore.DSASM.Constants.kTempExceptionVar,
                        datatype = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, false),
                    }
                };
                ProtoCore.Type inferedType = new ProtoCore.Type();
                inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeVar;
                inferedType.IsIndexable = false;
                DfsTraverse(exceptionAssignmentNode, ref inferedType, false, graphNode, subPass);

                foreach (var subnode in catchBlock.body)
                {
                    inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeVar;
                    inferedType.IsIndexable = false;
                    DfsTraverse(subnode, ref inferedType, false, graphNode, subPass);
                }

                // Jmp to code after catch block
            }

            tryLevel--;
        }
Пример #9
0
        private void EmitUnaryExpressionNode(ImperativeNode node, ref ProtoCore.Type inferedType)
        {
            if (IsParsingGlobal() || IsParsingGlobalFunctionBody())
            {
                UnaryExpressionNode u = node as UnaryExpressionNode;
                bool isPrefixOperation = ProtoCore.DSASM.UnaryOperator.Increment == u.Operator || ProtoCore.DSASM.UnaryOperator.Decrement == u.Operator;
                //(Ayush) In case of prefix, apply prefix operation first
                if (isPrefixOperation)
                {
                    if (u.Expression is IdentifierListNode || u.Expression is IdentifierNode)
                    {
                        BinaryExpressionNode binRight = new BinaryExpressionNode();
                        BinaryExpressionNode bin = new BinaryExpressionNode();
                        binRight.LeftNode = u.Expression;
                        binRight.RightNode = new IntNode() { value = "1" };
                        binRight.Optr = (ProtoCore.DSASM.UnaryOperator.Increment == u.Operator) ? ProtoCore.DSASM.Operator.add : ProtoCore.DSASM.Operator.sub;
                        bin.LeftNode = u.Expression; bin.RightNode = binRight; bin.Optr = ProtoCore.DSASM.Operator.assign;
                        EmitBinaryExpressionNode(bin, ref inferedType);
                    }
                    else
                        throw new BuildHaltException("Invalid use of prefix operation.");
                }

                DfsTraverse(u.Expression, ref inferedType);
            }
        }
Пример #10
0
        private void EmitFunctionDefinitionNode(ImperativeNode node, ref ProtoCore.Type inferedType)
        {
            bool parseGlobalFunctionSig = null == localProcedure && ProtoCore.DSASM.ImperativeCompilePass.kGlobalFuncSig == compilePass;
            bool parseGlobalFunctionBody = null == localProcedure && ProtoCore.DSASM.ImperativeCompilePass.kGlobalFuncBody == compilePass;

            FunctionDefinitionNode funcDef = node as FunctionDefinitionNode;
            ProtoCore.DSASM.CodeBlockType originalBlockType = codeBlock.blockType;
            codeBlock.blockType = ProtoCore.DSASM.CodeBlockType.kFunction;
            if (parseGlobalFunctionSig)
            {
                Debug.Assert(null == localProcedure);

                // TODO jun: Add semantics for checking overloads (different parameter types)
                localProcedure = new ProtoCore.DSASM.ProcedureNode();
                localProcedure.name = funcDef.Name;
                localProcedure.localCount = funcDef.localVars;
                localProcedure.returntype.UID = compileState.TypeSystem.GetType(funcDef.ReturnType.Name);
                if (localProcedure.returntype.UID == ProtoCore.DSASM.Constants.kInvalidIndex)
                    localProcedure.returntype.UID = (int)PrimitiveType.kTypeVar;
                localProcedure.returntype.Name = compileState.TypeSystem.GetType(localProcedure.returntype.UID);
                localProcedure.returntype.IsIndexable = funcDef.ReturnType.IsIndexable;
                localProcedure.returntype.rank = funcDef.ReturnType.rank;
                localProcedure.runtimeIndex = codeBlock.codeBlockId;

                globalProcIndex = codeBlock.procedureTable.Append(localProcedure);
                compileState.ProcNode = localProcedure;

                CodeRangeTable.AddCodeBlockFunctionEntry(codeBlock.codeBlockId,
                    globalProcIndex,
                    funcDef.FunctionBody.line,
                    funcDef.FunctionBody.col,
                    funcDef.FunctionBody.endLine,
                    funcDef.FunctionBody.endCol,
                    compileState.CurrentDSFileName);

                // Append arg symbols
                if (null != funcDef.Signature)
                {
                    foreach (VarDeclNode argNode in funcDef.Signature.Arguments)
                    {
                        IdentifierNode paramNode = null;
                        bool aIsDefault = false;
                        ProtoCore.AST.Node aDefaultExpression = null;
                        if (argNode.NameNode is IdentifierNode)
                        {
                            paramNode = argNode.NameNode as IdentifierNode;
                        }
                        else if (argNode.NameNode is BinaryExpressionNode)
                        {
                            BinaryExpressionNode bNode = argNode.NameNode as BinaryExpressionNode;
                            paramNode = bNode.LeftNode as IdentifierNode;
                            aIsDefault = true;
                            aDefaultExpression = bNode;
                            //buildStatus.LogSemanticError("Defualt parameters are not supported");
                            //throw new BuildHaltException();
                        }
                        else
                        {
                            Debug.Assert(false, "Check generated AST");
                        }

                        ProtoCore.Type argType = new ProtoCore.Type();
                        argType.UID = compileState.TypeSystem.GetType(argNode.ArgumentType.Name);
                        if (argType.UID == ProtoCore.DSASM.Constants.kInvalidIndex)
                            argType.UID = (int)PrimitiveType.kTypeVar;
                        argType.Name = compileState.TypeSystem.GetType(argType.UID);
                        argType.IsIndexable = argNode.ArgumentType.IsIndexable;
                        argType.rank = argNode.ArgumentType.rank;
                        int symbolIndex = AllocateArg(paramNode.Value, localProcedure.procId, argType);
                        if (ProtoCore.DSASM.Constants.kInvalidIndex == symbolIndex)
                        {
                            throw new BuildHaltException();
                        }
                        localProcedure.argTypeList.Add(argType);
                        ProtoCore.DSASM.ArgumentInfo argInfo = new ProtoCore.DSASM.ArgumentInfo { isDefault = aIsDefault, defaultExpression = aDefaultExpression, Name = paramNode.Name };
                        localProcedure.argInfoList.Add(argInfo);
                    }
                }

                ExceptionRegistration registration = compileState.ExceptionHandlingManager.ExceptionTable.GetExceptionRegistration(codeBlock.codeBlockId, globalProcIndex, globalClassIndex);
                if (registration == null)
                {
                    registration = compileState.ExceptionHandlingManager.ExceptionTable.Register(codeBlock.codeBlockId, globalProcIndex, globalClassIndex);
                    Debug.Assert(registration != null);
                }
            }
            else if (parseGlobalFunctionBody)
            {
                // Build arglist for comparison
                List<ProtoCore.Type> argList = new List<ProtoCore.Type>();
                if (null != funcDef.Signature)
                {
                    foreach (VarDeclNode argNode in funcDef.Signature.Arguments)
                    {
                        int argType = compileState.TypeSystem.GetType(argNode.ArgumentType.Name);
                        bool isArray = argNode.ArgumentType.IsIndexable;
                        int rank = argNode.ArgumentType.rank;
                        argList.Add(compileState.TypeSystem.BuildTypeObject(argType, isArray, rank));
                    }
                }

                // Get the exisitng procedure that was added on the previous pass
                globalProcIndex = codeBlock.procedureTable.IndexOfExact(funcDef.Name, argList);
                localProcedure = codeBlock.procedureTable.procList[globalProcIndex];

                Debug.Assert(null != localProcedure);

                // Copy the active function to the core so nested language blocks can refer to it
                compileState.ProcNode = localProcedure;

                // Arguments have been allocated, update the baseOffset
                localProcedure.localCount = compileState.BaseOffset;

                ProtoCore.FunctionEndPoint fep = null;

                //Traverse default argument
                foreach (ProtoCore.DSASM.ArgumentInfo argNode in localProcedure.argInfoList)
                {
                    if (!argNode.isDefault)
                    {
                        continue;
                    }
                    BinaryExpressionNode bNode = argNode.defaultExpression as BinaryExpressionNode;
                    // build a temporay node for statement : temp = defaultarg;
                    IdentifierNode iNodeTemp = new IdentifierNode()
                    {
                        Value = ProtoCore.DSASM.Constants.kTempDefaultArg,
                        Name = ProtoCore.DSASM.Constants.kTempDefaultArg,
                        datatype = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, false)
                    };
                    BinaryExpressionNode bNodeTemp = new BinaryExpressionNode();
                    bNodeTemp.LeftNode = iNodeTemp;
                    bNodeTemp.Optr = ProtoCore.DSASM.Operator.assign;
                    bNodeTemp.RightNode = bNode.LeftNode;
                    EmitBinaryExpressionNode(bNodeTemp, ref inferedType);
                    ////duild an inline conditional node for statement: defaultarg = (temp == DefaultArgNode) ? defaultValue : temp;
                    //InlineConditionalNode icNode = new InlineConditionalNode();
                    //BinaryExpressionNode cExprNode = new BinaryExpressionNode();
                    //cExprNode.Optr = ProtoCore.DSASM.Operator.eq;
                    //cExprNode.LeftNode = iNodeTemp;
                    //cExprNode.RightNode = new DefaultArgNode();
                    //icNode.ConditionExpression = cExprNode;
                    //icNode.TrueExpression = bNode.RightNode;
                    //icNode.FalseExpression = iNodeTemp;
                    //bNodeTemp.LeftNode = bNode.LeftNode;
                    //bNodeTemp.RightNode = icNode;
                    //EmitBinaryExpressionNode(bNodeTemp, ref inferedType);
                }

                // Traverse definition
                bool hasReturnStatement = false;
                foreach (ImperativeNode bnode in funcDef.FunctionBody.Body)
                {
                    DfsTraverse(bnode, ref inferedType);
                    BinaryExpressionNode binaryNode = bnode as BinaryExpressionNode;
                    hasReturnStatement = hasReturnStatement || ((binaryNode != null) && (binaryNode.LeftNode.Name == ProtoCore.DSDefinitions.Keyword.Return));
                }

                // All locals have been stack allocated, update the local count of this function
                localProcedure.localCount = compileState.BaseOffset;

                // Update the param stack indices of this function
                foreach (ProtoCore.DSASM.SymbolNode symnode in codeBlock.symbolTable.symbolList.Values)
                {
                    if (symnode.functionIndex == localProcedure.procId && symnode.isArgument)
                    {
                        symnode.index -= localProcedure.localCount;
                    }
                }

                ProtoCore.Lang.JILActivationRecord record = new ProtoCore.Lang.JILActivationRecord();
                record.pc = localProcedure.pc;
                record.locals = localProcedure.localCount;
                record.classIndex = ProtoCore.DSASM.Constants.kInvalidIndex;
                record.funcIndex = localProcedure.procId;
                fep = new ProtoCore.Lang.JILFunctionEndPoint(record);

                // Construct the fep arguments
                fep.FormalParams = new ProtoCore.Type[localProcedure.argTypeList.Count];
                fep.BlockScope = this.codeBlock.codeBlockId;
                localProcedure.argTypeList.CopyTo(fep.FormalParams, 0);

                // TODO Jun: 'classIndexAtCallsite' is the class index as it is stored at the callsite function tables
                // Determine whether this still needs to be aligned to the actual 'classIndex' variable
                // The factors that will affect this is whether the 2 function tables (compiler and callsite) need to be merged
                int classIndexAtCallsite = ProtoCore.DSASM.Constants.kInvalidIndex + 1;
                compileState.FunctionTable.AddFunctionEndPointer(classIndexAtCallsite, funcDef.Name, fep);

                //Fuqiang: return is already done in traversing the function body
                //// function return
                //EmitInstrConsole(ProtoCore.DSASM.kw.ret);
                //EmitReturn();
            }

            compileState.ProcNode = localProcedure = null;
            globalProcIndex = ProtoCore.DSASM.Constants.kGlobalScope;
            argOffset = 0;
            compileState.BaseOffset = 0;
            codeBlock.blockType = originalBlockType;
        }
Пример #11
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
            }
        }
Пример #12
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 
            }
        }
Пример #13
0
        private void EmitUnaryExpressionNode(ImperativeNode node, ref ProtoCore.Type inferedType, ProtoCore.AST.ImperativeAST.BinaryExpressionNode parentNode)
        {
            if (IsParsingGlobal() || IsParsingGlobalFunctionBody())
            {
                UnaryExpressionNode u = node as UnaryExpressionNode;
                bool isPrefixOperation = ProtoCore.DSASM.UnaryOperator.Increment == u.Operator || ProtoCore.DSASM.UnaryOperator.Decrement == u.Operator;
                //(Ayush) In case of prefix, apply prefix operation first
                if (isPrefixOperation)
                {
                    if (u.Expression is IdentifierListNode || u.Expression is IdentifierNode)
                    {
                        BinaryExpressionNode binRight = new BinaryExpressionNode();
                        BinaryExpressionNode bin = new BinaryExpressionNode();
                        binRight.LeftNode = u.Expression;
                        binRight.RightNode = new IntNode(1);
                        binRight.Optr = (ProtoCore.DSASM.UnaryOperator.Increment == u.Operator) ? ProtoCore.DSASM.Operator.add : ProtoCore.DSASM.Operator.sub;
                        bin.LeftNode = u.Expression; bin.RightNode = binRight; bin.Optr = ProtoCore.DSASM.Operator.assign;
                        EmitBinaryExpressionNode(bin, ref inferedType);
                    }
                    else
                        throw new BuildHaltException("Invalid use of prefix operation (15BB9C10).");
                }

                DfsTraverse(u.Expression, ref inferedType, false, null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone, parentNode);

                if (!isPrefixOperation)
                {
                    string op = Op.GetUnaryOpName(u.Operator);
                    EmitInstrConsole(op);
                    EmitUnary(Op.GetUnaryOpCode(u.Operator));
                }
            }
        }
Пример #14
0
 public BinaryExpressionNode(BinaryExpressionNode rhs)
     : base(rhs)
 {
     Optr = rhs.Optr;
     LeftNode = rhs.LeftNode == null ? null : ProtoCore.Utils.NodeUtils.Clone(rhs.LeftNode);
     RightNode = rhs.RightNode == null ? null : ProtoCore.Utils.NodeUtils.Clone(rhs.RightNode);
 }
Пример #15
0
        private void EmitInlineConditionalNode(ImperativeNode node, ref ProtoCore.Type inferedType, ProtoCore.AssociativeGraph.GraphNode graphNode, BinaryExpressionNode parentNode = null)
        {
            InlineConditionalNode inlineConNode = node as InlineConditionalNode;
            IfStmtNode ifNode = new IfStmtNode();
            ifNode.IfExprNode = inlineConNode.ConditionExpression;
            List<ImperativeNode> trueBody = new List<ImperativeNode>();
            trueBody.Add(inlineConNode.TrueExpression);
            List<ImperativeNode> falseBody = new List<ImperativeNode>();
            falseBody.Add(inlineConNode.FalseExpression);
            ifNode.IfBody = trueBody;
            ifNode.ElseBody = falseBody;

            DebugProperties.BreakpointOptions oldOptions = core.DebuggerProperties.breakOptions;
            DebugProperties.BreakpointOptions newOptions = oldOptions;
            newOptions |= DebugProperties.BreakpointOptions.EmitInlineConditionalBreakpoint;
            core.DebuggerProperties.breakOptions = newOptions;

            EmitIfStmtNode(ifNode, ref inferedType, parentNode, true, graphNode);

            core.DebuggerProperties.breakOptions = oldOptions;
        }