private void EmitLHSIdentifierListForBinaryExpr(AssociativeNode bnode, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone, bool isTempExpression = false) { BinaryExpressionNode binaryExpr = bnode as BinaryExpressionNode; if (binaryExpr == null || !(binaryExpr.LeftNode is IdentifierListNode)) { return; } if (ProtoCore.DSASM.Constants.kInvalidIndex == graphNode.updateBlock.startpc) { graphNode.updateBlock.startpc = pc; } // This is a setter, so disable dependents graphNode.allowDependents = false; IdentifierListNode theLeftNode = binaryExpr.LeftNode as IdentifierListNode; bool isThisPtr = null != theLeftNode.LeftNode.Name && theLeftNode.LeftNode.Name.Equals(ProtoCore.DSDefinitions.Keyword.This); if (isThisPtr) { graphNode.allowDependents = true; } ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = AutoGenerateUpdateReference(binaryExpr.LeftNode, graphNode); ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeArgRef = __To__Deprecate__AutoGenerateUpdateArgumentReference(binaryExpr.LeftNode, graphNode); ProtoCore.AST.Node lnode = binaryExpr.LeftNode; NodeUtils.CopyNodeLocation(lnode, binaryExpr); ProtoCore.AST.Node rnode = binaryExpr.RightNode; bool isCollapsed = false; EmitGetterSetterForIdentList(lnode, ref inferedType, graphNode, subPass, out isCollapsed, rnode); graphNode.allowDependents = true; // Dependency if (!isTempExpression) { // Dependency graph top level symbol graphNode.updateNodeRefList.Add(leftNodeRef); graphNode.updateNodeRefList[0].nodeList[0].dimensionNodeList = graphNode.dimensionNodeList; // @keyu: foo.id = 42; will generate same leftNodeRef and leftNodeArgRef if (!isThisPtr && !leftNodeRef.Equals(leftNodeArgRef)) { graphNode.updateNodeRefList.Add(leftNodeArgRef); } // // If the lhs of the expression is an identifier list, it could have been modified. // It must then be a dependent of its own graphnode // // class C // { // x : int; // constructor C(i:int) // { // x = i; // } // } // // i = 10; // a = C.C(i); // a.x = 15; -> re-execute this line ... as 'a' was redefined and its members now changed // val = a.x; // i = 7; // // // If inside a member function, and the lhs is a property, make sure it is not just: // x = y (this.x = y) // if (core.Options.LHSGraphNodeUpdate) { if (!isThisPtr || graphNode.updateNodeRefList[0].nodeList.Count > 1) { ProtoCore.AssociativeGraph.GraphNode dependentNode = new ProtoCore.AssociativeGraph.GraphNode(); dependentNode.isLHSNode = true; dependentNode.updateNodeRefList.Add(graphNode.updateNodeRefList[0]); graphNode.dependentList.Add(dependentNode); } } ProtoCore.DSASM.SymbolNode firstSymbol = leftNodeRef.nodeList[0].symbol; if (null != firstSymbol) { EmitDependency(binaryExpr.ExpressionUID, binaryExpr.modBlkUID, false); } if (core.Options.GenerateSSA) { if (!graphNode.IsSSANode() && !ProtoCore.AssociativeEngine.Utils.IsTempVarLHS(graphNode)) { // This is the last expression in the SSA'd expression // Backtrack and assign the this last final assignment graphnode to its associated SSA graphnodes for (int n = codeBlock.instrStream.dependencyGraph.GraphList.Count - 1; n >= 0; --n) { GraphNode currentNode = codeBlock.instrStream.dependencyGraph.GraphList[n]; bool isWithinSameScope = currentNode.classIndex == graphNode.classIndex && currentNode.procIndex == graphNode.procIndex; bool isWithinSameExpressionID = currentNode.exprUID == graphNode.exprUID; if (isWithinSameScope && isWithinSameExpressionID) { graphNode.IsLastNodeInSSA = true; codeBlock.instrStream.dependencyGraph.GraphList[n].lastGraphNode = graphNode; } } } } // Assign the end pc to this graph node's update block // Dependency graph construction is complete for this expression graphNode.updateBlock.endpc = pc - 1; PushGraphNode(graphNode); functionCallStack.Clear(); } }
private void EmitLHSIdentifierListForBinaryExpr(AssociativeNode bnode, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.CompilerDefinitions.SubCompilePass subPass = ProtoCore.CompilerDefinitions.SubCompilePass.None, bool isTempExpression = false) { BinaryExpressionNode binaryExpr = bnode as BinaryExpressionNode; if (binaryExpr == null || !(binaryExpr.LeftNode is IdentifierListNode)) { return; } if (ProtoCore.DSASM.Constants.kInvalidIndex == graphNode.updateBlock.startpc) { graphNode.updateBlock.startpc = pc; } // This is a setter, so disable dependents graphNode.allowDependents = false; IdentifierListNode theLeftNode = binaryExpr.LeftNode as IdentifierListNode; bool isThisPtr = null != theLeftNode.LeftNode.Name && theLeftNode.LeftNode.Name.Equals(ProtoCore.DSDefinitions.Keyword.This); if (isThisPtr) { graphNode.allowDependents = true; } ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = AutoGenerateUpdateReference(binaryExpr.LeftNode, graphNode); ProtoCore.AST.Node lnode = binaryExpr.LeftNode; NodeUtils.CopyNodeLocation(lnode, binaryExpr); ProtoCore.AST.Node rnode = binaryExpr.RightNode; bool isCollapsed = false; EmitGetterSetterForIdentList(lnode, ref inferedType, graphNode, subPass, out isCollapsed, rnode); graphNode.allowDependents = true; // Dependency if (!isTempExpression) { // Dependency graph top level symbol graphNode.updateNodeRefList.Add(leftNodeRef); graphNode.updateNodeRefList[0].nodeList[0].dimensionNodeList = graphNode.dimensionNodeList; ProtoCore.DSASM.SymbolNode firstSymbol = leftNodeRef.nodeList[0].symbol; if (null != firstSymbol) { EmitDependency(binaryExpr.ExpressionUID, false); } if (core.Options.GenerateSSA) { if (!graphNode.IsSSANode() && !ProtoCore.AssociativeEngine.Utils.IsTempVarLHS(graphNode)) { // This is the last expression in the SSA'd expression // Backtrack and assign the this last final assignment graphnode to its associated SSA graphnodes for (int n = codeBlock.instrStream.dependencyGraph.GraphList.Count - 1; n >= 0; --n) { GraphNode currentNode = codeBlock.instrStream.dependencyGraph.GraphList[n]; bool isWithinSameScope = currentNode.classIndex == graphNode.classIndex && currentNode.procIndex == graphNode.procIndex; bool isWithinSameExpressionID = currentNode.exprUID == graphNode.exprUID; if (isWithinSameScope && isWithinSameExpressionID) { graphNode.IsLastNodeInSSA = true; codeBlock.instrStream.dependencyGraph.GraphList[n].lastGraphNode = graphNode; } } } } // Assign the end pc to this graph node's update block // Dependency graph construction is complete for this expression graphNode.updateBlock.endpc = pc - 1; PushGraphNode(graphNode); functionCallStack.Clear(); } }