public ArrayNameNode(ArrayNameNode rhs) : base(rhs) { ArrayDimensions = null; if (null != rhs.ArrayDimensions) { ArrayDimensions = new ArrayNode(rhs.ArrayDimensions); } }
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); } } }
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"); } }
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 } }
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(); } }
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 } }
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 ArrayNameNode() { ArrayDimensions = null; }