public int Emit(CodeBlockNode codeblock) { bool isTopBlock = null == codeBlock.parent; if (!isTopBlock) { // If this is an inner block where there can be no classes, we can start at parsing at the global function state compilePass = ProtoCore.DSASM.ImperativeCompilePass.kGlobalFuncSig; } CodeRangeTable.AddCodeBlockRangeEntry(codeBlock.codeBlockId, codeblock.line, codeblock.col, codeblock.endLine, codeblock.endCol, compileState.CurrentDSFileName); ProtoCore.Type type = new ProtoCore.Type(); while (ProtoCore.DSASM.ImperativeCompilePass.kDone != compilePass) { foreach (ImperativeNode node in codeblock.Body) { type = new ProtoCore.Type(); type.UID = (int)PrimitiveType.kTypeVar; type.IsIndexable = false; DfsTraverse(node, ref type); } compilePass++; } compileState.InferedType = type; return codeBlock.codeBlockId; }
public CodeBlockNode(CodeBlockNode rhs) : base(rhs) { Body = new List <ImperativeNode>(); foreach (ImperativeNode aNode in rhs.Body) { ImperativeNode newNode = ProtoCore.Utils.NodeUtils.Clone(aNode); Body.Add(newNode); } }
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 } }
public CodeBlockNode(CodeBlockNode rhs) : base(rhs) { Body = new List<ImperativeNode>(); foreach (ImperativeNode aNode in rhs.Body) { ImperativeNode newNode = ProtoCore.Utils.NodeUtils.Clone(aNode); Body.Add(newNode); } }