public static ProtoCore.AST.AssociativeAST.ExprListNode BuildArrayExprList(ProtoCore.AST.AssociativeAST.AssociativeNode arrayNode) { ProtoCore.AST.AssociativeAST.ExprListNode exprlist = new ProtoCore.AST.AssociativeAST.ExprListNode(); while (arrayNode is ProtoCore.AST.AssociativeAST.ArrayNode) { ProtoCore.AST.AssociativeAST.ArrayNode array = arrayNode as ProtoCore.AST.AssociativeAST.ArrayNode; exprlist.list.Add(array.Expr); arrayNode = array.Type; } return(exprlist); }
private void EmitArrayNode(AST.AssociativeAST.ArrayNode arrayNode) { if (null != arrayNode) { EmitCode("["); DFSTraverse(arrayNode.Expr); EmitCode("]"); if (arrayNode.Type != null) { DFSTraverse(arrayNode.Type); } } }
public ExportWithUnits() { SelectedExportedUnit = ConversionUnit.Feet; SelectedExportedUnitsSource = Conversions.ConversionMetricLookup[ConversionMetricUnit.Length]; AssociativeNode geometryNode = new ArrayNode(); AssociativeNode stringNode = new StringNode(); InPortData.Add(new PortData("geometry", Resources.ExportToSatGeometryInputDescription, geometryNode)); InPortData.Add(new PortData("filePath", Resources.ExportToSatFilePathDescription, stringNode)); OutPortData.Add(new PortData("string", Resources.ExportToSatFilePathOutputDescription)); ShouldDisplayPreviewCore = true; RegisterAllPorts(); }
private void DFSEmitSSA_AST(AssociativeNode node, Stack<AssociativeNode> ssaStack, ref List<AssociativeNode> astlist) { Validity.Assert(null != astlist && null != ssaStack); if (node is BinaryExpressionNode) { BinaryExpressionNode astBNode = node as BinaryExpressionNode; AssociativeNode leftNode = null; AssociativeNode rightNode = null; bool isSSAAssignment = false; if (ProtoCore.DSASM.Operator.assign == astBNode.Optr) { leftNode = astBNode.LeftNode; DFSEmitSSA_AST(astBNode.RightNode, ssaStack, ref astlist); AssociativeNode assocNode = ssaStack.Pop(); if (assocNode is BinaryExpressionNode) { rightNode = (assocNode as BinaryExpressionNode).LeftNode; } else { rightNode = assocNode; } isSSAAssignment = false; // Handle SSA if the lhs is not an identifier // A non-identifier LHS is any LHS that is not just an identifier name. // i.e. a[0], a.b, f(), f(x) var isSingleIdentifier = (leftNode is IdentifierNode) && (leftNode as IdentifierNode).ArrayDimensions == null; if (!isSingleIdentifier) { EmitSSALHS(ref leftNode, ssaStack, ref astlist); } } else { BinaryExpressionNode tnode = new BinaryExpressionNode(); tnode.Optr = astBNode.Optr; DFSEmitSSA_AST(astBNode.LeftNode, ssaStack, ref astlist); DFSEmitSSA_AST(astBNode.RightNode, ssaStack, ref astlist); AssociativeNode lastnode = ssaStack.Pop(); AssociativeNode prevnode = ssaStack.Pop(); tnode.LeftNode = prevnode is BinaryExpressionNode ? (prevnode as BinaryExpressionNode).LeftNode : prevnode; tnode.RightNode = lastnode is BinaryExpressionNode ? (lastnode as BinaryExpressionNode).LeftNode : lastnode; // Left node leftNode = AstFactory.BuildIdentifier(CoreUtils.BuildSSATemp(core)); // Right node rightNode = tnode; isSSAAssignment = true; } var bnode = AstFactory.BuildAssignment(leftNode, rightNode); bnode.isSSAAssignment = isSSAAssignment; bnode.IsInputExpression = astBNode.IsInputExpression; astlist.Add(bnode); ssaStack.Push(bnode); } else if (node is ArrayNode) { var arrayNode = node as ArrayNode; DFSEmitSSA_AST(arrayNode.Expr, ssaStack, ref astlist); var bnode = new BinaryExpressionNode { Optr = Operator.assign }; // Left node var tmpIdent = AstFactory.BuildIdentifier(CoreUtils.BuildSSATemp(core)); Validity.Assert(null != tmpIdent); bnode.LeftNode = tmpIdent; if (arrayNode.Expr == null && arrayNode.Type == null) { // Right node bnode.RightNode = new NullNode(); astlist.Add(bnode); ssaStack.Push(bnode); return; } // pop off the dimension var dimensionNode = ssaStack.Pop(); ArrayNode currentDimensionNode; if (dimensionNode is BinaryExpressionNode) { currentDimensionNode = new ArrayNode((dimensionNode as BinaryExpressionNode).LeftNode, null); } else { currentDimensionNode = new ArrayNode(dimensionNode, null); } // Pop the prev SSA node where the current dimension will apply AssociativeNode nodePrev = ssaStack.Pop(); if (nodePrev is BinaryExpressionNode) { AssociativeNode rhsIdent =AstFactory.BuildIdentifier((nodePrev as BinaryExpressionNode).LeftNode.Name); (rhsIdent as IdentifierNode).ArrayDimensions = currentDimensionNode; bnode.RightNode = rhsIdent; astlist.Add(bnode); ssaStack.Push(bnode); if (null != arrayNode.Type) { DFSEmitSSA_AST(arrayNode.Type, ssaStack, ref astlist); } } else if (nodePrev is IdentifierListNode) { IdentifierNode iNode = (nodePrev as IdentifierListNode).RightNode as IdentifierNode; Validity.Assert(null != iNode); iNode.ArrayDimensions = currentDimensionNode; if (null != arrayNode.Type) { DFSEmitSSA_AST(arrayNode.Type, ssaStack, ref astlist); } } else { Validity.Assert(false); } } else if (node is IdentifierNode) { IdentifierNode ident = node as IdentifierNode; if (core.Options.GenerateSSA) { string ssaTempName = string.Empty; if (null == ident.ArrayDimensions) { BinaryExpressionNode bnode = new BinaryExpressionNode(); bnode.Optr = ProtoCore.DSASM.Operator.assign; // Left node ssaTempName = ProtoCore.Utils.CoreUtils.BuildSSATemp(core); var identNode =AstFactory.BuildIdentifier(ssaTempName); bnode.LeftNode = identNode; // Right node bnode.RightNode = ident; bnode.isSSAAssignment = true; astlist.Add(bnode); ssaStack.Push(bnode); // Associate the first pointer with each SSA temp // It is acceptable to store firstVar even if it is not a pointer as ResolveFinalNodeRefs() will just ignore this entry // if this ssa temp is not treated as a pointer inside the function string firstVar = ident.Name; ssaTempToFirstPointerMap.Add(ssaTempName, firstVar); } else { EmitSSAArrayIndex(ident, ssaStack, ref astlist); } } else { BinaryExpressionNode bnode = new BinaryExpressionNode(); bnode.Optr = ProtoCore.DSASM.Operator.assign; // Left node var identNode =AstFactory.BuildIdentifier(ProtoCore.Utils.CoreUtils.BuildSSATemp(core)); bnode.LeftNode = identNode; // Right node bnode.RightNode = ident; bnode.isSSAAssignment = true; astlist.Add(bnode); ssaStack.Push(bnode); } } else if (node is FunctionCallNode || node is FunctionDotCallNode) { FunctionCallNode fcNode = null; if (node is FunctionCallNode) { fcNode = new FunctionCallNode(node as FunctionCallNode); List<AssociativeNode> astlistArgs = new List<AssociativeNode>(); for (int idx = 0; idx < fcNode.FormalArguments.Count; idx++) { AssociativeNode arg = fcNode.FormalArguments[idx]; DFSEmitSSA_AST(arg, ssaStack, ref astlistArgs); AssociativeNode argNode = ssaStack.Pop(); if (argNode is BinaryExpressionNode) { BinaryExpressionNode argBinaryExpr = argNode as BinaryExpressionNode; var argLeftNode = argBinaryExpr.LeftNode as IdentifierNode; argLeftNode.ReplicationGuides = GetReplicationGuides(arg); argLeftNode.AtLevel = GetAtLevel(arg); fcNode.FormalArguments[idx] = argBinaryExpr.LeftNode; } else { fcNode.FormalArguments[idx] = argNode; } astlist.AddRange(astlistArgs); astlistArgs.Clear(); } } // Left node var leftNode =AstFactory.BuildIdentifier(CoreUtils.BuildSSATemp(core)); if (null != fcNode) { leftNode.ReplicationGuides = GetReplicationGuides(fcNode); leftNode.AtLevel = GetAtLevel(fcNode); } var bnode = AstFactory.BuildAssignment(leftNode, fcNode); bnode.isSSAAssignment = true; astlist.Add(bnode); ssaStack.Push(bnode); } else if (node is IdentifierListNode) { SSAIdentList(node, ref ssaStack, ref astlist); AssociativeNode lastNode = null; Validity.Assert(astlist.Count > 0); // Get the last identifierlist node and set its flag // This is required to reset the pointerlist for every identifierlist traversed // i.e. // a = p.x // reset the flag after traversing p.x // // b = p.x + g.y // reset the flag after traversing p.x and p.y // int lastIndex = astlist.Count - 1; for (int n = lastIndex; n >= 0 ; --n) { lastNode = astlist[n]; Validity.Assert(lastNode is BinaryExpressionNode); BinaryExpressionNode bnode = lastNode as BinaryExpressionNode; Validity.Assert(bnode.Optr == Operator.assign); if (bnode.RightNode is IdentifierListNode) { IdentifierListNode identList = bnode.RightNode as IdentifierListNode; identList.IsLastSSAIdentListFactor = true; break; } } // Assign the first ssa assignment flag BinaryExpressionNode firstBNode = astlist[0] as BinaryExpressionNode; Validity.Assert(null != firstBNode); Validity.Assert(firstBNode.Optr == Operator.assign); firstBNode.isSSAFirstAssignment = true; // // Get the first pointer // The first pointer is the lhs of the next dotcall // // Given: // a = x.y.z // SSA'd to: // t0 = x -> 'x' is the lhs of the first dotcall (x.y) // t1 = t0.y // t2 = t1.z // a = t2 IdentifierNode lhsIdent = null; if (firstBNode.RightNode is IdentifierNode) { // In this case the rhs of the ident list is an ident // Get the ident name lhsIdent = (firstBNode.RightNode as IdentifierNode); } else if(firstBNode.RightNode is FunctionCallNode) { // In this case the rhs of the ident list is a function // Get the function name lhsIdent = (firstBNode.RightNode as FunctionCallNode).Function as IdentifierNode; } else { lhsIdent = null; } //========================================================= // // 1. Backtrack and convert all identlist nodes to dot calls // This can potentially be optimized by performing the dotcall transform in SSAIdentList // // 2. Associate the first pointer with each SSA temp // //========================================================= AssociativeNode prevNode = null; for (int n = 0; n <= lastIndex; n++) { lastNode = astlist[n]; BinaryExpressionNode bnode = lastNode as BinaryExpressionNode; Validity.Assert(bnode.Optr == Operator.assign); // Get the ssa temp name Validity.Assert(bnode.LeftNode is IdentifierNode); string ssaTempName = (bnode.LeftNode as IdentifierNode).Name; Validity.Assert(CoreUtils.IsSSATemp(ssaTempName)); if (bnode.RightNode is IdentifierListNode) { IdentifierListNode identList = bnode.RightNode as IdentifierListNode; if (identList.RightNode is IdentifierNode) { IdentifierNode identNode = identList.RightNode as IdentifierNode; ProtoCore.AST.AssociativeAST.FunctionCallNode rcall = new ProtoCore.AST.AssociativeAST.FunctionCallNode(); rcall.Function = new IdentifierNode(identNode); rcall.Function.Name = ProtoCore.DSASM.Constants.kGetterPrefix + rcall.Function.Name; ProtoCore.Utils.CoreUtils.CopyDebugData(identList.LeftNode, lhsIdent); FunctionDotCallNode dotCall = ProtoCore.Utils.CoreUtils.GenerateCallDotNode(identList.LeftNode, rcall, core); dotCall.isLastSSAIdentListFactor = identList.IsLastSSAIdentListFactor; bnode.RightNode = dotCall; ProtoCore.Utils.CoreUtils.CopyDebugData(bnode, lhsIdent); // Update the LHS of the next dotcall // a = x.y.z // t0 = x // t1 = t0.y 'y' is the lhs of the next dotcall (y.z) // t2 = t1.z // a = t2 // Validity.Assert(rcall.Function is IdentifierNode); lhsIdent = rcall.Function as IdentifierNode; } else if (identList.RightNode is FunctionCallNode) { FunctionCallNode fCallNode = identList.RightNode as FunctionCallNode; ProtoCore.Utils.CoreUtils.CopyDebugData(identList.LeftNode, lhsIdent); FunctionDotCallNode dotCall = ProtoCore.Utils.CoreUtils.GenerateCallDotNode(identList.LeftNode, fCallNode, core); dotCall.isLastSSAIdentListFactor = identList.IsLastSSAIdentListFactor; bnode.RightNode = dotCall; ProtoCore.Utils.CoreUtils.CopyDebugData(bnode, lhsIdent); // Update the LHS of the next dotcall // a = x.y.z // t0 = x // t1 = t0.y 'y' is the lhs of the next dotcall (y.z) // t2 = t1.z // a = t2 // Validity.Assert(fCallNode.Function is IdentifierNode); lhsIdent = fCallNode.Function as IdentifierNode; } else { Validity.Assert(false); } } prevNode = bnode.RightNode; } } else if (node is ExprListNode) { ExprListNode exprList = node as ExprListNode; for (int n = 0; n < exprList.Exprs.Count; n++) { List<AssociativeNode> currentElementASTList = new List<AssociativeNode>(); DFSEmitSSA_AST(exprList.Exprs[n], ssaStack, ref currentElementASTList); astlist.AddRange(currentElementASTList); currentElementASTList.Clear(); AssociativeNode argNode = ssaStack.Pop(); exprList.Exprs[n] = argNode is BinaryExpressionNode ? (argNode as BinaryExpressionNode).LeftNode : argNode; } var leftNode = AstFactory.BuildIdentifier(CoreUtils.BuildSSATemp(core)); var bnode = AstFactory.BuildAssignment(leftNode, exprList); bnode.isSSAAssignment = true; astlist.Add(bnode); ssaStack.Push(bnode); } else if (node is InlineConditionalNode) { InlineConditionalNode ilnode = node as InlineConditionalNode; List<AssociativeNode> inlineExpressionASTList = new List<AssociativeNode>(); // Emit the boolean condition DFSEmitSSA_AST(ilnode.ConditionExpression, ssaStack, ref inlineExpressionASTList); AssociativeNode cexpr = ssaStack.Pop(); ilnode.ConditionExpression = cexpr is BinaryExpressionNode ? (cexpr as BinaryExpressionNode).LeftNode : cexpr; var namenode = ilnode.ConditionExpression as ArrayNameNode; if (namenode != null) { var rightNode = (cexpr is BinaryExpressionNode) ? (cexpr as BinaryExpressionNode).RightNode : cexpr; namenode.ReplicationGuides = GetReplicationGuides(rightNode); namenode.AtLevel = GetAtLevel(rightNode); } astlist.AddRange(inlineExpressionASTList); inlineExpressionASTList.Clear(); DFSEmitSSA_AST(ilnode.TrueExpression, ssaStack, ref inlineExpressionASTList); cexpr = ssaStack.Pop(); ilnode.TrueExpression = cexpr is BinaryExpressionNode ? (cexpr as BinaryExpressionNode).LeftNode : cexpr; namenode = ilnode.TrueExpression as ArrayNameNode; if (namenode != null) { var rightNode = (cexpr is BinaryExpressionNode) ? (cexpr as BinaryExpressionNode).RightNode : cexpr; namenode.ReplicationGuides = GetReplicationGuides(rightNode); namenode.AtLevel = GetAtLevel(rightNode); } astlist.AddRange(inlineExpressionASTList); inlineExpressionASTList.Clear(); DFSEmitSSA_AST(ilnode.FalseExpression, ssaStack, ref inlineExpressionASTList); cexpr = ssaStack.Pop(); ilnode.FalseExpression = cexpr is BinaryExpressionNode ? (cexpr as BinaryExpressionNode).LeftNode : cexpr; namenode = ilnode.FalseExpression as ArrayNameNode; if (namenode != null) { var rightNode = (cexpr is BinaryExpressionNode) ? (cexpr as BinaryExpressionNode).RightNode : cexpr; namenode.ReplicationGuides = GetReplicationGuides(rightNode); namenode.AtLevel = GetAtLevel(rightNode); } astlist.AddRange(inlineExpressionASTList); inlineExpressionASTList.Clear(); var leftNode = AstFactory.BuildIdentifier(CoreUtils.BuildSSATemp(core)); var bnode = AstFactory.BuildAssignment(leftNode, ilnode); bnode.isSSAAssignment = true; astlist.Add(bnode); ssaStack.Push(bnode); } else if (node is RangeExprNode) { RangeExprNode rangeNode = node as RangeExprNode; DFSEmitSSA_AST(rangeNode.From, ssaStack, ref astlist); AssociativeNode fromExpr = ssaStack.Pop(); rangeNode.From = fromExpr is BinaryExpressionNode ? (fromExpr as BinaryExpressionNode).LeftNode : fromExpr; DFSEmitSSA_AST(rangeNode.To, ssaStack, ref astlist); AssociativeNode toExpr = ssaStack.Pop(); rangeNode.To = toExpr is BinaryExpressionNode ? (toExpr as BinaryExpressionNode).LeftNode : toExpr; if (rangeNode.Step != null) { DFSEmitSSA_AST(rangeNode.Step, ssaStack, ref astlist); AssociativeNode stepExpr = ssaStack.Pop(); rangeNode.Step = stepExpr is BinaryExpressionNode ? (stepExpr as BinaryExpressionNode).LeftNode : stepExpr; } var leftNode = AstFactory.BuildIdentifier(CoreUtils.BuildSSATemp(core)); var bnode = AstFactory.BuildAssignment(leftNode, rangeNode); bnode.isSSAAssignment = true; astlist.Add(bnode); ssaStack.Push(bnode); } else if (node is GroupExpressionNode) { if (core.Options.GenerateSSA) { GroupExpressionNode groupExpr = node as GroupExpressionNode; if (null == groupExpr.ArrayDimensions) { DFSEmitSSA_AST(groupExpr.Expression, ssaStack, ref astlist); var leftNode =AstFactory.BuildIdentifier(CoreUtils.BuildSSATemp(core)); AssociativeNode groupExprBinaryStmt = ssaStack.Pop(); var rightNode = (groupExprBinaryStmt as BinaryExpressionNode).LeftNode; var bnode = AstFactory.BuildAssignment(leftNode, rightNode); bnode.isSSAAssignment = true; astlist.Add(bnode); ssaStack.Push(bnode); } else { EmitSSAArrayIndex(groupExpr, ssaStack, ref astlist); } } else { // We never supported SSA on grouped expressions // Keep it that way if SSA flag is off ssaStack.Push(node); } } // We allow a null to be generated an SSA variable // TODO Jun: Generalize this into genrating SSA temps for all literals else if (node is NullNode) { var leftNode = AstFactory.BuildIdentifier(CoreUtils.BuildSSATemp(core)); var bnode = AstFactory.BuildAssignment(leftNode, node); bnode.isSSAAssignment = true; astlist.Add(bnode); ssaStack.Push(bnode); } else { ssaStack.Push(node); } }
/// <summary> /// Emits the SSA form of each dimension in the ArrayNode data structure /// The dimensionNode is updated by the function with the SSA'd dimensions /// /// Given: /// dimensionNode -> a[b][c] /// Outputs: /// astlist -> t0 = b /// -> t1 = c /// dimensionNode -> a[t0][t1] /// /// </summary> /// <param name="dimensionNode"></param> /// <param name="astlist"></param> private void EmitSSAforArrayDimension(ref ArrayNode dimensionNode, ref List<AssociativeNode> astlist) { AssociativeNode indexNode = dimensionNode.Expr; // Traverse first dimension Stack<AssociativeNode> localStack = new Stack<AssociativeNode>(); DFSEmitSSA_AST(indexNode, localStack, ref astlist); AssociativeNode tempIndexNode = localStack.Last(); if (tempIndexNode is BinaryExpressionNode) { dimensionNode.Expr = (tempIndexNode as BinaryExpressionNode).LeftNode; // Traverse next dimension indexNode = dimensionNode.Type; while (indexNode is ArrayNode) { ArrayNode arrayNode = indexNode as ArrayNode; localStack = new Stack<AssociativeNode>(); DFSEmitSSA_AST(arrayNode.Expr, localStack, ref astlist); tempIndexNode = localStack.Last(); if (tempIndexNode is BinaryExpressionNode) { arrayNode.Expr = (tempIndexNode as BinaryExpressionNode).LeftNode; } indexNode = arrayNode.Type; } } }
/// <summary> /// This function applies SSA tranform to an array indexed identifier or identifier list /// /// The transform applies as such: /// i = 0 /// j = 1 /// x = a[i][j] /// /// t0 = a /// t1 = i /// t2 = t0[t1] /// t3 = j /// t4 = t2[t3] /// x = t4 /// /// </summary> /// <param name="idendNode"></param> /// <param name="ssaStack"></param> /// <param name="astlist"></param> private void EmitSSAArrayIndex(AssociativeNode node, Stack<AssociativeNode> ssaStack, ref List<AssociativeNode> astlist, bool isSSAPointerAssignment = false) { // // Build the first SSA binary assignment of the identifier without its indexing // x = a[i][j] -> t0 = a // BinaryExpressionNode bnode = new BinaryExpressionNode(); bnode.Optr = ProtoCore.DSASM.Operator.assign; // Left node string ssaTempName = ProtoCore.Utils.CoreUtils.BuildSSATemp(core); var tmpName =AstFactory.BuildIdentifier(ssaTempName); bnode.LeftNode = tmpName; bnode.isSSAAssignment = true; bnode.isSSAPointerAssignment = isSSAPointerAssignment; bnode.isSSAFirstAssignment = true; IdentifierNode identNode = null; ArrayNode arrayDimensions = null; string firstVarName = string.Empty; if (node is IdentifierNode) { identNode = node as IdentifierNode; // Right node - Array indexing will be applied to this new identifier firstVarName = identNode.Name; bnode.RightNode =AstFactory.BuildIdentifier(firstVarName); ProtoCore.Utils.CoreUtils.CopyDebugData(bnode.RightNode, node); // Get the array dimensions of this node arrayDimensions = identNode.ArrayDimensions; // Associate the first pointer with each SSA temp // It is acceptable to store firstVar even if it is not a pointer as ResolveFinalNodeRefs() will just ignore this entry // if this ssa temp is not treated as a pointer inside the function if (!ssaTempToFirstPointerMap.ContainsKey(ssaTempName)) { ssaTempToFirstPointerMap.Add(ssaTempName, firstVarName); } } else if (node is FunctionCallNode) { FunctionCallNode fcall = node as FunctionCallNode; Validity.Assert(fcall.Function is IdentifierNode); identNode = fcall.Function as IdentifierNode; // Assign the function array and guide properties to the new ident node identNode.ArrayDimensions = fcall.ArrayDimensions; identNode.ReplicationGuides = fcall.ReplicationGuides; identNode.AtLevel = fcall.AtLevel; // Right node - Remove the function array indexing. // The array indexing to this function will be applied downstream fcall.ArrayDimensions = null; bnode.RightNode = fcall; //ProtoCore.Utils.CoreUtils.CopyDebugData(bnode.RightNode, node); // Get the array dimensions of this node arrayDimensions = identNode.ArrayDimensions; } else if (node is IdentifierListNode) { // Apply array indexing to the right node of the ident list // a = p.x[i] -> apply it to x IdentifierListNode identList = node as IdentifierListNode; AssociativeNode rhsNode = identList.RightNode; if (rhsNode is IdentifierNode) { identNode = rhsNode as IdentifierNode; // Replace the indexed identifier with a new ident with the same name // i.e. replace x[i] with x AssociativeNode nonIndexedIdent =AstFactory.BuildIdentifier(identNode.Name); identList.RightNode = nonIndexedIdent; // Get the array dimensions of this node arrayDimensions = identNode.ArrayDimensions; } else if (rhsNode is FunctionCallNode) { FunctionCallNode fcall = rhsNode as FunctionCallNode; identNode = fcall.Function as IdentifierNode; AssociativeNode newCall = AstFactory.BuildFunctionCall(identNode.Name, fcall.FormalArguments); // Assign the function array and guide properties to the new ident node identNode.ArrayDimensions = fcall.ArrayDimensions; identNode.ReplicationGuides = fcall.ReplicationGuides; identNode.AtLevel = fcall.AtLevel; identList.RightNode = newCall; // Get the array dimensions of this node arrayDimensions = identNode.ArrayDimensions; } else { Validity.Assert(false, "This token is not indexable"); } // Right node bnode.RightNode = identList; //ProtoCore.Utils.CoreUtils.CopyDebugData(bnode.RightNode, node); bnode.isSSAPointerAssignment = true; } else if (node is GroupExpressionNode) { GroupExpressionNode groupExpr = node as GroupExpressionNode; DFSEmitSSA_AST(groupExpr.Expression, ssaStack, ref astlist); arrayDimensions = groupExpr.ArrayDimensions; } else { Validity.Assert(false); } // Push the first SSA stmt astlist.Add(bnode); ssaStack.Push(bnode); // Traverse the array index // t1 = i List<AssociativeNode> arrayDimASTList = new List<AssociativeNode>(); DFSEmitSSA_AST(arrayDimensions.Expr, ssaStack, ref arrayDimASTList); astlist.AddRange(arrayDimASTList); arrayDimASTList.Clear(); // // Build the indexing statement // t2 = t0[t1] BinaryExpressionNode indexedStmt = new BinaryExpressionNode(); indexedStmt.Optr = ProtoCore.DSASM.Operator.assign; // Build the left node of the indexing statement #region SSA_INDEX_STMT_LEFT ssaTempName = ProtoCore.Utils.CoreUtils.BuildSSATemp(core); AssociativeNode tmpIdent =AstFactory.BuildIdentifier(ssaTempName); Validity.Assert(null != tmpIdent); indexedStmt.LeftNode = tmpIdent; //ProtoCore.Utils.CoreUtils.CopyDebugData(bnode, node); // Associate the first pointer with each SSA temp // It is acceptable to store firstVar even if it is not a pointer as ResolveFinalNodeRefs() will just ignore this entry // if this ssa temp is not treated as a pointer inside the function if (!string.IsNullOrEmpty(firstVarName)) { if (!ssaTempToFirstPointerMap.ContainsKey(ssaTempName)) { ssaTempToFirstPointerMap.Add(ssaTempName, firstVarName); } } #endregion // Build the right node of the indexing statement #region SSA_INDEX_STMT_RIGHT ArrayNode arrayNode = null; // pop off the dimension AssociativeNode dimensionNode = ssaStack.Pop(); if (dimensionNode is BinaryExpressionNode) { arrayNode = new ArrayNode((dimensionNode as BinaryExpressionNode).LeftNode, null); } else { arrayNode = new ArrayNode(dimensionNode, null); } // pop off the prev SSA variable AssociativeNode prevSSAStmt = ssaStack.Pop(); // Assign the curent dimension to the prev SSA variable Validity.Assert(prevSSAStmt is BinaryExpressionNode); AssociativeNode rhsIdent =AstFactory.BuildIdentifier((prevSSAStmt as BinaryExpressionNode).LeftNode.Name); (rhsIdent as IdentifierNode).ArrayDimensions = arrayNode; // Right node of the indexing statement indexedStmt.RightNode = rhsIdent; astlist.Add(indexedStmt); ssaStack.Push(indexedStmt); // Traverse the next dimension // [j] if (null != arrayDimensions.Type) { DFSEmitSSA_AST(arrayDimensions.Type, ssaStack, ref arrayDimASTList); astlist.AddRange(arrayDimASTList); arrayDimASTList.Clear(); } #endregion }
/// <summary> /// This function applies SSA tranform to an array indexed identifier or identifier list /// /// The transform applies as such: /// i = 0 /// j = 1 /// x = a[i][j] /// /// t0 = a /// t1 = i /// t2 = t0[t1] /// t3 = j /// t4 = t2[t3] /// x = t4 /// /// </summary> /// <param name="idendNode"></param> /// <param name="ssaStack"></param> /// <param name="astlist"></param> private void EmitSSAArrayIndex(AssociativeNode node, Stack<AssociativeNode> ssaStack, ref List<AssociativeNode> astlist, bool isSSAPointerAssignment = false) { // // Build the first SSA binary assignment of the identifier without its indexing // x = a[i][j] -> t0 = a // BinaryExpressionNode bnode = new BinaryExpressionNode(); bnode.Optr = ProtoCore.DSASM.Operator.assign; // Left node var tmpName = nodeBuilder.BuildIdentfier(ProtoCore.Utils.CoreUtils.GetSSATemp(compileStateTracker)); bnode.LeftNode = tmpName; bnode.isSSAAssignment = true; bnode.isSSAPointerAssignment = isSSAPointerAssignment; bnode.isSSAFirstAssignment = true; IdentifierNode identNode = null; if (node is IdentifierNode) { identNode = node as IdentifierNode; // Right node - Array indexing will be applied to this new identifier bnode.RightNode = nodeBuilder.BuildIdentfier(identNode.Name); } else if (node is FunctionCallNode) { FunctionCallNode fcall = node as FunctionCallNode; Validity.Assert(fcall.Function is IdentifierNode); identNode = fcall.Function as IdentifierNode; // Assign the function array and guide properties to the new ident node identNode.ArrayDimensions = fcall.ArrayDimensions; identNode.ReplicationGuides = fcall.ReplicationGuides; // Right node - Remove the function array indexing. // The array indexing to this function will be applied downstream fcall.ArrayDimensions = null; bnode.RightNode = fcall; } else if (node is IdentifierListNode) { // Apply array indexing to the right node of the ident list // a = p.x[i] -> apply it to x IdentifierListNode identList = node as IdentifierListNode; AssociativeNode rhsNode = identList.RightNode; Validity.Assert(rhsNode is IdentifierNode); identNode = rhsNode as IdentifierNode; // Replace the indexed identifier with a new ident with the same name // i.e. replace x[i] with x AssociativeNode nonIndexedIdent = nodeBuilder.BuildIdentfier(identNode.Name); identList.RightNode = nonIndexedIdent; // Right node bnode.RightNode = identList; bnode.isSSAPointerAssignment = true; } else { Validity.Assert(false); } // Push the first SSA stmt astlist.Add(bnode); ssaStack.Push(bnode); // Traverse the array index // t1 = i DFSEmitSSA_AST(identNode.ArrayDimensions.Expr, ssaStack, ref astlist); // // Build the indexing statement // t2 = t0[t1] BinaryExpressionNode indexedStmt = new BinaryExpressionNode(); indexedStmt.Optr = ProtoCore.DSASM.Operator.assign; // Build the left node of the indexing statement #region SSA_INDEX_STMT_LEFT AssociativeNode tmpIdent = nodeBuilder.BuildIdentfier(ProtoCore.Utils.CoreUtils.GetSSATemp(compileStateTracker)); Validity.Assert(null != tmpIdent); indexedStmt.LeftNode = tmpIdent; #endregion // Build the right node of the indexing statement #region SSA_INDEX_STMT_RIGHT ArrayNode arrayNode = null; // pop off the dimension AssociativeNode dimensionNode = ssaStack.Pop(); if (dimensionNode is BinaryExpressionNode) { arrayNode = new ArrayNode((dimensionNode as BinaryExpressionNode).LeftNode, null); } else { arrayNode = new ArrayNode(dimensionNode, null); } // pop off the prev SSA variable AssociativeNode prevSSAStmt = ssaStack.Pop(); // Assign the curent dimension to the prev SSA variable Validity.Assert(prevSSAStmt is BinaryExpressionNode); AssociativeNode rhsIdent = nodeBuilder.BuildIdentfier((prevSSAStmt as BinaryExpressionNode).LeftNode.Name); (rhsIdent as IdentifierNode).ArrayDimensions = arrayNode; // Right node of the indexing statement indexedStmt.RightNode = rhsIdent; astlist.Add(indexedStmt); ssaStack.Push(indexedStmt); // Traverse the next dimension // [j] if (null != identNode.ArrayDimensions.Type) { DFSEmitSSA_AST(identNode.ArrayDimensions.Type, ssaStack, ref astlist); } #endregion }
/* proc DFSEmit_SSA_AST(node, ssastack[], astlist[]) if node is binary expression def bnode if node.optr is assign op bnode.optr = node.optr bnode.left = node.left DFSEmit_SSA_AST(node.right, ssastack, astlist) bnode.right = ssastack.pop() else def tnode tnode.optr = node.optr DFSEmit_SSA_AST(node.left, ssastack, astlist) DFSEmit_SSA_AST(node.right, ssastack, astlist) def lastnode = ssastack.pop() def prevnode = ssastack.pop() if prevnode is binary tnode.left = prevnode.left else tnode.left = prevnode end if lastnode is binary tnode.right = lastnode.left else tnode.right = lastnode end bnode.optr = �=� bnode.left = GetSSATemp() bnode.right = tnode end astlist.append(bnode) ssastack.push(bnode) else if node is identifier def bnode bnode.optr = �=� bnode.left = GetSSATemp() bnode.right = node astlist.append(bnode) ssastack.push(bnode) else ssastack.push(node) end end */ private void DFSEmitSSA_AST(AssociativeNode node, Stack<AssociativeNode> ssaStack, ref List<AssociativeNode> astlist) { Debug.Assert(null != astlist && null != ssaStack); if (node is BinaryExpressionNode) { BinaryExpressionNode astBNode = node as BinaryExpressionNode; BinaryExpressionNode bnode = new BinaryExpressionNode(); if (ProtoCore.DSASM.Operator.assign == astBNode.Optr) { bnode.Optr = ProtoCore.DSASM.Operator.assign; bnode.LeftNode = astBNode.LeftNode; DFSEmitSSA_AST(astBNode.RightNode, ssaStack, ref astlist); AssociativeNode assocNode = ssaStack.Pop(); if (assocNode is BinaryExpressionNode) { bnode.RightNode = (assocNode as BinaryExpressionNode).LeftNode; } else { bnode.RightNode = assocNode; } bnode.isSSAAssignment = false; } else { BinaryExpressionNode tnode = new BinaryExpressionNode(); tnode.Optr = astBNode.Optr; DFSEmitSSA_AST(astBNode.LeftNode, ssaStack, ref astlist); DFSEmitSSA_AST(astBNode.RightNode, ssaStack, ref astlist); AssociativeNode lastnode = ssaStack.Pop(); AssociativeNode prevnode = ssaStack.Pop(); tnode.LeftNode = prevnode is BinaryExpressionNode ? (prevnode as BinaryExpressionNode).LeftNode : prevnode; tnode.RightNode = lastnode is BinaryExpressionNode ? (lastnode as BinaryExpressionNode).LeftNode : lastnode; bnode.Optr = ProtoCore.DSASM.Operator.assign; // Left node var identNode = nodeBuilder.BuildIdentfier(ProtoCore.Utils.CoreUtils.GetSSATemp(compileStateTracker)); bnode.LeftNode = identNode; // Right node bnode.RightNode = tnode; bnode.isSSAAssignment = true; } astlist.Add(bnode); ssaStack.Push(bnode); } else if (node is ArrayNode) { ArrayNode arrayNode = node as ArrayNode; DFSEmitSSA_AST(arrayNode.Expr, ssaStack, ref astlist); BinaryExpressionNode bnode = new BinaryExpressionNode(); bnode.Optr = ProtoCore.DSASM.Operator.assign; // Left node AssociativeNode tmpIdent = nodeBuilder.BuildIdentfier(ProtoCore.Utils.CoreUtils.GetSSATemp(compileStateTracker)); Validity.Assert(null != tmpIdent); bnode.LeftNode = tmpIdent; // pop off the dimension AssociativeNode dimensionNode = ssaStack.Pop(); ArrayNode currentDimensionNode = null; if (dimensionNode is BinaryExpressionNode) { currentDimensionNode = new ArrayNode((dimensionNode as BinaryExpressionNode).LeftNode, null); } else { currentDimensionNode = new ArrayNode(dimensionNode, null); } // Pop the prev SSA node where the current dimension will apply AssociativeNode nodePrev = ssaStack.Pop(); if (nodePrev is BinaryExpressionNode) { AssociativeNode rhsIdent = nodeBuilder.BuildIdentfier((nodePrev as BinaryExpressionNode).LeftNode.Name); (rhsIdent as IdentifierNode).ArrayDimensions = currentDimensionNode; bnode.RightNode = rhsIdent; astlist.Add(bnode); ssaStack.Push(bnode); if (null != arrayNode.Type) { DFSEmitSSA_AST(arrayNode.Type, ssaStack, ref astlist); } } else if (nodePrev is IdentifierListNode) { IdentifierNode iNode = (nodePrev as IdentifierListNode).RightNode as IdentifierNode; Validity.Assert(null != iNode); iNode.ArrayDimensions = currentDimensionNode; if (null != arrayNode.Type) { DFSEmitSSA_AST(arrayNode.Type, ssaStack, ref astlist); } } else { Validity.Assert(false); } //bnode.RightNode = rhsIdent; //astlist.Add(bnode); //ssaStack.Push(bnode); } else if (node is IdentifierNode) { IdentifierNode ident = node as IdentifierNode; if (null == ident.ArrayDimensions) { BinaryExpressionNode bnode = new BinaryExpressionNode(); bnode.Optr = ProtoCore.DSASM.Operator.assign; // Left node var identNode = nodeBuilder.BuildIdentfier(ProtoCore.Utils.CoreUtils.GetSSATemp(compileStateTracker)); bnode.LeftNode = identNode; // Right node bnode.RightNode = ident; bnode.isSSAAssignment = true; astlist.Add(bnode); ssaStack.Push(bnode); } else { EmitSSAArrayIndex(ident, ssaStack, ref astlist); } } else if (node is FunctionCallNode || node is FunctionDotCallNode) { FunctionCallNode fcNode = null; if (node is FunctionCallNode) { fcNode = node as FunctionCallNode; for (int idx = 0; idx < fcNode.FormalArguments.Count; idx++) { AssociativeNode arg = fcNode.FormalArguments[idx]; DFSEmitSSA_AST(arg, ssaStack, ref astlist); AssociativeNode argNode = ssaStack.Pop(); if (argNode is BinaryExpressionNode) { BinaryExpressionNode argBinaryExpr = argNode as BinaryExpressionNode; (argBinaryExpr.LeftNode as IdentifierNode).ReplicationGuides = GetReplicationGuidesFromASTNode(argBinaryExpr.RightNode); fcNode.FormalArguments[idx] = argBinaryExpr.LeftNode; } else { fcNode.FormalArguments[idx] = argNode; } } } BinaryExpressionNode bnode = new BinaryExpressionNode(); bnode.Optr = ProtoCore.DSASM.Operator.assign; // Left node var identNode = nodeBuilder.BuildIdentfier(ProtoCore.Utils.CoreUtils.GetSSATemp(compileStateTracker)); bnode.LeftNode = identNode; // Store the replication guide from the function call to the temp (identNode as IdentifierNode).ReplicationGuides = GetReplicationGuidesFromASTNode(node); //Right node bnode.RightNode = node; bnode.isSSAAssignment = true; astlist.Add(bnode); ssaStack.Push(bnode); } else if (node is IdentifierListNode) { SSAIdentList(node, ref ssaStack, ref astlist); AssociativeNode lastNode = null; Validity.Assert(astlist.Count > 0); // Get the last identifierlist node and set its flag // This is required to reset the pointerlist for every identifierlist traversed // i.e. // a = p.x // reset the flag after traversing p.x // // b = p.x + g.y // reset the flag after traversing p.x and p.y // int lastIndex = astlist.Count - 1; for (int n = lastIndex; n >= 0 ; --n) { lastNode = astlist[n]; Validity.Assert(lastNode is BinaryExpressionNode); BinaryExpressionNode bnode = lastNode as BinaryExpressionNode; Validity.Assert(bnode.Optr == Operator.assign); if (bnode.RightNode is IdentifierListNode) { IdentifierListNode identList = bnode.RightNode as IdentifierListNode; identList.isLastSSAIdentListFactor = true; break; } } // // Backtrack and convert all identlist nodes to dot calls // This can potentially be optimized by performing the dotcall transform in SSAIdentList // /////////////////////////// int x = 0; for (int n = lastIndex; n >= 0; --n) { lastNode = astlist[n]; BinaryExpressionNode bnode = lastNode as BinaryExpressionNode; Validity.Assert(bnode.Optr == Operator.assign); if (bnode.RightNode is IdentifierListNode) { IdentifierListNode identList = bnode.RightNode as IdentifierListNode; if (identList.RightNode is IdentifierNode) { IdentifierNode identNode = identList.RightNode as IdentifierNode; ProtoCore.AST.AssociativeAST.FunctionCallNode rcall = new ProtoCore.AST.AssociativeAST.FunctionCallNode(); rcall.Function = new IdentifierNode(identNode); rcall.Function.Name = ProtoCore.DSASM.Constants.kGetterPrefix + rcall.Function.Name; FunctionDotCallNode dotCall = ProtoCore.Utils.CoreUtils.GenerateCallDotNode(identList.LeftNode, rcall, compileStateTracker); dotCall.isLastSSAIdentListFactor = identList.isLastSSAIdentListFactor; bnode.RightNode = dotCall; } else if (identList.RightNode is FunctionCallNode) { FunctionCallNode fCallNode = identList.RightNode as FunctionCallNode; FunctionDotCallNode dotCall = ProtoCore.Utils.CoreUtils.GenerateCallDotNode(identList.LeftNode, fCallNode, compileStateTracker); dotCall.isLastSSAIdentListFactor = identList.isLastSSAIdentListFactor; bnode.RightNode = dotCall; } else { Validity.Assert(false); } } if (bnode.isSSAFirstAssignment) { break; } } /////////////////////////// } else if (node is ExprListNode) { ExprListNode exprList = node as ExprListNode; for (int n = 0; n < exprList.list.Count; n++) { DFSEmitSSA_AST(exprList.list[n], ssaStack, ref astlist); AssociativeNode argNode = ssaStack.Pop(); exprList.list[n] = argNode is BinaryExpressionNode ? (argNode as BinaryExpressionNode).LeftNode : argNode; } BinaryExpressionNode bnode = new BinaryExpressionNode(); bnode.Optr = ProtoCore.DSASM.Operator.assign; // Left node var identNode = nodeBuilder.BuildIdentfier(ProtoCore.Utils.CoreUtils.GetSSATemp(compileStateTracker)); bnode.LeftNode = identNode; //Right node bnode.RightNode = exprList; bnode.isSSAAssignment = true; astlist.Add(bnode); ssaStack.Push(bnode); } else if (node is InlineConditionalNode) { InlineConditionalNode ilnode = node as InlineConditionalNode; DFSEmitSSA_AST(ilnode.ConditionExpression, ssaStack, ref astlist); AssociativeNode cexpr = ssaStack.Pop(); ilnode.ConditionExpression = cexpr is BinaryExpressionNode ? (cexpr as BinaryExpressionNode).LeftNode : cexpr; DFSEmitSSA_AST(ilnode.TrueExpression, ssaStack, ref astlist); AssociativeNode trueExpr = ssaStack.Pop(); ilnode.TrueExpression = trueExpr is BinaryExpressionNode ? (trueExpr as BinaryExpressionNode).LeftNode : trueExpr; DFSEmitSSA_AST(ilnode.FalseExpression, ssaStack, ref astlist); AssociativeNode falseExpr = ssaStack.Pop(); ilnode.FalseExpression = falseExpr is BinaryExpressionNode ? (falseExpr as BinaryExpressionNode).LeftNode : falseExpr; BinaryExpressionNode bnode = new BinaryExpressionNode(); bnode.Optr = ProtoCore.DSASM.Operator.assign; // Left node var identNode = nodeBuilder.BuildIdentfier(ProtoCore.Utils.CoreUtils.GetSSATemp(compileStateTracker)); bnode.LeftNode = identNode; //Right node bnode.RightNode = ilnode; bnode.isSSAAssignment = true; astlist.Add(bnode); ssaStack.Push(bnode); } else if (node is RangeExprNode) { RangeExprNode rangeNode = node as RangeExprNode; DFSEmitSSA_AST(rangeNode.FromNode, ssaStack, ref astlist); AssociativeNode fromExpr = ssaStack.Pop(); rangeNode.FromNode = fromExpr is BinaryExpressionNode ? (fromExpr as BinaryExpressionNode).LeftNode : fromExpr; DFSEmitSSA_AST(rangeNode.ToNode, ssaStack, ref astlist); AssociativeNode toExpr = ssaStack.Pop(); rangeNode.ToNode = toExpr is BinaryExpressionNode ? (toExpr as BinaryExpressionNode).LeftNode : toExpr; if (rangeNode.StepNode != null) { DFSEmitSSA_AST(rangeNode.StepNode, ssaStack, ref astlist); AssociativeNode stepExpr = ssaStack.Pop(); rangeNode.StepNode = stepExpr is BinaryExpressionNode ? (stepExpr as BinaryExpressionNode).LeftNode : stepExpr; } BinaryExpressionNode bnode = new BinaryExpressionNode(); bnode.Optr = ProtoCore.DSASM.Operator.assign; // Left node var identNode = nodeBuilder.BuildIdentfier(ProtoCore.Utils.CoreUtils.GetSSATemp(compileStateTracker)); bnode.LeftNode = identNode; //Right node bnode.RightNode = rangeNode; bnode.isSSAAssignment = true; astlist.Add(bnode); ssaStack.Push(bnode); } else { ssaStack.Push(node); } }
void Associative_NameReference(out ProtoCore.AST.AssociativeAST.AssociativeNode node) { ProtoCore.AST.AssociativeAST.ArrayNameNode nameNode = null; ProtoCore.AST.AssociativeAST.GroupExpressionNode groupExprNode = null; if (la.kind == 12) { Get(); Associative_Expression(out node); if (node is ProtoCore.AST.AssociativeAST.ArrayNameNode) { nameNode = node as ProtoCore.AST.AssociativeAST.ArrayNameNode; } else { groupExprNode = new ProtoCore.AST.AssociativeAST.GroupExpressionNode(); groupExprNode.Expression = node; nameNode = groupExprNode; } Expect(13); } else if (IsFunctionCall()) { if (isLeft) { errors.SemErr(la.line, la.col, Resources.FunctionCallCannotBeAtLeftSide); } Associative_FunctionCall(out node); nameNode = node as ProtoCore.AST.AssociativeAST.ArrayNameNode; } else if (la.kind == 1) { Associative_Ident(out node); nameNode = node as ProtoCore.AST.AssociativeAST.ArrayNameNode; } else if (la.kind == 45) { Associative_ArrayExprList(out node); nameNode = node as ProtoCore.AST.AssociativeAST.ArrayNameNode; } else SynErr(99); if (la.kind == 10) { ProtoCore.AST.AssociativeAST.ArrayNode array = new ProtoCore.AST.AssociativeAST.ArrayNode(); Get(); if (StartOf(4)) { bool tmpIsLeft = isLeft; isLeft = false; Associative_Expression(out node); isLeft = tmpIsLeft; array.Expr = node; array.Type = nameNode.ArrayDimensions; NodeUtils.SetNodeLocation(array, t); nameNode.ArrayDimensions = array; } Expect(11); while (la.kind == 10) { Get(); if (StartOf(4)) { bool tmpIsLeft = isLeft; isLeft = false; Associative_Expression(out node); isLeft = tmpIsLeft; ProtoCore.AST.AssociativeAST.ArrayNode array2 = new ProtoCore.AST.AssociativeAST.ArrayNode(); array2.Expr = node; array2.Type = null; NodeUtils.SetNodeLocation(array2, t); array.Type = array2; array = array2; } Expect(11); } if (groupExprNode != null) { var expr = groupExprNode.Expression; if (expr is ProtoCore.AST.AssociativeAST.IdentifierListNode) { var rightNode = (expr as ProtoCore.AST.AssociativeAST.IdentifierListNode).RightNode; if (rightNode is ProtoCore.AST.AssociativeAST.ArrayNameNode) { var rightMostArrayNameNode = rightNode as ProtoCore.AST.AssociativeAST.ArrayNameNode; if (rightMostArrayNameNode.ArrayDimensions == null) { rightMostArrayNameNode.ArrayDimensions = groupExprNode.ArrayDimensions; } else { rightMostArrayNameNode.ArrayDimensions.Type = groupExprNode.ArrayDimensions; } groupExprNode.ArrayDimensions = null; } } else if (expr is ProtoCore.AST.AssociativeAST.RangeExprNode) { var rangeExprNode = expr as ProtoCore.AST.AssociativeAST.RangeExprNode; if (rangeExprNode.ArrayDimensions == null) { rangeExprNode.ArrayDimensions = groupExprNode.ArrayDimensions; } else { rangeExprNode.ArrayDimensions.Type = groupExprNode.ArrayDimensions; } groupExprNode.ArrayDimensions = null; } else if (expr is ProtoCore.AST.AssociativeAST.ExprListNode) { var exprListNode = expr as ProtoCore.AST.AssociativeAST.ExprListNode; if (exprListNode.ArrayDimensions == null) { exprListNode.ArrayDimensions = groupExprNode.ArrayDimensions; } else { exprListNode.ArrayDimensions.Type = groupExprNode.ArrayDimensions; } groupExprNode.ArrayDimensions = null; } else if (expr is ProtoCore.AST.AssociativeAST.FunctionDotCallNode) { var dotCall = (expr as ProtoCore.AST.AssociativeAST.FunctionDotCallNode).DotCall; var arrayExpr = (dotCall.FormalArguments[2] as ProtoCore.AST.AssociativeAST.ExprListNode); var dimCount = (dotCall.FormalArguments[3] as ProtoCore.AST.AssociativeAST.IntNode); var dims = dimCount.Value; var newdims = dims; if (arrayExpr != null) { var newarray = groupExprNode.ArrayDimensions; while (newarray != null) { arrayExpr.Exprs.Add(newarray.Expr); newdims++; newarray = (newarray.Type as ProtoCore.AST.AssociativeAST.ArrayNode); } (dotCall.FormalArguments[3] as ProtoCore.AST.AssociativeAST.IntNode).Value = newdims; } groupExprNode.ArrayDimensions = null; } } } if (la.kind == 8 || la.kind == 9) { AssociativeNode levelNode = null; bool isDominant = false; if (la.kind == 8) { Get(); Associative_Number(out levelNode); } else { Get(); Associative_Number(out levelNode); isDominant = true; } IntNode listAtLevel = levelNode as IntNode; if (listAtLevel != null) { var atLevel = new AtLevelNode { Level = listAtLevel.Value, IsDominant = isDominant }; nameNode.AtLevel = atLevel; } } if (IsReplicationGuide()) { var guides = new List<AssociativeNode>(); Expect(17); string repguide = String.Empty; bool isLongest = false; ReplicationGuideNode repGuideNode = null; if (IsPostfixedReplicationGuide()) { Expect(7); isLongest = true; } else if (la.kind == 2) { Get(); isLongest = false; } else SynErr(100); repguide = t.val; if (isLongest) { repguide = repguide.Remove(repguide.Length - 1); } var numNode = new IdentifierNode() { Value = repguide }; repGuideNode = new ReplicationGuideNode(); repGuideNode.RepGuide = numNode; repGuideNode.IsLongest = isLongest; NodeUtils.SetNodeLocation(numNode, t); Expect(18); guides.Add(repGuideNode); while (la.kind == 17) { Get(); if (IsPostfixedReplicationGuide()) { Expect(7); isLongest = true; } else if (la.kind == 2) { Get(); isLongest = false; } else SynErr(101); repguide = t.val; if (isLongest) { repguide = repguide.Remove(repguide.Length - 1); } numNode = AstFactory.BuildIdentifier(repguide); repGuideNode = new ReplicationGuideNode(); repGuideNode.RepGuide = numNode; repGuideNode.IsLongest = isLongest; NodeUtils.SetNodeLocation(numNode, t); Expect(18); guides.Add(repGuideNode); } nameNode.ReplicationGuides = guides; if (groupExprNode != null) { var expr = groupExprNode.Expression; if (expr is IdentifierListNode) { var rightNode = (expr as IdentifierListNode).RightNode; if (rightNode is ArrayNameNode) { var rightMostArrayNameNode = rightNode as ArrayNameNode; if (rightMostArrayNameNode.ReplicationGuides == null) { rightMostArrayNameNode.ReplicationGuides = guides; } else { rightMostArrayNameNode.ReplicationGuides.InsertRange(0, guides); } groupExprNode.ReplicationGuides = null; } } else if (expr is FunctionDotCallNode) { var functionCall = (expr as FunctionDotCallNode).FunctionCall; var function = (functionCall.Function as ArrayNameNode); if (function.ReplicationGuides == null) { function.ReplicationGuides = guides; } else { function.ReplicationGuides.InsertRange(0, guides); } groupExprNode.ReplicationGuides = null; } } } if (groupExprNode != null && groupExprNode.ArrayDimensions == null && (groupExprNode.ReplicationGuides == null || groupExprNode.ReplicationGuides.Count == 0)) { node = groupExprNode.Expression; } else { node = nameNode; } }
void Associative_NameReference(out ProtoCore.AST.AssociativeAST.AssociativeNode node) { ProtoCore.AST.AssociativeAST.ArrayNameNode nameNode = null; ProtoCore.AST.AssociativeAST.GroupExpressionNode groupExprNode = null; if (la.kind == 9) { Get(); Associative_Expression(out node); if (node is ProtoCore.AST.AssociativeAST.FunctionCallNode || node is ProtoCore.AST.AssociativeAST.IdentifierNode) { nameNode = node as ProtoCore.AST.AssociativeAST.ArrayNameNode; } else { groupExprNode = new ProtoCore.AST.AssociativeAST.GroupExpressionNode(); groupExprNode.Expression = node; nameNode = groupExprNode; } Expect(10); } else if (IsFunctionCall()) { if (isLeft) { errors.SemErr(la.line, la.col, "function call is not allowed at the left hand side of an assignment"); } Associative_FunctionCall(out node); nameNode = node as ProtoCore.AST.AssociativeAST.ArrayNameNode; } else if (la.kind == 1) { Associative_Ident(out node); nameNode = node as ProtoCore.AST.AssociativeAST.ArrayNameNode; } else if (la.kind == 44) { Associative_ArrayExprList(out node); nameNode = node as ProtoCore.AST.AssociativeAST.ArrayNameNode; } else SynErr(102); if (la.kind == 7) { ProtoCore.AST.AssociativeAST.ArrayNode array = new ProtoCore.AST.AssociativeAST.ArrayNode(); Get(); if (StartOf(4)) { bool tmpIsLeft = isLeft; isLeft = false; Associative_Expression(out node); isLeft = tmpIsLeft; array.Expr = node; array.Type = null; NodeUtils.SetNodeLocation(array, t); nameNode.ArrayDimensions = array; } Expect(8); while (la.kind == 7) { Get(); if (StartOf(4)) { bool tmpIsLeft = isLeft; isLeft = false; Associative_Expression(out node); isLeft = tmpIsLeft; ProtoCore.AST.AssociativeAST.ArrayNode array2 = new ProtoCore.AST.AssociativeAST.ArrayNode(); array2.Expr = node; array2.Type = null; NodeUtils.SetNodeLocation(array2, t); array.Type = array2; array = array2; } Expect(8); } if (groupExprNode != null) { var expr = groupExprNode.Expression; if (expr is ProtoCore.AST.AssociativeAST.IdentifierListNode) { var rightNode = (expr as ProtoCore.AST.AssociativeAST.IdentifierListNode).RightNode; if (rightNode is ProtoCore.AST.AssociativeAST.ArrayNameNode) { var rightMostArrayNameNode = rightNode as ProtoCore.AST.AssociativeAST.ArrayNameNode; if (rightMostArrayNameNode.ArrayDimensions == null) { rightMostArrayNameNode.ArrayDimensions = groupExprNode.ArrayDimensions; } else { rightMostArrayNameNode.ArrayDimensions.Type = groupExprNode.ArrayDimensions; } groupExprNode.ArrayDimensions = null; } } else if (expr is ProtoCore.AST.AssociativeAST.RangeExprNode) { var rangeExprNode = expr as ProtoCore.AST.AssociativeAST.RangeExprNode; if (rangeExprNode.ArrayDimensions == null) { rangeExprNode.ArrayDimensions = groupExprNode.ArrayDimensions; } else { rangeExprNode.ArrayDimensions.Type = groupExprNode.ArrayDimensions; } groupExprNode.ArrayDimensions = null; } else if (expr is ProtoCore.AST.AssociativeAST.ExprListNode) { var exprListNode = expr as ProtoCore.AST.AssociativeAST.ExprListNode; if (exprListNode.ArrayDimensions == null) { exprListNode.ArrayDimensions = groupExprNode.ArrayDimensions; } else { exprListNode.ArrayDimensions.Type = groupExprNode.ArrayDimensions; } groupExprNode.ArrayDimensions = null; } else if (expr is ProtoCore.AST.AssociativeAST.FunctionDotCallNode) { var dotCall = (expr as ProtoCore.AST.AssociativeAST.FunctionDotCallNode).DotCall; var arrayExpr = (dotCall.FormalArguments[2] as ProtoCore.AST.AssociativeAST.ExprListNode); var dimCount = (dotCall.FormalArguments[3] as ProtoCore.AST.AssociativeAST.IntNode); int dims = Int32.Parse(dimCount.value); int newdims = dims; if (arrayExpr != null) { var newarray = groupExprNode.ArrayDimensions; while (newarray != null) { arrayExpr.list.Add(newarray.Expr); newdims++; newarray = (newarray.Type as ProtoCore.AST.AssociativeAST.ArrayNode); } (dotCall.FormalArguments[3] as ProtoCore.AST.AssociativeAST.IntNode).value = newdims.ToString(); } groupExprNode.ArrayDimensions = null; } } } if (IsReplicationGuide()) { var guides = new List<ProtoCore.AST.AssociativeAST.AssociativeNode>(); Expect(14); Expect(2); ProtoCore.AST.AssociativeAST.AssociativeNode numNode = new ProtoCore.AST.AssociativeAST.IdentifierNode() { Value = t.val }; NodeUtils.SetNodeLocation(numNode, t); Expect(15); guides.Add(numNode); while (la.kind == 14) { Get(); Expect(2); numNode = new ProtoCore.AST.AssociativeAST.IdentifierNode() { Value = t.val }; NodeUtils.SetNodeLocation(numNode, t); Expect(15); guides.Add(numNode); } nameNode.ReplicationGuides = guides; if (groupExprNode != null) { var expr = groupExprNode.Expression; if (expr is ProtoCore.AST.AssociativeAST.IdentifierListNode) { var rightNode = (expr as ProtoCore.AST.AssociativeAST.IdentifierListNode).RightNode; if (rightNode is ProtoCore.AST.AssociativeAST.ArrayNameNode) { var rightMostArrayNameNode = rightNode as ProtoCore.AST.AssociativeAST.ArrayNameNode; if (rightMostArrayNameNode.ReplicationGuides == null) { rightMostArrayNameNode.ReplicationGuides = guides; } else { rightMostArrayNameNode.ReplicationGuides.InsertRange(0, guides); } groupExprNode.ReplicationGuides = null; } } else if (expr is ProtoCore.AST.AssociativeAST.FunctionDotCallNode) { var functionCall = (expr as ProtoCore.AST.AssociativeAST.FunctionDotCallNode).FunctionCall; var function = (functionCall.Function as ProtoCore.AST.AssociativeAST.ArrayNameNode); if (function.ReplicationGuides == null) { function.ReplicationGuides = guides; } else { function.ReplicationGuides.InsertRange(0, guides); } groupExprNode.ReplicationGuides = null; } } } if (groupExprNode != null && groupExprNode.ArrayDimensions == null && groupExprNode.ReplicationGuides == null) { node = groupExprNode.Expression; } else { node = nameNode; } }
public ArrayNameNode(ArrayNameNode rhs) : base(rhs) { ArrayDimensions = null; if (null != rhs.ArrayDimensions) { ArrayDimensions = new ArrayNode(rhs.ArrayDimensions); } ReplicationGuides = null; if (null != rhs.ReplicationGuides) { ReplicationGuides = new List<AssociativeNode>(); foreach (AssociativeNode argNode in rhs.ReplicationGuides) { AssociativeNode tempNode = NodeUtils.Clone(argNode); ReplicationGuides.Add(tempNode); } } }
public ArrayNode(ArrayNode rhs) : base(rhs) { Expr = null; Type = null; if (null != rhs) { if (null != rhs.Expr) { Expr = NodeUtils.Clone(rhs.Expr); } if (null != rhs.Type) { Type = NodeUtils.Clone(rhs.Type); } } }
void Associative_NameReference(out ProtoCore.AST.AssociativeAST.AssociativeNode node) { ProtoCore.AST.AssociativeAST.ArrayNameNode nameNode = null; ProtoCore.AST.AssociativeAST.GroupExpressionNode groupExprNode = null; if (la.kind == 10) { Get(); Associative_Expression(out node); if (node is ProtoCore.AST.AssociativeAST.ArrayNameNode) { nameNode = node as ProtoCore.AST.AssociativeAST.ArrayNameNode; } else { groupExprNode = new ProtoCore.AST.AssociativeAST.GroupExpressionNode(); groupExprNode.Expression = node; nameNode = groupExprNode; } Expect(11); } else if (IsFunctionCall()) { if (isLeft) { errors.SemErr(la.line, la.col, "function call is not allowed at the left hand side of an assignment"); } Associative_FunctionCall(out node); nameNode = node as ProtoCore.AST.AssociativeAST.ArrayNameNode; } else if (la.kind == 1) { Associative_Ident(out node); nameNode = node as ProtoCore.AST.AssociativeAST.ArrayNameNode; } else if (la.kind == 47) { Associative_ArrayExprList(out node); nameNode = node as ProtoCore.AST.AssociativeAST.ArrayNameNode; } else SynErr(105); if (la.kind == 8) { ProtoCore.AST.AssociativeAST.ArrayNode array = new ProtoCore.AST.AssociativeAST.ArrayNode(); Get(); if (StartOf(4)) { bool tmpIsLeft = isLeft; isLeft = false; Associative_Expression(out node); isLeft = tmpIsLeft; array.Expr = node; array.Type = nameNode.ArrayDimensions; NodeUtils.SetNodeLocation(array, t); nameNode.ArrayDimensions = array; } Expect(9); while (la.kind == 8) { Get(); if (StartOf(4)) { bool tmpIsLeft = isLeft; isLeft = false; Associative_Expression(out node); isLeft = tmpIsLeft; ProtoCore.AST.AssociativeAST.ArrayNode array2 = new ProtoCore.AST.AssociativeAST.ArrayNode(); array2.Expr = node; array2.Type = null; NodeUtils.SetNodeLocation(array2, t); array.Type = array2; array = array2; } Expect(9); } if (groupExprNode != null) { var expr = groupExprNode.Expression; if (expr is ProtoCore.AST.AssociativeAST.IdentifierListNode) { var rightNode = (expr as ProtoCore.AST.AssociativeAST.IdentifierListNode).RightNode; if (rightNode is ProtoCore.AST.AssociativeAST.ArrayNameNode) { var rightMostArrayNameNode = rightNode as ProtoCore.AST.AssociativeAST.ArrayNameNode; if (rightMostArrayNameNode.ArrayDimensions == null) { rightMostArrayNameNode.ArrayDimensions = groupExprNode.ArrayDimensions; } else { rightMostArrayNameNode.ArrayDimensions.Type = groupExprNode.ArrayDimensions; } groupExprNode.ArrayDimensions = null; } } else if (expr is ProtoCore.AST.AssociativeAST.RangeExprNode) { var rangeExprNode = expr as ProtoCore.AST.AssociativeAST.RangeExprNode; if (rangeExprNode.ArrayDimensions == null) { rangeExprNode.ArrayDimensions = groupExprNode.ArrayDimensions; } else { rangeExprNode.ArrayDimensions.Type = groupExprNode.ArrayDimensions; } groupExprNode.ArrayDimensions = null; } else if (expr is ProtoCore.AST.AssociativeAST.ExprListNode) { var exprListNode = expr as ProtoCore.AST.AssociativeAST.ExprListNode; if (exprListNode.ArrayDimensions == null) { exprListNode.ArrayDimensions = groupExprNode.ArrayDimensions; } else { exprListNode.ArrayDimensions.Type = groupExprNode.ArrayDimensions; } groupExprNode.ArrayDimensions = null; } else if (expr is ProtoCore.AST.AssociativeAST.FunctionDotCallNode) { var dotCall = (expr as ProtoCore.AST.AssociativeAST.FunctionDotCallNode).DotCall; var arrayExpr = (dotCall.FormalArguments[2] as ProtoCore.AST.AssociativeAST.ExprListNode); var dimCount = (dotCall.FormalArguments[3] as ProtoCore.AST.AssociativeAST.IntNode); var dims = dimCount.Value; var newdims = dims; if (arrayExpr != null) { var newarray = groupExprNode.ArrayDimensions; while (newarray != null) { arrayExpr.list.Add(newarray.Expr); newdims++; newarray = (newarray.Type as ProtoCore.AST.AssociativeAST.ArrayNode); } (dotCall.FormalArguments[3] as ProtoCore.AST.AssociativeAST.IntNode).Value = newdims; } groupExprNode.ArrayDimensions = null; } } } if (IsReplicationGuide()) { var guides = new List<ProtoCore.AST.AssociativeAST.AssociativeNode>(); Expect(15); string repguide = String.Empty; bool isLongest = false; ProtoCore.AST.AssociativeAST.AssociativeNode numNode = null; ProtoCore.AST.AssociativeAST.ReplicationGuideNode repGuideNode = null; if (IsPostfixedReplicationGuide()) { Expect(7); repguide = t.val; repguide = repguide.Remove(repguide.Length - 1); isLongest = true; numNode = new ProtoCore.AST.AssociativeAST.IdentifierNode() { Value = repguide }; repGuideNode = new ProtoCore.AST.AssociativeAST.ReplicationGuideNode(); repGuideNode.RepGuide = numNode; repGuideNode.IsLongest = isLongest; NodeUtils.SetNodeLocation(numNode, t); } else if (la.kind == 2) { Get(); repguide = t.val; isLongest = false; numNode = new ProtoCore.AST.AssociativeAST.IdentifierNode() { Value = repguide }; repGuideNode = new ProtoCore.AST.AssociativeAST.ReplicationGuideNode(); repGuideNode.RepGuide = numNode; repGuideNode.IsLongest = isLongest; NodeUtils.SetNodeLocation(numNode, t); } else SynErr(106); Expect(16); guides.Add(repGuideNode); while (la.kind == 15) { Get(); if (IsPostfixedReplicationGuide()) { Expect(7); repguide = t.val; repguide = repguide.Remove(repguide.Length - 1); isLongest = true; numNode = new ProtoCore.AST.AssociativeAST.IdentifierNode() { Value = repguide }; repGuideNode = new ProtoCore.AST.AssociativeAST.ReplicationGuideNode(); repGuideNode.RepGuide = numNode; repGuideNode.IsLongest = isLongest; NodeUtils.SetNodeLocation(numNode, t); } else if (la.kind == 2) { Get(); repguide = t.val; isLongest = false; numNode = new ProtoCore.AST.AssociativeAST.IdentifierNode() { Value = repguide }; repGuideNode = new ProtoCore.AST.AssociativeAST.ReplicationGuideNode(); repGuideNode.RepGuide = numNode; repGuideNode.IsLongest = isLongest; NodeUtils.SetNodeLocation(numNode, t); } else SynErr(107); Expect(16); guides.Add(repGuideNode); } nameNode.ReplicationGuides = guides; if (groupExprNode != null) { var expr = groupExprNode.Expression; if (expr is ProtoCore.AST.AssociativeAST.IdentifierListNode) { var rightNode = (expr as ProtoCore.AST.AssociativeAST.IdentifierListNode).RightNode; if (rightNode is ProtoCore.AST.AssociativeAST.ArrayNameNode) { var rightMostArrayNameNode = rightNode as ProtoCore.AST.AssociativeAST.ArrayNameNode; if (rightMostArrayNameNode.ReplicationGuides == null) { rightMostArrayNameNode.ReplicationGuides = guides; } else { rightMostArrayNameNode.ReplicationGuides.InsertRange(0, guides); } groupExprNode.ReplicationGuides = null; } } else if (expr is ProtoCore.AST.AssociativeAST.FunctionDotCallNode) { var functionCall = (expr as ProtoCore.AST.AssociativeAST.FunctionDotCallNode).FunctionCall; var function = (functionCall.Function as ProtoCore.AST.AssociativeAST.ArrayNameNode); if (function.ReplicationGuides == null) { function.ReplicationGuides = guides; } else { function.ReplicationGuides.InsertRange(0, guides); } groupExprNode.ReplicationGuides = null; } } } if (groupExprNode != null && groupExprNode.ArrayDimensions == null && (groupExprNode.ReplicationGuides == null || groupExprNode.ReplicationGuides.Count == 0)) { node = groupExprNode.Expression; } else { node = nameNode; } }