public bool IsEqual(UpdateNodeRef rhs) { if (nodeList.Count != rhs.nodeList.Count) { return(false); } for (int n = 0; n < nodeList.Count; ++n) { if (nodeList[n].dimensionNodeList.Count != rhs.nodeList[n].dimensionNodeList.Count) { return(false); } else if (nodeList[n].dimensionNodeList.Count != 0) { for (int m = 0; m < nodeList[n].dimensionNodeList.Count; m++) { if (nodeList[n].dimensionNodeList[m].symbol.name != rhs.nodeList[n].dimensionNodeList[m].symbol.name) { return(false); } } } if (!nodeList[n].IsEqual(rhs.nodeList[n])) { return(false); } } return(true); }
public void PushUpdateNodeRef(UpdateNodeRef nodeRef) { Validity.Assert(null != nodeList); foreach (UpdateNode node in nodeRef.nodeList) { nodeList.Add(node); } }
public UpdateNodeRef(UpdateNodeRef rhs) { if (null != rhs && null != rhs.nodeList) { nodeList = new List <UpdateNode>(rhs.nodeList); } else { nodeList = new List <UpdateNode>(); } }
public UpdateNodeRef(UpdateNodeRef rhs) { nodeList = new List <UpdateNode>(); if (null != rhs && null != rhs.nodeList) { foreach (UpdateNode node in rhs.nodeList) { PushUpdateNode(node); } } }
public UpdateNodeRef GetUntilFirstProc() { UpdateNodeRef newRef = new UpdateNodeRef(); foreach (UpdateNode node in nodeList) { if (node.nodeType != UpdateNodeType.kMethod) { newRef.nodeList.Add(node); } } return(newRef); }
public void PushSymbolReference(SymbolNode symbol, UpdateNodeType type = UpdateNodeType.kSymbol) { Validity.Assert(null != symbol); UpdateNode updateNode = new UpdateNode(); updateNode.symbol = symbol; updateNode.nodeType = type; UpdateNodeRef nodeRef = new UpdateNodeRef(); nodeRef.PushUpdateNode(updateNode); updateNodeRefList.Add(nodeRef); }
public void PushProcReference(ProtoCore.DSASM.ProcedureNode proc) { Debug.Assert(null != proc); Debug.Assert(null != updateNodeRefList); UpdateNode updateNode = new UpdateNode(); updateNode.procNode = proc; updateNode.nodeType = UpdateNodeType.kMethod; UpdateNodeRef nodeRef = new UpdateNodeRef(); nodeRef.PushUpdateNode(updateNode); updateNodeRefList.Add(nodeRef); }
public void PushSymbolReference(ProtoCore.DSASM.SymbolNode symbol, ProtoCore.AssociativeGraph.UpdateNodeType type = UpdateNodeType.kSymbol) { Debug.Assert(null != symbol); Debug.Assert(null != updateNodeRefList); UpdateNode updateNode = new UpdateNode(); updateNode.symbol = symbol; updateNode.nodeType = type; UpdateNodeRef nodeRef = new UpdateNodeRef(); nodeRef.PushUpdateNode(updateNode); updateNodeRefList.Add(nodeRef); }
public void PushSymbolReference(SymbolNode symbol) { Validity.Assert(null != symbol); UpdateNode updateNode = new UpdateNode(); updateNode.symbol = symbol; updateNode.nodeType = UpdateNodeType.kSymbol; UpdateNodeRef nodeRef = new UpdateNodeRef(); nodeRef.block = symbol.runtimeTableIndex; nodeRef.PushUpdateNode(updateNode); updateNodeRefList.Add(nodeRef); }
public void PushSymbolReference(ProtoCore.DSASM.SymbolNode symbol) { Debug.Assert(null != symbol); Debug.Assert(null != updateNodeRefList); UpdateNode updateNode = new UpdateNode(); updateNode.symbol = symbol; updateNode.nodeType = UpdateNodeType.kSymbol; UpdateNodeRef nodeRef = new UpdateNodeRef(); nodeRef.block = symbol.runtimeTableIndex; nodeRef.PushUpdateNode(updateNode); updateNodeRefList.Add(nodeRef); }
public bool IsUpdateableBy(UpdateNodeRef modifiedRef) { // Function to check if the current graphnode can be modified by the modified reference bool isUpdateable = false; if (modifiedRef.nodeList.Count < updateNodeRefList[0].nodeList.Count) { isUpdateable = true; for (int n = 0; n < modifiedRef.nodeList.Count; ++n) { UpdateNode updateNode = modifiedRef.nodeList[n]; if (!updateNode.Equals(updateNodeRefList[0].nodeList[n])) { isUpdateable = false; break; } } } return(isUpdateable); }
public void PushSymbolReference(ProtoCore.DSASM.SymbolNode symbol) { Validity.Assert(null != symbol); Validity.Assert(null != updateNodeRefList); UpdateNode updateNode = new UpdateNode(); updateNode.symbol = symbol; updateNode.nodeType = UpdateNodeType.kSymbol; UpdateNodeRef nodeRef = new UpdateNodeRef(); nodeRef.block = symbol.runtimeTableIndex; nodeRef.PushUpdateNode(updateNode); updateNodeRefList.Add(nodeRef); }
public UpdateNodeRef(UpdateNodeRef rhs) { if (null != rhs && null != rhs.nodeList) { nodeList = new List<UpdateNode>(rhs.nodeList); } else { nodeList = new List<UpdateNode>(); } }
public bool DependsOn(UpdateNodeRef modifiedRef, ref GraphNode dependentNode) { bool match = false; foreach (GraphNode depNode in dependentList) { Validity.Assert(1 == depNode.updateNodeRefList.Count); //foreach (UpdateNodeRef depNodeRef in depNode.updateNodeRefList) //{ UpdateNodeRef depNodeRef = depNode.updateNodeRefList[0]; bool bothSymbolsMatch = false; bool bothSymbolsStatic = false; bool inImperativeMatch = false; bool inImperative = false; if (depNodeRef != null) if (depNodeRef.nodeList != null && modifiedRef.nodeList != null && depNodeRef.nodeList.Count > 0 && modifiedRef.nodeList.Count > 0) { if (depNodeRef.nodeList.Count > modifiedRef.nodeList.Count) { for (int m = 0; m < depNodeRef.nodeList.Count; m++) { if (depNodeRef.nodeList[m] != null && modifiedRef.nodeList[0] != null && depNodeRef.nodeList[m].symbol != null && modifiedRef.nodeList[0].symbol != null) { if (modifiedRef.nodeList[0].symbol.forArrayName != null && !modifiedRef.nodeList[0].symbol.forArrayName.Equals("")) { inImperative = true; if (modifiedRef.nodeList[0].symbol.functionIndex == Constants.kInvalidIndex) { inImperative = inImperative && (depNodeRef.nodeList[m].symbol.functionIndex == Constants.kInvalidIndex) && (modifiedRef.nodeList[0].symbol.codeBlockId == depNodeRef.nodeList[m].symbol.codeBlockId); } if (inImperative && modifiedRef.nodeList[0].symbol.functionIndex == depNodeRef.nodeList[m].symbol.functionIndex && (modifiedRef.nodeList[0].symbol.name == depNodeRef.nodeList[m].symbol.name || modifiedRef.nodeList[0].symbol.forArrayName == depNodeRef.nodeList[m].symbol.name)) { inImperativeMatch = true; } } } } } else if (depNodeRef.nodeList.Count == modifiedRef.nodeList.Count) { for (int m = 0; m < depNodeRef.nodeList.Count && m < modifiedRef.nodeList.Count; m++) { if (depNodeRef.nodeList[m] != null && modifiedRef.nodeList[m] != null && depNodeRef.nodeList[m].symbol != null && modifiedRef.nodeList[m].symbol != null) { if (modifiedRef.nodeList[0].symbol.forArrayName != null && !modifiedRef.nodeList[0].symbol.forArrayName.Equals("")) { inImperative = true; if (modifiedRef.nodeList[m].symbol.functionIndex == Constants.kInvalidIndex) { inImperative = inImperative && (depNodeRef.nodeList[m].symbol.functionIndex == Constants.kInvalidIndex) && (modifiedRef.nodeList[m].symbol.codeBlockId == depNodeRef.nodeList[m].symbol.codeBlockId); } if (inImperative && modifiedRef.nodeList[m].symbol.functionIndex == depNodeRef.nodeList[m].symbol.functionIndex && modifiedRef.nodeList[m].symbol.name == depNodeRef.nodeList[m].symbol.name ) { inImperativeMatch = true; } } } } } } if (!inImperativeMatch) { // Does first symbol match if (null != modifiedRef.nodeList[0].symbol && null != depNodeRef.nodeList[0].symbol) { bothSymbolsMatch = modifiedRef.nodeList[0].symbol.Equals(depNodeRef.nodeList[0].symbol); bothSymbolsStatic = modifiedRef.nodeList[0].symbol.memregion == MemoryRegion.kMemStatic && depNodeRef.nodeList[0].symbol.memregion == MemoryRegion.kMemStatic && modifiedRef.nodeList[0].symbol.name == depNodeRef.nodeList[0].symbol.name; // Check further if their array index match in literal values if (bothSymbolsMatch) { // Are the indices the same number bool areIndicesMatching = modifiedRef.nodeList[0].dimensionNodeList.Count >= depNodeRef.nodeList[0].dimensionNodeList.Count; if (areIndicesMatching && depNodeRef.nodeList[0].dimensionNodeList.Count > 0) { for (int n = 0; n < depNodeRef.nodeList[0].dimensionNodeList.Count; ++n) { // Is either a non-literal UpdateNode modDimNode =modifiedRef.nodeList[0].dimensionNodeList[n]; UpdateNode depDimNode = depNodeRef.nodeList[0].dimensionNodeList[n]; if (modDimNode.nodeType != depDimNode.nodeType) { bothSymbolsMatch = false; } else if (modDimNode.nodeType == UpdateNodeType.kLiteral) { bothSymbolsMatch = modDimNode.symbol.name.CompareTo(depDimNode.symbol.name) == 0; } else if (modDimNode.nodeType == UpdateNodeType.kSymbol) { bothSymbolsMatch = modDimNode.symbol.Equals(depDimNode.symbol); } else { bothSymbolsMatch = false; } if (!bothSymbolsMatch) { break; } } } } } if (bothSymbolsMatch || bothSymbolsStatic) { match = true; // If it is static, then all symbols must match if (bothSymbolsStatic) { // The number of symbols in the modifed reference... // ...must match // The number of symbols in the current dependency noderef if (modifiedRef.nodeList.Count == depNodeRef.nodeList.Count) { for (int n = 1; n < modifiedRef.nodeList.Count; ++n) { //Validity.Assert(!modifiedRef.nodeList[n].isMethod); //Validity.Assert(!depNodeRef.nodeList[n].isMethod); if (UpdateNodeType.kMethod == modifiedRef.nodeList[n].nodeType || UpdateNodeType.kMethod == depNodeRef.nodeList[n].nodeType) { match = false; break; } if (modifiedRef.nodeList[n].symbol.index != depNodeRef.nodeList[n].symbol.index) { match = false; break; } } } else { match = false; } } else { if (modifiedRef.nodeList.Count >= depNodeRef.nodeList.Count) { // // The modifed reference is either the same nodelist length or more than the current dependent // a.x.y is being compared to a.x // for (int n = 1; n < modifiedRef.nodeList.Count; ++n) { if (modifiedRef.nodeList.Count != depNodeRef.nodeList.Count) { if (n >= depNodeRef.nodeList.Count) { match = false; break; } } if (UpdateNodeType.kMethod == modifiedRef.nodeList[n].nodeType || UpdateNodeType.kMethod == depNodeRef.nodeList[n].nodeType) { match = false; break; } if (modifiedRef.nodeList[n].symbol.name != depNodeRef.nodeList[n].symbol.name) { match = false; break; } } } else { // // The modifed reference nodelist is less than than the current dependent nodelist // a.x is being compared to a.x.y // for (int n = 1; n < depNodeRef.nodeList.Count; ++n) { if (n >= modifiedRef.nodeList.Count) { break; } if (UpdateNodeType.kMethod == modifiedRef.nodeList[n].nodeType || UpdateNodeType.kMethod == depNodeRef.nodeList[n].nodeType) { match = false; break; } if (modifiedRef.nodeList[n].symbol.name != depNodeRef.nodeList[n].symbol.name) { match = false; break; } } } } } dependentNode = depNode; if (match) { break; } } else { for (int m = 0; m < depNodeRef.nodeList.Count && m < modifiedRef.nodeList.Count; m++) { // Does first symbol match if (null != modifiedRef.nodeList[m].symbol && null != depNodeRef.nodeList[m].symbol) { bothSymbolsMatch = modifiedRef.nodeList[m].symbol.Equals(depNodeRef.nodeList[m].symbol); bothSymbolsStatic = modifiedRef.nodeList[m].symbol.memregion == MemoryRegion.kMemStatic && depNodeRef.nodeList[m].symbol.memregion == MemoryRegion.kMemStatic && modifiedRef.nodeList[m].symbol.name == depNodeRef.nodeList[m].symbol.name; // Check further if their array index match in literal values if (bothSymbolsMatch) { // Are the indices the same number bool areIndicesMatching = modifiedRef.nodeList[m].dimensionNodeList.Count == depNodeRef.nodeList[m].dimensionNodeList.Count; if (areIndicesMatching && modifiedRef.nodeList[m].dimensionNodeList.Count > 0) { for (int n = 0; n < modifiedRef.nodeList[m].dimensionNodeList.Count; ++n) { // Is either a non-literal bool isEitherNonLiteral = modifiedRef.nodeList[m].dimensionNodeList[n].nodeType != UpdateNodeType.kLiteral || depNodeRef.nodeList[m].dimensionNodeList[n].nodeType != UpdateNodeType.kLiteral; if (isEitherNonLiteral) { bothSymbolsMatch = false; break; } // They are both literal, now check for their literal values if (0 != modifiedRef.nodeList[m].dimensionNodeList[n].symbol.name.CompareTo(depNodeRef.nodeList[m].dimensionNodeList[n].symbol.name)) { // They are not the same bothSymbolsMatch = false; break; } } } } } if (bothSymbolsMatch || bothSymbolsStatic || inImperativeMatch) { match = true; // If it is static, then all symbols must match if (bothSymbolsStatic) { // The number of symbols in the modifed reference... // ...must match // The number of symbols in the current dependency noderef if (modifiedRef.nodeList.Count == depNodeRef.nodeList.Count) { for (int n = 1; n < modifiedRef.nodeList.Count; ++n) { //Validity.Assert(!modifiedRef.nodeList[n].isMethod); //Validity.Assert(!depNodeRef.nodeList[n].isMethod); if (UpdateNodeType.kMethod == modifiedRef.nodeList[n].nodeType || UpdateNodeType.kMethod == depNodeRef.nodeList[n].nodeType) { match = false; break; } if (modifiedRef.nodeList[n].symbol.index != depNodeRef.nodeList[n].symbol.index) { match = false; break; } } } else { match = false; } } else { if (modifiedRef.nodeList.Count >= depNodeRef.nodeList.Count) { // // The modifed reference is either the same nodelist length or more than the current dependent // a.x.y is being compared to a.x // for (int n = 1; n < modifiedRef.nodeList.Count; ++n) { if (modifiedRef.nodeList.Count != depNodeRef.nodeList.Count) { if (n >= depNodeRef.nodeList.Count) { match = false; break; } } if (UpdateNodeType.kMethod == modifiedRef.nodeList[n].nodeType || UpdateNodeType.kMethod == depNodeRef.nodeList[n].nodeType) { match = false; break; } if (modifiedRef.nodeList[n].symbol.name != depNodeRef.nodeList[n].symbol.name) { match = false; break; } } } else { // // The modifed reference nodelist is less than than the current dependent nodelist // a.x is being compared to a.x.y // for (int n = 1; n < depNodeRef.nodeList.Count; ++n) { if (n >= modifiedRef.nodeList.Count) { break; } if (UpdateNodeType.kMethod == modifiedRef.nodeList[n].nodeType || UpdateNodeType.kMethod == depNodeRef.nodeList[n].nodeType) { match = false; break; } if (modifiedRef.nodeList[n].symbol.name != depNodeRef.nodeList[n].symbol.name) { match = false; break; } } } } } } dependentNode = depNode; if (match) { break; } } //} } return match; }
protected void BuildRealDependencyForIdentList(AssociativeGraph.GraphNode graphNode) { if (ssaPointerStack.Count == 0) { return; } // Push all dependent pointers ProtoCore.AST.AssociativeAST.IdentifierListNode identList = BuildIdentifierList(ssaPointerStack.Peek()); // Comment Jun: perhaps this can be an assert? if (null != identList) { ProtoCore.Type type = new ProtoCore.Type(); type.UID = globalClassIndex; ProtoCore.AssociativeGraph.UpdateNodeRef nodeRef = new AssociativeGraph.UpdateNodeRef(); int functionIndex = globalProcIndex; DFSGetSymbolList_Simple(identList, ref type, ref functionIndex, nodeRef); if (null != graphNode && nodeRef.nodeList.Count > 0) { ProtoCore.AssociativeGraph.GraphNode dependentNode = new ProtoCore.AssociativeGraph.GraphNode(); dependentNode.updateNodeRefList.Add(nodeRef); graphNode.PushDependent(dependentNode); // If the pointerList is a setter, then it should also be in the lhs of a graphNode // Given: // a.x = 1 // Which was converted to: // tvar = a.set_x(1) // Set a.x as lhs of the graphnode. // This means that statement that depends on a.x can re-execute, such as: // p = a.x; // List<ProtoCore.AST.AssociativeAST.AssociativeNode> topList = ssaPointerStack.Peek(); string propertyName = topList[topList.Count - 1].Name; bool isSetter = propertyName.StartsWith(Constants.kSetterPrefix); if (isSetter) { graphNode.updateNodeRefList.Add(nodeRef); graphNode.IsLHSIdentList = true; AutoGenerateUpdateArgumentReference(nodeRef, graphNode); } } } }
private ProtoCore.AssociativeGraph.UpdateNodeRef AutoGenerateUpdateReference(AssociativeNode node, ProtoCore.AssociativeGraph.GraphNode graphNode) { // Get the lhs symbol list ProtoCore.Type type = new ProtoCore.Type(); type.UID = globalClassIndex; ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef(); DFSGetSymbolList(node, ref type, leftNodeRef); // Auto-generate the updateNodeRefs for this graphnode given the list // stored in the first procedure found in the assignment expression if (functionCallStack.Count > 0) { ProtoCore.DSASM.ProcedureNode firstProc = functionCallStack[0]; if (!firstProc.IsAutoGenerated) { graphNode.firstProc = firstProc; } } return leftNodeRef; }
private ProtoCore.AssociativeGraph.UpdateNodeRef GetUpdatedNodeRef(AssociativeNode node) { if (null == localProcedure) { return null; } // Get the lhs symbol list ProtoCore.Type type = new ProtoCore.Type(); type.UID = globalClassIndex; ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef(); DFSGetSymbolList(node, ref type, leftNodeRef); return leftNodeRef; }
public ProcedureNode TraverseDotFunctionCall( ProtoCore.AST.Node node, ProtoCore.AST.Node parentNode, int lefttype, int depth, GraphNode graphNode, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass, BinaryExpressionNode bnode, ref ProtoCore.Type inferedType) { ProcedureNode procCallNode = null; var dotCallType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, 0); ; bool isConstructor = false; bool isStaticCall = false; bool isUnresolvedDot = false; int classIndex = Constants.kInvalidIndex; string className = string.Empty; var dotCall = new FunctionDotCallNode(node as FunctionDotCallNode); var funcCall = dotCall.DotCall; var procName = dotCall.FunctionCall.Function.Name; var firstArgument = dotCall.DotCall.FormalArguments[0]; if (firstArgument is FunctionDotCallNode) { isUnresolvedDot = true; } else if (firstArgument is IdentifierNode) { // Check if the lhs identifer is a class name className = (firstArgument as IdentifierNode).Name; classIndex = core.ClassTable.IndexOf(className); // Check if the lhs is an variable SymbolNode symbolnode; bool isAccessible; bool hasAllocated = VerifyAllocation(className, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible); bool toResolveMethodOnClass = classIndex != Constants.kInvalidIndex; // If the lhs is an variable which happens to have a same name // as some class, then check the right hand side is a valid // constructor or static function call. if (toResolveMethodOnClass && hasAllocated && isAccessible) { var classes = core.ClassTable.ClassNodes; var classNode = classes[classIndex]; int argCount = dotCall.FunctionCall.FormalArguments.Count; var procNode = classNode.GetFirstConstructorBy(procName, argCount); if (procNode == null) { procNode = classNode.GetFirstStaticFunctionBy(procName, argCount); } if (procNode == null) { toResolveMethodOnClass = false; classIndex = Constants.kInvalidIndex; className = string.Empty; } } if (toResolveMethodOnClass) { dotCall.DotCall.FormalArguments[0] = new IntNode(classIndex); inferedType.UID = dotCallType.UID = classIndex; // Now the left hand side of dot call is a valid class name. // There are three cases for the right hand side: calling a // function, getting a static property or getting a function // pointer. I.e., // // x = Foo.foo(); // // Or // // y = Bar.bar; // static property or funciton pointer // Bar.bar_2 = z; // static property // // For the latters, they are converted to getter/setter. // I.e., // // y = Bar.%get_bar(); // %ret = Bar.%set_bar_2(z); // // We need to check each case. var classes = core.ClassTable.ClassNodes; var classNode = classes[classIndex]; var property = String.Empty; if (CoreUtils.TryGetPropertyName(procName, out property)) { if (procCallNode == null) { procCallNode = classNode.GetFirstStaticFunctionBy(procName); isStaticCall = procCallNode != null; } if (procCallNode == null) { if (subPass != ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone) { return null; } // Try static function firstly procCallNode = classNode.GetFirstStaticFunctionBy(property); if (procCallNode == null) { procCallNode = classNode.GetFirstMemberFunctionBy(property); } if (procCallNode == null) { procCallNode = classNode.GetFirstMemberFunctionBy(procName); } if (procCallNode != null) { EmitFunctionPointer(procCallNode); } else { string message = String.Format(ProtoCore.Properties.Resources.kCallingNonStaticProperty, className, property); buildStatus.LogWarning(WarningID.kCallingNonStaticMethodOnClass, message, core.CurrentDSFileName, dotCall.line, dotCall.col, graphNode); EmitNullNode(new NullNode(), ref inferedType); } return null; } } else { int argCount = dotCall.FunctionCall.FormalArguments.Count; procCallNode = classNode.GetFirstConstructorBy(procName, argCount); isConstructor = procCallNode != null; if (procCallNode == null) { procCallNode = classNode.GetFirstStaticFunctionBy(procName, argCount); isStaticCall = procCallNode != null; } if (!isStaticCall && !isConstructor) { if (subPass == ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone) { string message = String.Format(ProtoCore.Properties.Resources.kStaticMethodNotFound, className, procName); buildStatus.LogWarning(WarningID.kFunctionNotFound, message, core.CurrentDSFileName, dotCall.line, dotCall.col, graphNode); EmitNullNode(new NullNode(), ref inferedType); } return null; } } } else if (hasAllocated && symbolnode.datatype.UID != (int)PrimitiveType.kTypeVar) { inferedType.UID = symbolnode.datatype.UID; if (Constants.kInvalidIndex != inferedType.UID) { procCallNode = GetProcedureFromInstance(symbolnode.datatype.UID, dotCall.FunctionCall); } if (null != procCallNode) { if (procCallNode.IsConstructor) { if (subPass == ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone) { string message = String.Format(ProtoCore.Properties.Resources.KCallingConstructorOnInstance, procName); buildStatus.LogWarning(WarningID.kCallingConstructorOnInstance, message, core.CurrentDSFileName, funcCall.line, funcCall.col, graphNode); EmitNullNode(new NullNode(), ref inferedType); } return null; } isAccessible = procCallNode.AccessModifier == ProtoCore.CompilerDefinitions.AccessModifier.kPublic || (procCallNode.AccessModifier == ProtoCore.CompilerDefinitions.AccessModifier.kPrivate && procCallNode.ClassID == globalClassIndex); if (!isAccessible) { if (subPass == ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone) { string message = String.Format(ProtoCore.Properties.Resources.kMethodIsInaccessible, procName); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kAccessViolation, message, core.CurrentDSFileName, funcCall.line, funcCall.col, graphNode); } } var dynamicRhsIndex = (int)(dotCall.DotCall.FormalArguments[1] as IntNode).Value; var dynFunc = core.DynamicFunctionTable.GetFunctionAtIndex(dynamicRhsIndex); dynFunc.ClassIndex = procCallNode.ClassID; } } else { isUnresolvedDot = true; } } // Its an accceptable method at this point List<ProtoCore.Type> arglist = new List<ProtoCore.Type>(); TraverseDotCallArguments(funcCall, dotCall, procCallNode, arglist, procName, classIndex, className, isStaticCall, isConstructor, graphNode, subPass, bnode); if (subPass == ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier) { return null; } if (!isConstructor && !isStaticCall) { Validity.Assert(dotCall.DotCall.FormalArguments[ProtoCore.DSASM.Constants.kDotArgIndexArrayArgs] is ExprListNode); ExprListNode functionArgs = dotCall.DotCall.FormalArguments[ProtoCore.DSASM.Constants.kDotArgIndexArrayArgs] as ExprListNode; functionArgs.Exprs.Insert(0, dotCall.DotCall.FormalArguments[ProtoCore.DSASM.Constants.kDotArgIndexPtr]); } // From here on, handle the actual procedure call int type = ProtoCore.DSASM.Constants.kInvalidIndex; int refClassIndex = ProtoCore.DSASM.Constants.kInvalidIndex; if (parentNode != null && parentNode is IdentifierListNode) { var leftnode = (parentNode as IdentifierListNode).LeftNode; if (leftnode != null && leftnode is IdentifierNode) { refClassIndex = core.ClassTable.IndexOf(leftnode.Name); } } if (firstArgument is FunctionCallNode || firstArgument is FunctionDotCallNode || firstArgument is ExprListNode) { inferedType.UID = arglist[0].UID; } // If lefttype is a valid class then check if calling a constructor if (procCallNode == null && (int)PrimitiveType.kInvalidType != inferedType.UID && (int)PrimitiveType.kTypeVoid != inferedType.UID && procName != Constants.kFunctionPointerCall) { procCallNode = core.ClassTable.ClassNodes[inferedType.UID].GetFirstMemberFunctionBy(procName); } // Try function pointer firstly if ((procCallNode == null) && (procName != Constants.kFunctionPointerCall)) { bool isAccessibleFp; ProtoCore.DSASM.SymbolNode symbolnode = null; bool isAllocated = VerifyAllocation(procName, globalClassIndex, globalProcIndex, out symbolnode, out isAccessibleFp); if (isAllocated) // not checking the type against function pointer, as the type could be var { procName = Constants.kFunctionPointerCall; // The graph node always depends on this function pointer if (null != graphNode) { PushSymbolAsDependent(symbolnode, graphNode); } } } // Always try global function firstly. Because we dont have syntax // support for calling global function (say, ::foo()), if we try // member function firstly, there is no way to call a global function // For member function, we can use this.foo() to distinguish it from // global function. if ((procCallNode == null) && (procName != Constants.kFunctionPointerCall)) { procCallNode = CoreUtils.GetFunctionBySignature(procName, arglist, codeBlock); if (null != procCallNode) { type = Constants.kGlobalScope; if (core.TypeSystem.IsHigherRank(procCallNode.ReturnType.UID, inferedType.UID)) { inferedType = procCallNode.ReturnType; } } } // Try member functions in global class scope if ((procCallNode == null) && (procName != Constants.kFunctionPointerCall) && (parentNode == null)) { if (globalClassIndex != Constants.kInvalidIndex) { int realType; bool isAccessible; bool isStaticOrConstructor = refClassIndex != Constants.kInvalidIndex; ProcedureNode memProcNode = core.ClassTable.ClassNodes[globalClassIndex].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out realType, isStaticOrConstructor); if (memProcNode != null) { Validity.Assert(realType != Constants.kInvalidIndex); procCallNode = memProcNode; inferedType = procCallNode.ReturnType; type = realType; if (!isAccessible) { string message = String.Format(ProtoCore.Properties.Resources.kMethodIsInaccessible, procName); buildStatus.LogWarning(WarningID.kAccessViolation, message, core.CurrentDSFileName, funcCall.line, funcCall.col, graphNode); inferedType.UID = (int)PrimitiveType.kTypeNull; EmitPushNull(); return procCallNode; } } } } if (isUnresolvedDot || procCallNode == null) { if (dotCallType.UID != (int)PrimitiveType.kTypeVar) { inferedType.UID = dotCallType.UID; } var procNode = CoreUtils.GetFunctionByName(Constants.kDotMethodName, codeBlock); if (CoreUtils.IsGetter(procName)) { EmitFunctionCall(depth, type, arglist, procNode, funcCall, true); } else { EmitFunctionCall(depth, type, arglist, procNode, funcCall, false, bnode); } return procNode; } else { if (procCallNode.IsConstructor && (globalClassIndex != Constants.kInvalidIndex) && (globalProcIndex != Constants.kInvalidIndex) && (globalClassIndex == inferedType.UID)) { ProcedureNode contextProcNode = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Procedures[globalProcIndex]; if (contextProcNode.IsConstructor && string.Equals(contextProcNode.Name, procCallNode.Name) && contextProcNode.RuntimeIndex == procCallNode.RuntimeIndex) { string message = String.Format(ProtoCore.Properties.Resources.kCallingConstructorInConstructor, procName); buildStatus.LogWarning(WarningID.kCallingConstructorInConstructor, message, core.CurrentDSFileName, node.line, node.col, graphNode); inferedType.UID = (int)PrimitiveType.kTypeNull; EmitPushNull(); return procCallNode; } } inferedType = procCallNode.ReturnType; // Get the dot call procedure if (isConstructor || isStaticCall) { bool isGetter = CoreUtils.IsGetter(procName); EmitFunctionCall(depth, procCallNode.ClassID, arglist, procCallNode, funcCall, isGetter, bnode); } else { var procNode = CoreUtils.GetFunctionByName(Constants.kDotMethodName, codeBlock); if (CoreUtils.IsSetter(procName)) { EmitFunctionCall(depth, type, arglist, procNode, funcCall); } // Do not emit breakpoint at getters only - pratapa else if (CoreUtils.IsGetter(procName)) { EmitFunctionCall(depth, type, arglist, procNode, funcCall, true); } else { EmitFunctionCall(depth, type, arglist, procNode, funcCall, false, bnode); } if (dotCallType.UID != (int)PrimitiveType.kTypeVar) { inferedType.UID = dotCallType.UID; } } if (isConstructor) { foreach (AssociativeNode paramNode in dotCall.FunctionCall.FormalArguments) { // Get the lhs symbol list ProtoCore.Type ltype = new ProtoCore.Type(); ltype.UID = globalClassIndex; UpdateNodeRef argNodeRef = new UpdateNodeRef(); DFSGetSymbolList(paramNode, ref ltype, argNodeRef); if (null != graphNode) { if (argNodeRef.nodeList.Count > 0) { graphNode.updatedArguments.Add(argNodeRef); } } } graphNode.firstProc = procCallNode; } return procCallNode; } }
// // proc ResolveFinalNodeRefs() // foreach graphnode in graphnodeList // def firstproc = graphnode.firstproc // // Auto-generate the updateNodeRefs for this graphnode given the // // list stored in the first procedure found in the assignment expression // foreach noderef in firstProc.updatedProperties // def n = graphnode.firstProcRefIndex // def autogenRef = updateNodeRef[n] // autogenRef.append(noderef) // graphnode.pushUpdateRef(autogenRef) // end // end // end // private void ResolveFinalNodeRefs() { foreach (ProtoCore.AssociativeGraph.GraphNode graphNode in codeBlock.instrStream.dependencyGraph.GraphList) { ProtoCore.DSASM.ProcedureNode firstProc = graphNode.firstProc; if (null == firstProc || firstProc.IsAutoGenerated) { continue; } // TODO: The following implementation is wrong. // Suppose for function call: x = foo().bar(); which converted // to x = %dot(foo(), bar(), ...); the following checking skips // it because %dot() is an internal function. -Yu Ke // Do this only for non auto-generated function calls //if any local var is depend on global var if (core.Options.localDependsOnGlobalSet) { if (!firstProc.Name.ToCharArray()[0].Equals('_') && !firstProc.Name.ToCharArray()[0].Equals('%')) { //for each node foreach (ProtoCore.AssociativeGraph.GraphNode gNode in codeBlock.instrStream.dependencyGraph.GraphList) { if (gNode.updateNodeRefList != null && gNode.updateNodeRefList.Count != 0) { if (gNode.procIndex == firstProc.ID && !gNode.updateNodeRefList[0].nodeList[0].symbol.name.ToCharArray()[0].Equals('%')) { foreach (ProtoCore.AssociativeGraph.GraphNode dNode in gNode.dependentList) { if (dNode.procIndex == ProtoCore.DSASM.Constants.kGlobalScope) { if (!dNode.updateNodeRefList[0].nodeList[0].symbol.name.ToCharArray()[0].Equals('%')) { graphNode.PushDependent(dNode); } } } } } } } } if (firstProc.ClassID == Constants.kGlobalScope) { graphNode.updateNodeRefList.AddRange(firstProc.UpdatedGlobalVariables); } else { // For each property modified foreach (ProtoCore.AssociativeGraph.UpdateNodeRef updateRef in firstProc.UpdatedProperties) { int index = graphNode.firstProcRefIndex; // Is it a global function if (ProtoCore.DSASM.Constants.kInvalidIndex != index) { if (core.Options.GenerateSSA) { foreach (ProtoCore.AssociativeGraph.GraphNode dependent in graphNode.dependentList) { // Do this only if first proc is a member function... ProtoCore.AssociativeGraph.UpdateNodeRef autogenRef = new ProtoCore.AssociativeGraph.UpdateNodeRef(dependent.updateNodeRefList[0]); autogenRef = autogenRef.GetUntilFirstProc(); // ... and the first symbol is an instance of a user-defined type int last = autogenRef.nodeList.Count - 1; Validity.Assert(autogenRef.nodeList[last].nodeType != ProtoCore.AssociativeGraph.UpdateNodeType.kMethod && null != autogenRef.nodeList[last].symbol); if (autogenRef.nodeList[last].symbol.datatype.UID >= (int)PrimitiveType.kMaxPrimitives) { autogenRef.PushUpdateNodeRef(updateRef); graphNode.updateNodeRefList.Add(autogenRef); if (graphNode.lastGraphNode != null) { graphNode.lastGraphNode.updateNodeRefList.Add(autogenRef); } } } } else { // Do this only if first proc is a member function... ProtoCore.AssociativeGraph.UpdateNodeRef autogenRef = new ProtoCore.AssociativeGraph.UpdateNodeRef(graphNode.dependentList[0].updateNodeRefList[0]); autogenRef = autogenRef.GetUntilFirstProc(); // ... and the first symbol is an instance of a user-defined type int last = autogenRef.nodeList.Count - 1; Validity.Assert(autogenRef.nodeList[last].nodeType != ProtoCore.AssociativeGraph.UpdateNodeType.kMethod && null != autogenRef.nodeList[last].symbol); if (autogenRef.nodeList[last].symbol.datatype.UID >= (int)PrimitiveType.kMaxPrimitives) { autogenRef.PushUpdateNodeRef(updateRef); graphNode.updateNodeRefList.Add(autogenRef); } } } } } if (graphNode.updatedArguments.Count > 0) { // For each argument modified int n = 0; // Create the current modified argument foreach (KeyValuePair<string, List<ProtoCore.AssociativeGraph.UpdateNodeRef>> argNameModifiedStatementsPair in firstProc.UpdatedArgumentProperties) { // For every single arguments' modified statements foreach (ProtoCore.AssociativeGraph.UpdateNodeRef nodeRef in argNameModifiedStatementsPair.Value) { if (core.Options.GenerateSSA) { // // We just trigger update from whichever statement is dependent on the first pointer associatied with this SSA stmt // Given: // p = C.C(); // a = p.x; // i = f(p); // // %t0 = C.C() // p = %t0 // %t1 = p // %t2 = %t1.x // a = %t2 // %t3 = p // %t4 = f(%t3) -> Assume that function 'f' modifies the property 'x' of its argument // -> The graph node of this stmt has 2 updatenoderefs // -> there are %t4 and p ('p' because it is the first pointer of %t3 // i = %t4 // // Get the modified property name string argname = graphNode.updatedArguments[n].nodeList[0].symbol.name; if (ProtoCore.Utils.CoreUtils.IsSSATemp(argname) && ssaTempToFirstPointerMap.ContainsKey(argname)) { // The property is an SSA temp, Get the SSA first pointer associated with this temp argname = ssaTempToFirstPointerMap[argname]; } bool isAccessible = false; SymbolNode symbol = null; bool isAllocated = VerifyAllocation(argname, globalClassIndex, globalProcIndex, out symbol, out isAccessible); if (isAllocated) { ProtoCore.AssociativeGraph.UpdateNode updateNode = new UpdateNode(); updateNode.symbol = symbol; updateNode.nodeType = ProtoCore.AssociativeGraph.UpdateNodeType.kSymbol; ProtoCore.AssociativeGraph.UpdateNodeRef argNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef(); argNodeRef.PushUpdateNode(updateNode); graphNode.updateNodeRefList.Add(argNodeRef); } } else { ProtoCore.AssociativeGraph.UpdateNodeRef argNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef(); argNodeRef.PushUpdateNodeRef(graphNode.updatedArguments[n]); argNodeRef.PushUpdateNodeRef(nodeRef); graphNode.updateNodeRefList.Add(argNodeRef); } } ++n; } } } }
public ProtoCore.DSASM.ProcedureNode TraverseDotFunctionCall(ProtoCore.AST.Node node, ProtoCore.AST.Node parentNode, int lefttype, int depth, ref ProtoCore.Type inferedType, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone, ProtoCore.AST.AssociativeAST.BinaryExpressionNode bnode = null) { FunctionCallNode funcCall = null; ProtoCore.DSASM.ProcedureNode procCallNode = null; ProtoCore.DSASM.ProcedureNode procDotCallNode = null; string procName = null; List<ProtoCore.Type> arglist = new List<ProtoCore.Type>(); ProtoCore.Type dotCallType = new ProtoCore.Type(); dotCallType.UID = (int)PrimitiveType.kTypeVar; dotCallType.IsIndexable = false; bool isConstructor = false; bool isStaticCall = false; bool isStaticCallAllowed = false; bool isUnresolvedDot = false; bool isUnresolvedMethod = false; int classIndex = ProtoCore.DSASM.Constants.kInvalidIndex; string className = string.Empty; ProtoCore.AST.AssociativeAST.FunctionDotCallNode dotCall = node as ProtoCore.AST.AssociativeAST.FunctionDotCallNode; funcCall = dotCall.DotCall; procName = dotCall.FunctionCall.Function.Name; List<AssociativeNode> replicationGuide = (dotCall.FunctionCall.Function as IdentifierNode).ReplicationGuides; var dotCallFirstArgument = dotCall.DotCall.FormalArguments[0]; if (dotCallFirstArgument is FunctionDotCallNode) { isUnresolvedDot = true; } else if (dotCallFirstArgument is IdentifierNode || dotCallFirstArgument is ThisPointerNode) { // Check if the lhs identifer is a class name string lhsName = ""; int ci = Constants.kInvalidIndex; if (dotCallFirstArgument is IdentifierNode) { lhsName = (dotCallFirstArgument as IdentifierNode).Name; ci = compileStateTracker.ClassTable.IndexOf(lhsName); classIndex = ci; className = lhsName; // As a class name can be used as property name, we need to // check if this identifier is a property or a class name. // if (ci != Constants.kInvalidIndex && globalClassIndex != Constants.kInvalidIndex) { ProtoCore.DSASM.SymbolNode symbolnode; bool isAccessbile = false; bool hasAllocated = VerifyAllocation(lhsName, globalClassIndex, globalProcIndex, out symbolnode, out isAccessbile); // Well, found a property whose name is class name. Now // we need to check if the RHS function call is // constructor or not. if (hasAllocated && isAccessbile && symbolnode.functionIndex == ProtoCore.DSASM.Constants.kInvalidIndex) { var procnode = GetProcedureFromInstance(ci, dotCall.FunctionCall); if (procnode != null && !procnode.isConstructor) { ci = Constants.kInvalidIndex; lhsName = ""; } } } } if (ci != ProtoCore.DSASM.Constants.kInvalidIndex) { // It is a class name dotCall.DotCall.FormalArguments[0] = new IntNode { value = ci.ToString() }; dotCallFirstArgument = dotCall.DotCall.FormalArguments[0]; inferedType.UID = dotCallType.UID = ci; string rhsName = dotCall.FunctionCall.Function.Name; procCallNode = GetProcedureFromInstance(ci, dotCall.FunctionCall, graphNode); if (null != procCallNode) { isConstructor = procCallNode.isConstructor; // It's a static call if its not a constructor isStaticCall = !procCallNode.isConstructor; // If this is a static call and the first method found was not static // Look further if (isStaticCall && !procCallNode.isStatic) { ProtoCore.DSASM.ProcedureNode staticProcCallNode = compileStateTracker.ClassTable.ClassNodes[ci].GetFirstStaticMemberFunction(procName); if (null != staticProcCallNode) { procCallNode = staticProcCallNode; } } isStaticCallAllowed = procCallNode.isStatic && isStaticCall; } else { ProtoCore.DSASM.ProcedureNode staticProcCallNode = compileStateTracker.ClassTable.ClassNodes[ci].GetFirstStaticMemberFunction(procName); string functionName = dotCall.FunctionCall.Function.Name; string property; if (null != staticProcCallNode) { string message = String.Format(ProtoCore.BuildData.WarningMessage.kMethodHasInvalidArguments, functionName); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kCallingNonStaticMethodOnClass, message, compileStateTracker.CurrentDSFileName, dotCall.line, dotCall.col); } else if (CoreUtils.TryGetPropertyName(functionName, out property)) { string message = String.Format(ProtoCore.BuildData.WarningMessage.kCallingNonStaticProperty, lhsName, property); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kCallingNonStaticMethodOnClass, message, compileStateTracker.CurrentDSFileName, dotCall.line, dotCall.col); } else { string message = String.Format(ProtoCore.BuildData.WarningMessage.kCallingNonStaticMethod, lhsName, functionName); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kCallingNonStaticMethodOnClass, message, compileStateTracker.CurrentDSFileName, dotCall.line, dotCall.col); } } } if (dotCall.DotCall.FormalArguments.Count == ProtoCore.DSASM.Constants.kDotCallArgCount) { if (dotCallFirstArgument is IdentifierNode) { ProtoCore.DSASM.SymbolNode symbolnode = null; bool isAccessible = false; bool isAllocated = VerifyAllocation((dotCallFirstArgument as IdentifierNode).Name, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible); if (isAllocated && symbolnode.datatype.UID != (int)PrimitiveType.kTypeVar) { inferedType.UID = symbolnode.datatype.UID; if (ProtoCore.DSASM.Constants.kInvalidIndex != inferedType.UID) { procCallNode = GetProcedureFromInstance(symbolnode.datatype.UID, dotCall.FunctionCall); } if (null != procCallNode) { if (procCallNode.isConstructor) { if (subPass != ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier) { // A constructor cannot be called from an instance string message = String.Format(ProtoCore.BuildData.WarningMessage.KCallingConstructorOnInstance, procName); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kCallingConstructorOnInstance, message, compileStateTracker.CurrentDSFileName, funcCall.line, funcCall.col); } isUnresolvedDot = true; isUnresolvedMethod = true; } else { isAccessible = procCallNode.access == ProtoCore.DSASM.AccessSpecifier.kPublic || (procCallNode.access == ProtoCore.DSASM.AccessSpecifier.kPrivate && procCallNode.classScope == globalClassIndex); if (!isAccessible) { if (subPass != ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier) { string message = String.Format(ProtoCore.BuildData.WarningMessage.kMethodIsInaccessible, procName); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kAccessViolation, message, compileStateTracker.CurrentDSFileName, funcCall.line, funcCall.col); } } if (null != procCallNode) { int dynamicRhsIndex = int.Parse((dotCall.DotCall.FormalArguments[1] as IntNode).value); compileStateTracker.DynamicFunctionTable.functionTable[dynamicRhsIndex].classIndex = procCallNode.classScope; compileStateTracker.DynamicFunctionTable.functionTable[dynamicRhsIndex].procedureIndex = procCallNode.procId; compileStateTracker.DynamicFunctionTable.functionTable[dynamicRhsIndex].pc = procCallNode.pc; } } } } else { isUnresolvedDot = true; } } else if (dotCallFirstArgument is ThisPointerNode) { if (globalClassIndex != Constants.kInvalidIndex) { procCallNode = GetProcedureFromInstance(globalClassIndex, dotCall.FunctionCall); if (null != procCallNode && procCallNode.isConstructor) { dotCall.DotCall.FormalArguments[0] = new IntNode { value = globalClassIndex.ToString() }; dotCallFirstArgument = dotCall.DotCall.FormalArguments[0]; inferedType.UID = dotCallType.UID = ci; } } } } } else if (funcCall.FormalArguments[0] is IntNode) { inferedType.UID = dotCallType.UID = int.Parse((funcCall.FormalArguments[0] as IntNode).value); classIndex = inferedType.UID; procCallNode = GetProcedureFromInstance(dotCallType.UID, dotCall.FunctionCall, graphNode); if (null != procCallNode) { // It's a static call if its not a constructor isConstructor = procCallNode.isConstructor; isStaticCall = !procCallNode.isConstructor; // If this is a static call and the first method found was not static // Look further if (isStaticCall && !procCallNode.isStatic) { ProtoCore.DSASM.ProcedureNode staticProcCallNode = compileStateTracker.ClassTable.ClassNodes[inferedType.UID].GetFirstStaticMemberFunction(procName); if (null != staticProcCallNode) { procCallNode = staticProcCallNode; } } isStaticCallAllowed = procCallNode.isStatic && isStaticCall; className = compileStateTracker.ClassTable.ClassNodes[dotCallType.UID].name; if (isStaticCall && !isStaticCallAllowed) { if (subPass != ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier) { string property; className = compileStateTracker.ClassTable.ClassNodes[dotCallType.UID].name; ProtoCore.DSASM.ProcedureNode staticProcCallNode = compileStateTracker.ClassTable.ClassNodes[inferedType.UID].GetFirstStaticMemberFunction(procName); if (null != staticProcCallNode) { string message = String.Format(ProtoCore.BuildData.WarningMessage.kMethodHasInvalidArguments, procName); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kCallingNonStaticMethodOnClass, message, compileStateTracker.CurrentDSFileName, dotCall.line, dotCall.col); } else if (CoreUtils.TryGetPropertyName(procName, out property)) { string message = String.Format(ProtoCore.BuildData.WarningMessage.kCallingNonStaticProperty, property, className); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kCallingNonStaticMethodOnClass, message, compileStateTracker.CurrentDSFileName, dotCall.line, dotCall.col); } else { string message = String.Format(ProtoCore.BuildData.WarningMessage.kCallingNonStaticMethod, procName, className); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kCallingNonStaticMethodOnClass, message, compileStateTracker.CurrentDSFileName, dotCall.line, dotCall.col); } } isUnresolvedMethod = true; } else { inferedType = procCallNode.returntype; } } } // Its an accceptable method at this point if (!isUnresolvedMethod) { int funtionArgCount = 0; //foreach (AssociativeNode paramNode in funcCall.FormalArguments) for (int n = 0; n < funcCall.FormalArguments.Count; ++n) { AssociativeNode paramNode = funcCall.FormalArguments[n]; ProtoCore.Type paramType = new ProtoCore.Type(); paramType.UID = (int)ProtoCore.PrimitiveType.kTypeVoid; paramType.IsIndexable = false; emitReplicationGuide = false; // If it's a binary node then continue type check, otherwise disable type check and just take the type of paramNode itself // f(1+2.0) -> type check enabled - param is typed as double // f(2) -> type check disabled - param is typed as int enforceTypeCheck = !(paramNode is BinaryExpressionNode); // TODO Jun: Cleansify me // What im doing is just taking the second parameter of the dot op (The method call) // ...and adding it to the graph node dependencies if (ProtoCore.DSASM.Constants.kDotArgIndexDynTableIndex == n) { if (subPass != ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier) { if (!isConstructor) { if (null != procCallNode) { if (graphNode.dependentList.Count > 0) { ProtoCore.AssociativeGraph.UpdateNodeRef nodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef(); ProtoCore.AssociativeGraph.UpdateNode updateNode = new ProtoCore.AssociativeGraph.UpdateNode(); ProtoCore.DSASM.ProcedureNode procNodeDummy = new ProtoCore.DSASM.ProcedureNode(); if (procCallNode.isAutoGenerated) { ProtoCore.DSASM.SymbolNode sym = new ProtoCore.DSASM.SymbolNode(); sym.name = procName.Remove(0, ProtoCore.DSASM.Constants.kSetterPrefix.Length); updateNode.nodeType = ProtoCore.AssociativeGraph.UpdateNodeType.kSymbol; updateNode.symbol = sym; } else { procNodeDummy.name = procName; updateNode.nodeType = ProtoCore.AssociativeGraph.UpdateNodeType.kMethod; updateNode.procNode = procNodeDummy; } graphNode.dependentList[0].updateNodeRefList[0].nodeList.Add(updateNode); } } else { // comment Jun: // This is dotarg whos first argument is also a dotarg // dotarg(dorarg...)...) if (graphNode.dependentList.Count > 0) { if (ProtoCore.Utils.CoreUtils.IsGetterSetter(procName)) { ProtoCore.AssociativeGraph.UpdateNode updateNode = new ProtoCore.AssociativeGraph.UpdateNode(); ProtoCore.DSASM.SymbolNode sym = new ProtoCore.DSASM.SymbolNode(); sym.name = procName.Remove(0, ProtoCore.DSASM.Constants.kSetterPrefix.Length); updateNode.nodeType = ProtoCore.AssociativeGraph.UpdateNodeType.kSymbol; updateNode.symbol = sym; graphNode.dependentList[0].updateNodeRefList[0].nodeList.Add(updateNode); } } } } } } // Traversing the first arg (the LHS pointer/Static instanct/Constructor if (ProtoCore.DSASM.Constants.kDotArgIndexPtr == n) { // Comment Jun: // Allow guides only on 'this' pointers for non getter/setter methods // No guides for 'this' pointers in constructors calls (There is no this pointer yet) // /* class C { def f(a : int) { return = 10; } } p = {C.C(), C.C()}; x = p<1>.f({1,2}<2>); // guides allowed on the pointer 'p' class A { x : var[]; constructor A() { x = {1,2}; } } a = A.A(); b = A.A(); c = a<1>.x<2>; // guides not allowed on getter */ if (!ProtoCore.Utils.CoreUtils.IsGetterSetter(procName) && !isConstructor) { emitReplicationGuide = true; } DfsTraverse(paramNode, ref paramType, false, graphNode, subPass, bnode); if (subPass != ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier) { if (isStaticCall && isStaticCallAllowed) { Validity.Assert(ProtoCore.DSASM.Constants.kInvalidIndex != classIndex); Validity.Assert(string.Empty != className); SymbolNode classSymbol = new SymbolNode(); classSymbol.name = className; classSymbol.classScope = classIndex; ProtoCore.AssociativeGraph.GraphNode dependentNode = new ProtoCore.AssociativeGraph.GraphNode(); dependentNode.PushSymbolReference(classSymbol, ProtoCore.AssociativeGraph.UpdateNodeType.kSymbol); graphNode.PushDependent(dependentNode); } } } // Traversing the actual arguments passed into the function (not the dot function) else if (ProtoCore.DSASM.Constants.kDotArgIndexArrayArgs == n) { int defaultAdded = 0; // If its null this is the second call in a chained dot if (null != procCallNode) { // Check how many args were passed in.... against what is expected defaultAdded = procCallNode.argInfoList.Count - dotCall.FunctionCall.FormalArguments.Count; } // Enable graphnode dependencies if its a setter method bool allowDependentState = null != graphNode ? graphNode.allowDependents : false; if (ProtoCore.Utils.CoreUtils.IsSetter(procName)) { // If the arguments are not temporaries ProtoCore.AST.AssociativeAST.ExprListNode exprList = paramNode as ExprListNode; Validity.Assert(1 == exprList.list.Count); string varname = string.Empty; if (exprList.list[0] is IdentifierNode) { varname = (exprList.list[0] as IdentifierNode).Name; // Only allow the acutal function variables and SSA temp vars // TODO Jun: determine what temp could be passed in that is autodegenerated and non-SSA if (!ProtoCore.Utils.CoreUtils.IsAutoGeneratedVar(varname) || ProtoCore.Utils.CoreUtils.IsSSATemp(varname)) { graphNode.allowDependents = true; } } else { graphNode.allowDependents = true; } } emitReplicationGuide = true; if (defaultAdded > 0) { ProtoCore.AST.AssociativeAST.ExprListNode exprList = paramNode as ExprListNode; if (subPass != AssociativeSubCompilePass.kUnboundIdentifier) { for (int i = 0; i < defaultAdded; i++) { exprList.list.Add(new DefaultArgNode()); } } DfsTraverse(paramNode, ref paramType, false, graphNode, subPass); funtionArgCount = exprList.list.Count; } else { Validity.Assert(paramNode is ProtoCore.AST.AssociativeAST.ExprListNode); ProtoCore.AST.AssociativeAST.ExprListNode exprList = paramNode as ProtoCore.AST.AssociativeAST.ExprListNode; // Comment Jun: This is a getter/setter or a an auto-generated thisarg function... // ...add the dynamic sv that will be resolved as a pointer at runtime if (!isStaticCall && !isConstructor) { //if (null != procCallNode && ProtoCore.Utils.CoreUtils.IsGetterSetter(procCallNode.name) && AssociativeSubCompilePass.kNone == subPass) // TODO Jun: pls get rid of subPass checking outside the core travesal if (ProtoCore.DSASM.AssociativeSubCompilePass.kNone == subPass) { exprList.list.Insert(0, new DynamicNode()); } } if (exprList.list.Count > 0) { foreach (ProtoCore.AST.AssociativeAST.AssociativeNode exprListNode in exprList.list) { bool repGuideState = emitReplicationGuide; if (subPass != ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier) { if (exprListNode is ProtoCore.AST.AssociativeAST.ExprListNode || exprListNode is ProtoCore.AST.AssociativeAST.GroupExpressionNode) { if (compileStateTracker.Options.TempReplicationGuideEmptyFlag) { // Emit the replication guide for the exprlist List<ProtoCore.AST.AssociativeAST.AssociativeNode> repGuideList = GetReplicationGuides(exprListNode); EmitReplicationGuides(repGuideList, true); emitReplicationGuide = false; // Pop off the guide if the current element was an array if (null != repGuideList) { EmitInstrConsole(ProtoCore.DSASM.kw.popg); EmitPopGuide(); } } } } else { emitReplicationGuide = false; } DfsTraverse(exprListNode, ref paramType, false, graphNode, subPass, bnode); emitReplicationGuide = repGuideState; } if (subPass != ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier) { EmitInstrConsole(ProtoCore.DSASM.kw.alloca, exprList.list.Count.ToString()); EmitPopArray(exprList.list.Count); if (exprList.ArrayDimensions != null) { int dimensions = DfsEmitArrayIndexHeap(exprList.ArrayDimensions, graphNode); EmitInstrConsole(ProtoCore.DSASM.kw.pushindex, dimensions.ToString() + "[dim]"); EmitPushArrayIndex(dimensions); } } } else { if (exprList != null) { bool emitReplicationGuideState = emitReplicationGuide; emitReplicationGuide = false; DfsTraverse(paramNode, ref paramType, false, graphNode, subPass); emitReplicationGuide = emitReplicationGuideState; } else { DfsTraverse(paramNode, ref paramType, false, graphNode, subPass); } } funtionArgCount = exprList.list.Count; } emitReplicationGuide = false; // Restore the state only if it is a setter method if (ProtoCore.Utils.CoreUtils.IsSetter(procName)) { graphNode.allowDependents = allowDependentState; } } else if (ProtoCore.DSASM.Constants.kDotArgIndexArgCount == n) { ProtoCore.AST.AssociativeAST.IntNode argNumNode = new ProtoCore.AST.AssociativeAST.IntNode() { value = funtionArgCount.ToString() }; DfsTraverse(argNumNode, ref paramType, false, graphNode, subPass); } else { DfsTraverse(paramNode, ref paramType, false, graphNode, subPass); } emitReplicationGuide = false; enforceTypeCheck = true; arglist.Add(paramType); } } if (subPass == ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier) { return null; } // Comment Jun: Append the lhs pointer as an argument to the overloaded function if (!isConstructor && !isStaticCall) { Validity.Assert(dotCall.DotCall.FormalArguments[ProtoCore.DSASM.Constants.kDotArgIndexArrayArgs] is ExprListNode); ExprListNode functionArgs = dotCall.DotCall.FormalArguments[ProtoCore.DSASM.Constants.kDotArgIndexArrayArgs] as ExprListNode; functionArgs.list.Insert(0, dotCall.DotCall.FormalArguments[ProtoCore.DSASM.Constants.kDotArgIndexPtr]); } if (isUnresolvedMethod) { EmitNullNode(new NullNode(), ref inferedType); return null; } procDotCallNode = compileStateTracker.GetFirstVisibleProcedure(ProtoCore.DSASM.Constants.kDotArgMethodName, arglist, codeBlock); // From here on, handle the actual procedure call int type = ProtoCore.DSASM.Constants.kInvalidIndex; int refClassIndex = ProtoCore.DSASM.Constants.kInvalidIndex; if (parentNode != null && parentNode is ProtoCore.AST.AssociativeAST.IdentifierListNode) { ProtoCore.AST.Node leftnode = (parentNode as ProtoCore.AST.AssociativeAST.IdentifierListNode).LeftNode; if (leftnode != null && leftnode is ProtoCore.AST.AssociativeAST.IdentifierNode) { refClassIndex = compileStateTracker.ClassTable.IndexOf(leftnode.Name); } } if (dotCallFirstArgument is FunctionCallNode || dotCallFirstArgument is FunctionDotCallNode || dotCallFirstArgument is ExprListNode) { inferedType.UID = arglist[0].UID; } // If lefttype is a valid class then check if calling a constructor if ((int)ProtoCore.PrimitiveType.kInvalidType != inferedType.UID && (int)ProtoCore.PrimitiveType.kTypeVoid != inferedType.UID && procName != ProtoCore.DSASM.Constants.kFunctionPointerCall) { bool isStaticOrConstructor = refClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex; procCallNode = compileStateTracker.ClassTable.ClassNodes[inferedType.UID].GetFirstMemberFunction(procName); } // Try function pointer firstly if ((procCallNode == null) && (procName != ProtoCore.DSASM.Constants.kFunctionPointerCall)) { bool isAccessibleFp; ProtoCore.DSASM.SymbolNode symbolnode = null; bool isAllocated = VerifyAllocation(procName, globalClassIndex, globalProcIndex, out symbolnode, out isAccessibleFp); if (isAllocated) // not checking the type against function pointer, as the type could be var { procName = ProtoCore.DSASM.Constants.kFunctionPointerCall; // The graph node always depends on this function pointer if (null != graphNode) { ProtoCore.AssociativeGraph.GraphNode dependentNode = new ProtoCore.AssociativeGraph.GraphNode(); dependentNode.PushSymbolReference(symbolnode); graphNode.PushDependent(dependentNode); } } } // Always try global function firstly. Because we dont have syntax // support for calling global function (say, ::foo()), if we try // member function firstly, there is no way to call a global function // For member function, we can use this.foo() to distinguish it from // global function. if ((procCallNode == null) && (procName != ProtoCore.DSASM.Constants.kFunctionPointerCall)) { procCallNode = compileStateTracker.GetFirstVisibleProcedure(procName, arglist, codeBlock); if (null != procCallNode) { type = ProtoCore.DSASM.Constants.kGlobalScope; if (compileStateTracker.TypeSystem.IsHigherRank(procCallNode.returntype.UID, inferedType.UID)) { inferedType = procCallNode.returntype; } } } // Try member functions in global class scope if ((procCallNode == null) && (procName != ProtoCore.DSASM.Constants.kFunctionPointerCall) && (parentNode == null)) { if (globalClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex) { int realType; bool isAccessible; bool isStaticOrConstructor = refClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex; ProtoCore.DSASM.ProcedureNode memProcNode = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out realType, isStaticOrConstructor); if (memProcNode != null) { Debug.Assert(realType != ProtoCore.DSASM.Constants.kInvalidIndex); procCallNode = memProcNode; inferedType = procCallNode.returntype; type = realType; if (!isAccessible) { string message = String.Format(ProtoCore.BuildData.WarningMessage.kMethodIsInaccessible, procName); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kAccessViolation, message, compileStateTracker.CurrentDSFileName, funcCall.line, funcCall.col); inferedType.UID = (int)PrimitiveType.kTypeNull; EmitPushNull(); return procCallNode; } } } } if (isUnresolvedDot) { // Get the dot call procedure ProtoCore.DSASM.ProcedureNode procNode = procDotCallNode; if (!isConstructor && !isStaticCall) { procNode = compileStateTracker.GetFirstVisibleProcedure(ProtoCore.DSASM.Constants.kDotMethodName, null, codeBlock); } if(CoreUtils.IsGetter(procName)) { EmitFunctionCall(depth, type, arglist, procNode, funcCall, true); } else EmitFunctionCall(depth, type, arglist, procNode, funcCall, false, bnode); if (dotCallType.UID != (int)PrimitiveType.kTypeVar) { inferedType.UID = dotCallType.UID; } return procCallNode; } if (null != procCallNode) { if (procCallNode.isConstructor && (globalClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex) && (globalProcIndex != ProtoCore.DSASM.Constants.kInvalidIndex) && (globalClassIndex == inferedType.UID)) { ProtoCore.DSASM.ProcedureNode contextProcNode = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].vtable.procList[globalProcIndex]; if (contextProcNode.isConstructor && string.Equals(contextProcNode.name, procCallNode.name) && contextProcNode.runtimeIndex == procCallNode.runtimeIndex) { string message = String.Format(ProtoCore.BuildData.WarningMessage.kCallingConstructorInConstructor, procName); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kCallingConstructorInConstructor, message, compileStateTracker.CurrentDSFileName, node.line, node.col); inferedType.UID = (int)PrimitiveType.kTypeNull; EmitPushNull(); return procCallNode; } } inferedType = procCallNode.returntype; //if call is replication call if (procCallNode.isThisCallReplication) { inferedType.IsIndexable = true; inferedType.rank++; } // Get the dot call procedure ProtoCore.DSASM.ProcedureNode procNode = procDotCallNode; if (!isConstructor && !isStaticCall) { procNode = compileStateTracker.GetFirstVisibleProcedure(ProtoCore.DSASM.Constants.kDotMethodName, null, codeBlock); } if (CoreUtils.IsSetter(procName)) { EmitFunctionCall(depth, type, arglist, procNode, funcCall); } // Do not emit breakpoint at getters only - pratapa else if (CoreUtils.IsGetter(procName)) { EmitFunctionCall(depth, type, arglist, procNode, funcCall, true); } else { EmitFunctionCall(depth, type, arglist, procNode, funcCall, false, bnode); } if (dotCallType.UID != (int)PrimitiveType.kTypeVar) { inferedType.UID = dotCallType.UID; } if (isConstructor) { foreach (AssociativeNode paramNode in dotCall.FunctionCall.FormalArguments) { // Get the lhs symbol list ProtoCore.Type ltype = new ProtoCore.Type(); ltype.UID = globalClassIndex; ProtoCore.AssociativeGraph.UpdateNodeRef argNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef(); DFSGetSymbolList(paramNode, ref ltype, argNodeRef); if (null != graphNode) { graphNode.updatedArguments.Add(argNodeRef); } } graphNode.firstProc = procCallNode; } return procCallNode; } else { // Function does not exist at this point but we try to reolve at runtime if (depth <= 0 && procName != ProtoCore.DSASM.Constants.kFunctionPointerCall) { if (inferedType.UID != (int)PrimitiveType.kTypeVar) { if (!compileStateTracker.Options.SuppressFunctionResolutionWarning) { string property; if (CoreUtils.TryGetPropertyName(procName, out property)) { string message = String.Format(ProtoCore.BuildData.WarningMessage.kPropertyNotFound, property); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kPropertyNotFound, message, compileStateTracker.CurrentDSFileName, funcCall.line, funcCall.col); } else { string message = String.Format(ProtoCore.BuildData.WarningMessage.kMethodNotFound, procName); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kFunctionNotFound, message, compileStateTracker.CurrentDSFileName, funcCall.line, funcCall.col); } } inferedType.UID = (int)PrimitiveType.kTypeNull; } // Get the dot call procedure ProtoCore.DSASM.ProcedureNode procNode = procDotCallNode; if (!isConstructor && !isStaticCall) { procNode = compileStateTracker.GetFirstVisibleProcedure(ProtoCore.DSASM.Constants.kDotMethodName, null, codeBlock); } if (CoreUtils.IsGetter(procName)) { EmitFunctionCall(depth, type, arglist, procNode, funcCall, true); } else EmitFunctionCall(depth, type, arglist, procNode, funcCall, false, bnode); if (dotCallType.UID != (int)PrimitiveType.kTypeVar) { inferedType.UID = dotCallType.UID; } } else { if (procName == ProtoCore.DSASM.Constants.kFunctionPointerCall && depth == 0) { ProtoCore.DSASM.DynamicFunctionNode dynamicFunctionNode = new ProtoCore.DSASM.DynamicFunctionNode(procName, arglist, lefttype); compileStateTracker.DynamicFunctionTable.functionTable.Add(dynamicFunctionNode); var iNode = nodeBuilder.BuildIdentfier(funcCall.Function.Name); EmitIdentifierNode(iNode, ref inferedType); } else { ProtoCore.DSASM.DynamicFunctionNode dynamicFunctionNode = new ProtoCore.DSASM.DynamicFunctionNode(funcCall.Function.Name, arglist, lefttype); compileStateTracker.DynamicFunctionTable.functionTable.Add(dynamicFunctionNode); } // The function call EmitInstrConsole(ProtoCore.DSASM.kw.callr, funcCall.Function.Name + "[dynamic]"); EmitDynamicCall(compileStateTracker.DynamicFunctionTable.functionTable.Count - 1, globalClassIndex, depth, funcCall.line, funcCall.col, funcCall.endLine, funcCall.endCol); // The function return value EmitInstrConsole(ProtoCore.DSASM.kw.push, ProtoCore.DSASM.kw.regRX); ProtoCore.DSASM.StackValue opReturn = new ProtoCore.DSASM.StackValue(); opReturn.optype = ProtoCore.DSASM.AddressType.Register; opReturn.opdata = (int)ProtoCore.DSASM.Registers.RX; EmitPush(opReturn); if (compileStateTracker.Options.TempReplicationGuideEmptyFlag && emitReplicationGuide) { int guides = EmitReplicationGuides(replicationGuide); EmitInstrConsole(ProtoCore.DSASM.kw.pushindex, guides + "[guide]"); EmitPushReplicationGuide(guides); } //assign inferedType to var inferedType.UID = (int)PrimitiveType.kTypeVar; } } return procDotCallNode; }
private ProtoCore.AssociativeGraph.UpdateNodeRef AutoGenerateUpdateArgumentArrayReference(AssociativeNode node, ProtoCore.AssociativeGraph.GraphNode graphNode) { // Get the lhs symbol list ProtoCore.Type type = new ProtoCore.Type(); type.UID = globalClassIndex; ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef(); DFSGetSymbolList(node, ref type, leftNodeRef); ProtoCore.DSASM.SymbolNode firstSymbol = null; // Check if we are inside a procedure if (null != localProcedure) { if (1 == leftNodeRef.nodeList.Count) { firstSymbol = leftNodeRef.nodeList[0].symbol; // Check if it is an array modification if (graphNode.dimensionNodeList.Count > 0) { // There is only one, see if its an array modification // Now check if the first element of the identifier list is an argument foreach (ProtoCore.DSASM.ArgumentInfo argInfo in localProcedure.argInfoList) { // See if this modified variable is an argument if (argInfo.Name == firstSymbol.name) { List<ProtoCore.AssociativeGraph.UpdateNode> dimensionList = null; bool found = localProcedure.updatedArgumentArrays.TryGetValue(argInfo.Name, out dimensionList); if (found) { // Overwrite it dimensionList = graphNode.dimensionNodeList; } else { // Create a new modified array entry localProcedure.updatedArgumentArrays.Add(argInfo.Name, graphNode.dimensionNodeList); } } } } } } return leftNodeRef; }
public bool DependsOn(UpdateNodeRef modifiedRef, ref GraphNode dependentNode) { bool match = false; foreach (GraphNode depNode in dependentList) { Validity.Assert(1 == depNode.updateNodeRefList.Count); //foreach (UpdateNodeRef depNodeRef in depNode.updateNodeRefList) //{ UpdateNodeRef depNodeRef = depNode.updateNodeRefList[0]; bool bothSymbolsMatch = false; bool bothSymbolsStatic = false; bool inImperativeMatch = false; bool inImperative = false; if (depNodeRef != null) { if (depNodeRef.nodeList != null && modifiedRef.nodeList != null && depNodeRef.nodeList.Count > 0 && modifiedRef.nodeList.Count > 0) { if (depNodeRef.nodeList.Count > modifiedRef.nodeList.Count) { for (int m = 0; m < depNodeRef.nodeList.Count; m++) { if (depNodeRef.nodeList[m] != null && modifiedRef.nodeList[0] != null && depNodeRef.nodeList[m].symbol != null && modifiedRef.nodeList[0].symbol != null) { if (modifiedRef.nodeList[0].symbol.forArrayName != null && !modifiedRef.nodeList[0].symbol.forArrayName.Equals("")) { inImperative = true; if (modifiedRef.nodeList[0].symbol.functionIndex == Constants.kInvalidIndex) { inImperative = inImperative && (depNodeRef.nodeList[m].symbol.functionIndex == Constants.kInvalidIndex) && (modifiedRef.nodeList[0].symbol.codeBlockId == depNodeRef.nodeList[m].symbol.codeBlockId); } if (inImperative && modifiedRef.nodeList[0].symbol.functionIndex == depNodeRef.nodeList[m].symbol.functionIndex && (modifiedRef.nodeList[0].symbol.name == depNodeRef.nodeList[m].symbol.name || modifiedRef.nodeList[0].symbol.forArrayName == depNodeRef.nodeList[m].symbol.name)) { inImperativeMatch = true; } } } } } else if (depNodeRef.nodeList.Count == modifiedRef.nodeList.Count) { for (int m = 0; m < depNodeRef.nodeList.Count && m < modifiedRef.nodeList.Count; m++) { if (depNodeRef.nodeList[m] != null && modifiedRef.nodeList[m] != null && depNodeRef.nodeList[m].symbol != null && modifiedRef.nodeList[m].symbol != null) { if (modifiedRef.nodeList[0].symbol.forArrayName != null && !modifiedRef.nodeList[0].symbol.forArrayName.Equals("")) { inImperative = true; if (modifiedRef.nodeList[m].symbol.functionIndex == Constants.kInvalidIndex) { inImperative = inImperative && (depNodeRef.nodeList[m].symbol.functionIndex == Constants.kInvalidIndex) && (modifiedRef.nodeList[m].symbol.codeBlockId == depNodeRef.nodeList[m].symbol.codeBlockId); } if (inImperative && modifiedRef.nodeList[m].symbol.functionIndex == depNodeRef.nodeList[m].symbol.functionIndex && modifiedRef.nodeList[m].symbol.name == depNodeRef.nodeList[m].symbol.name) { inImperativeMatch = true; } } } } } } } if (!inImperativeMatch) { // Does first symbol match if (null != modifiedRef.nodeList[0].symbol && null != depNodeRef.nodeList[0].symbol) { bothSymbolsMatch = modifiedRef.nodeList[0].symbol.Equals(depNodeRef.nodeList[0].symbol); bothSymbolsStatic = modifiedRef.nodeList[0].symbol.memregion == MemoryRegion.kMemStatic && depNodeRef.nodeList[0].symbol.memregion == MemoryRegion.kMemStatic && modifiedRef.nodeList[0].symbol.name == depNodeRef.nodeList[0].symbol.name; // Check further if their array index match in literal values if (bothSymbolsMatch) { // Are the indices the same number bool areIndicesMatching = modifiedRef.nodeList[0].dimensionNodeList.Count >= depNodeRef.nodeList[0].dimensionNodeList.Count; if (areIndicesMatching && depNodeRef.nodeList[0].dimensionNodeList.Count > 0) { for (int n = 0; n < depNodeRef.nodeList[0].dimensionNodeList.Count; ++n) { // Is either a non-literal UpdateNode modDimNode = modifiedRef.nodeList[0].dimensionNodeList[n]; UpdateNode depDimNode = depNodeRef.nodeList[0].dimensionNodeList[n]; if (modDimNode.nodeType != depDimNode.nodeType) { bothSymbolsMatch = false; } else if (modDimNode.nodeType == UpdateNodeType.kLiteral) { bothSymbolsMatch = modDimNode.symbol.name.CompareTo(depDimNode.symbol.name) == 0; } else if (modDimNode.nodeType == UpdateNodeType.kSymbol) { bothSymbolsMatch = modDimNode.symbol.Equals(depDimNode.symbol); } else { bothSymbolsMatch = false; } if (!bothSymbolsMatch) { break; } } } } } if (bothSymbolsMatch || bothSymbolsStatic) { match = true; // If it is static, then all symbols must match if (bothSymbolsStatic) { // The number of symbols in the modifed reference... // ...must match // The number of symbols in the current dependency noderef if (modifiedRef.nodeList.Count == depNodeRef.nodeList.Count) { for (int n = 1; n < modifiedRef.nodeList.Count; ++n) { //Validity.Assert(!modifiedRef.nodeList[n].isMethod); //Validity.Assert(!depNodeRef.nodeList[n].isMethod); if (UpdateNodeType.kMethod == modifiedRef.nodeList[n].nodeType || UpdateNodeType.kMethod == depNodeRef.nodeList[n].nodeType) { match = false; break; } if (modifiedRef.nodeList[n].symbol.index != depNodeRef.nodeList[n].symbol.index) { match = false; break; } } } else { match = false; } } else { if (modifiedRef.nodeList.Count >= depNodeRef.nodeList.Count) { // // The modifed reference is either the same nodelist length or more than the current dependent // a.x.y is being compared to a.x // for (int n = 1; n < modifiedRef.nodeList.Count; ++n) { if (modifiedRef.nodeList.Count != depNodeRef.nodeList.Count) { if (n >= depNodeRef.nodeList.Count) { match = false; break; } } if (UpdateNodeType.kMethod == modifiedRef.nodeList[n].nodeType || UpdateNodeType.kMethod == depNodeRef.nodeList[n].nodeType) { match = false; break; } if (modifiedRef.nodeList[n].symbol.name != depNodeRef.nodeList[n].symbol.name) { match = false; break; } } } else { // // The modifed reference nodelist is less than than the current dependent nodelist // a.x is being compared to a.x.y // for (int n = 1; n < depNodeRef.nodeList.Count; ++n) { if (n >= modifiedRef.nodeList.Count) { break; } if (UpdateNodeType.kMethod == modifiedRef.nodeList[n].nodeType || UpdateNodeType.kMethod == depNodeRef.nodeList[n].nodeType) { match = false; break; } if (modifiedRef.nodeList[n].symbol.name != depNodeRef.nodeList[n].symbol.name) { match = false; break; } } } } } dependentNode = depNode; if (match) { break; } } else { for (int m = 0; m < depNodeRef.nodeList.Count && m < modifiedRef.nodeList.Count; m++) { // Does first symbol match if (null != modifiedRef.nodeList[m].symbol && null != depNodeRef.nodeList[m].symbol) { bothSymbolsMatch = modifiedRef.nodeList[m].symbol.Equals(depNodeRef.nodeList[m].symbol); bothSymbolsStatic = modifiedRef.nodeList[m].symbol.memregion == MemoryRegion.kMemStatic && depNodeRef.nodeList[m].symbol.memregion == MemoryRegion.kMemStatic && modifiedRef.nodeList[m].symbol.name == depNodeRef.nodeList[m].symbol.name; // Check further if their array index match in literal values if (bothSymbolsMatch) { // Are the indices the same number bool areIndicesMatching = modifiedRef.nodeList[m].dimensionNodeList.Count == depNodeRef.nodeList[m].dimensionNodeList.Count; if (areIndicesMatching && modifiedRef.nodeList[m].dimensionNodeList.Count > 0) { for (int n = 0; n < modifiedRef.nodeList[m].dimensionNodeList.Count; ++n) { // Is either a non-literal bool isEitherNonLiteral = modifiedRef.nodeList[m].dimensionNodeList[n].nodeType != UpdateNodeType.kLiteral || depNodeRef.nodeList[m].dimensionNodeList[n].nodeType != UpdateNodeType.kLiteral; if (isEitherNonLiteral) { bothSymbolsMatch = false; break; } // They are both literal, now check for their literal values if (0 != modifiedRef.nodeList[m].dimensionNodeList[n].symbol.name.CompareTo(depNodeRef.nodeList[m].dimensionNodeList[n].symbol.name)) { // They are not the same bothSymbolsMatch = false; break; } } } } } if (bothSymbolsMatch || bothSymbolsStatic || inImperativeMatch) { match = true; // If it is static, then all symbols must match if (bothSymbolsStatic) { // The number of symbols in the modifed reference... // ...must match // The number of symbols in the current dependency noderef if (modifiedRef.nodeList.Count == depNodeRef.nodeList.Count) { for (int n = 1; n < modifiedRef.nodeList.Count; ++n) { //Validity.Assert(!modifiedRef.nodeList[n].isMethod); //Validity.Assert(!depNodeRef.nodeList[n].isMethod); if (UpdateNodeType.kMethod == modifiedRef.nodeList[n].nodeType || UpdateNodeType.kMethod == depNodeRef.nodeList[n].nodeType) { match = false; break; } if (modifiedRef.nodeList[n].symbol.index != depNodeRef.nodeList[n].symbol.index) { match = false; break; } } } else { match = false; } } else { if (modifiedRef.nodeList.Count >= depNodeRef.nodeList.Count) { // // The modifed reference is either the same nodelist length or more than the current dependent // a.x.y is being compared to a.x // for (int n = 1; n < modifiedRef.nodeList.Count; ++n) { if (modifiedRef.nodeList.Count != depNodeRef.nodeList.Count) { if (n >= depNodeRef.nodeList.Count) { match = false; break; } } if (UpdateNodeType.kMethod == modifiedRef.nodeList[n].nodeType || UpdateNodeType.kMethod == depNodeRef.nodeList[n].nodeType) { match = false; break; } if (modifiedRef.nodeList[n].symbol.name != depNodeRef.nodeList[n].symbol.name) { match = false; break; } } } else { // // The modifed reference nodelist is less than than the current dependent nodelist // a.x is being compared to a.x.y // for (int n = 1; n < depNodeRef.nodeList.Count; ++n) { if (n >= modifiedRef.nodeList.Count) { break; } if (UpdateNodeType.kMethod == modifiedRef.nodeList[n].nodeType || UpdateNodeType.kMethod == depNodeRef.nodeList[n].nodeType) { match = false; break; } if (modifiedRef.nodeList[n].symbol.name != depNodeRef.nodeList[n].symbol.name) { match = false; break; } } } } } } dependentNode = depNode; if (match) { break; } } //} } return(match); }
protected void BuildRealDependencyForIdentList(AssociativeGraph.GraphNode graphNode) { // Push all dependent pointers ProtoCore.AST.AssociativeAST.IdentifierListNode identList = BuildIdentifierList(ssaPointerList); // Comment Jun: perhaps this can be an assert? if (null != identList) { ProtoCore.Type type = new ProtoCore.Type(); type.UID = globalClassIndex; ProtoCore.AssociativeGraph.UpdateNodeRef nodeRef = new AssociativeGraph.UpdateNodeRef(); int functionIndex = globalProcIndex; DFSGetSymbolList_Simple(identList, ref type, ref functionIndex, nodeRef); if (null != graphNode && nodeRef.nodeList.Count > 0) { ProtoCore.AssociativeGraph.GraphNode dependentNode = new ProtoCore.AssociativeGraph.GraphNode(); dependentNode.updateNodeRefList.Add(nodeRef); graphNode.PushDependent(dependentNode); } } }
public void PushSymbolReference(ProtoCore.DSASM.SymbolNode symbol, ProtoCore.AssociativeGraph.UpdateNodeType type = UpdateNodeType.kSymbol) { Validity.Assert(null != symbol); Validity.Assert(null != updateNodeRefList); UpdateNode updateNode = new UpdateNode(); updateNode.symbol = symbol; updateNode.nodeType = type; UpdateNodeRef nodeRef = new UpdateNodeRef(); nodeRef.PushUpdateNode(updateNode); updateNodeRefList.Add(nodeRef); }
public void PushProcReference(ProtoCore.DSASM.ProcedureNode proc) { Validity.Assert(null != proc); Validity.Assert(null != updateNodeRefList); UpdateNode updateNode = new UpdateNode(); updateNode.procNode = proc; updateNode.nodeType = UpdateNodeType.kMethod; UpdateNodeRef nodeRef = new UpdateNodeRef(); nodeRef.PushUpdateNode(updateNode); updateNodeRefList.Add(nodeRef); }
public bool IsUpdateableBy(UpdateNodeRef modifiedRef) { // Function to check if the current graphnode can be modified by the modified reference bool isUpdateable = false; if (modifiedRef.nodeList.Count < updateNodeRefList[0].nodeList.Count) { isUpdateable = true; for (int n = 0; n < modifiedRef.nodeList.Count; ++n) { ProtoCore.AssociativeGraph.UpdateNode updateNode = modifiedRef.nodeList[n]; if (!updateNode.IsEqual(updateNodeRefList[0].nodeList[n])) { isUpdateable = false; break; } } } return isUpdateable; }
public override ProtoCore.DSASM.ProcedureNode TraverseFunctionCall(ProtoCore.AST.Node node, ProtoCore.AST.Node parentNode, int lefttype, int depth, ref ProtoCore.Type inferedType, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone, ProtoCore.AST.Node bnode = null) { FunctionCallNode funcCall = null; string procName = null; List<ProtoCore.Type> arglist = new List<ProtoCore.Type>(); ProtoCore.Type dotCallType = new ProtoCore.Type(); dotCallType.UID = (int)PrimitiveType.kTypeVar; dotCallType.IsIndexable = false; ProtoCore.AssociativeGraph.UpdateNode updateNode = new ProtoCore.AssociativeGraph.UpdateNode(); if (node is ProtoCore.AST.AssociativeAST.FunctionDotCallNode) { return TraverseDotFunctionCall(node, parentNode, lefttype, depth, ref inferedType, graphNode, subPass, bnode as BinaryExpressionNode); } else { funcCall = node as FunctionCallNode; procName = funcCall.Function.Name; int classIndex = compileStateTracker.ClassTable.IndexOf(procName); bool isAccessible; int dummy; // To support unamed constructor if (classIndex != Constants.kInvalidIndex) { ProcedureNode constructor = compileStateTracker.ClassTable.ClassNodes[classIndex].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out dummy, true); if (constructor != null && constructor.isConstructor) { FunctionCallNode rhsFNode = node as ProtoCore.AST.AssociativeAST.FunctionCallNode; AssociativeNode classNode = nodeBuilder.BuildIdentfier(procName); FunctionDotCallNode dotCallNode = ProtoCore.Utils.CoreUtils.GenerateCallDotNode(classNode, rhsFNode, compileStateTracker); return TraverseDotFunctionCall(dotCallNode, parentNode, lefttype, depth, ref inferedType, graphNode, subPass, bnode as BinaryExpressionNode); } } } foreach (AssociativeNode paramNode in funcCall.FormalArguments) { ProtoCore.Type paramType = new ProtoCore.Type(); paramType.UID = (int)ProtoCore.PrimitiveType.kTypeVoid; paramType.IsIndexable = false; // The range expression function does not need replication guides emitReplicationGuide = !procName.Equals(ProtoCore.DSASM.Constants.kFunctionRangeExpression); // If it's a binary node then continue type check, otherwise disable type check and just take the type of paramNode itself // f(1+2.0) -> type check enabled - param is typed as double // f(2) -> type check disabled - param is typed as int enforceTypeCheck = !(paramNode is BinaryExpressionNode); DfsTraverse(paramNode, ref paramType, false, graphNode, subPass, bnode); emitReplicationGuide = false; enforceTypeCheck = true; arglist.Add(paramType); } if (subPass == ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier) { return null; } ProtoCore.DSASM.ProcedureNode procNode = null; int type = ProtoCore.DSASM.Constants.kInvalidIndex; int refClassIndex = ProtoCore.DSASM.Constants.kInvalidIndex; if (parentNode != null && parentNode is ProtoCore.AST.AssociativeAST.IdentifierListNode) { ProtoCore.AST.Node leftnode = (parentNode as ProtoCore.AST.AssociativeAST.IdentifierListNode).LeftNode; if (leftnode != null && leftnode is ProtoCore.AST.AssociativeAST.IdentifierNode) { refClassIndex = compileStateTracker.ClassTable.IndexOf(leftnode.Name); } } // Check for the actual method, not the dot method // If lefttype is a valid class then check if calling a constructor if ((int)ProtoCore.PrimitiveType.kInvalidType != inferedType.UID && (int)ProtoCore.PrimitiveType.kTypeVoid != inferedType.UID && procName != ProtoCore.DSASM.Constants.kFunctionPointerCall) { bool isAccessible; int realType; bool isStaticOrConstructor = refClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex; procNode = compileStateTracker.ClassTable.ClassNodes[inferedType.UID].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out realType, isStaticOrConstructor); if (procNode != null) { Debug.Assert(realType != ProtoCore.DSASM.Constants.kInvalidIndex); type = lefttype = realType; if (!isAccessible) { type = lefttype = realType; procNode = null; string message = String.Format(ProtoCore.BuildData.WarningMessage.kMethodIsInaccessible, procName); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kAccessViolation, message, compileStateTracker.CurrentDSFileName, funcCall.line, funcCall.col); inferedType.UID = (int)PrimitiveType.kTypeNull; EmitPushNull(); return procNode; } } } // Try function pointer firstly if ((procNode == null) && (procName != ProtoCore.DSASM.Constants.kFunctionPointerCall)) { bool isAccessibleFp; ProtoCore.DSASM.SymbolNode symbolnode = null; bool isAllocated = VerifyAllocation(procName, globalClassIndex, globalProcIndex, out symbolnode, out isAccessibleFp); if (isAllocated) // not checking the type against function pointer, as the type could be var { procName = ProtoCore.DSASM.Constants.kFunctionPointerCall; // The graph node always depends on this function pointer if (null != graphNode) { ProtoCore.AssociativeGraph.GraphNode dependentNode = new ProtoCore.AssociativeGraph.GraphNode(); dependentNode.PushSymbolReference(symbolnode); graphNode.PushDependent(dependentNode); } } } // Always try global function firstly. Because we dont have syntax // support for calling global function (say, ::foo()), if we try // member function firstly, there is no way to call a global function // For member function, we can use this.foo() to distinguish it from // global function. if ((procNode == null) && (procName != ProtoCore.DSASM.Constants.kFunctionPointerCall)) { procNode = compileStateTracker.GetFirstVisibleProcedure(procName, arglist, codeBlock); if (null != procNode) { type = ProtoCore.DSASM.Constants.kGlobalScope; if (compileStateTracker.TypeSystem.IsHigherRank(procNode.returntype.UID, inferedType.UID)) { inferedType = procNode.returntype; } } } // Try member functions in global class scope if ((procNode == null) && (procName != ProtoCore.DSASM.Constants.kFunctionPointerCall) && (parentNode == null)) { if (globalClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex) { int realType; bool isAccessible; bool isStaticOrConstructor = refClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex; ProtoCore.DSASM.ProcedureNode memProcNode = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out realType, isStaticOrConstructor); if (memProcNode != null) { Debug.Assert(realType != ProtoCore.DSASM.Constants.kInvalidIndex); procNode = memProcNode; inferedType = procNode.returntype; type = realType; if (!isAccessible) { string message = String.Format(ProtoCore.BuildData.WarningMessage.kMethodIsInaccessible, procName); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kAccessViolation, message, compileStateTracker.CurrentDSFileName, funcCall.line, funcCall.col); inferedType.UID = (int)PrimitiveType.kTypeNull; EmitPushNull(); return procNode; } } } } if (null != procNode) { if (procNode.isConstructor && (globalClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex) && (globalProcIndex != ProtoCore.DSASM.Constants.kInvalidIndex) && (globalClassIndex == inferedType.UID)) { ProtoCore.DSASM.ProcedureNode contextProcNode = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].vtable.procList[globalProcIndex]; if (contextProcNode.isConstructor && string.Equals(contextProcNode.name, procNode.name) && contextProcNode.runtimeIndex == procNode.runtimeIndex) { string message = String.Format(ProtoCore.BuildData.WarningMessage.kCallingConstructorInConstructor, procName); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kCallingConstructorInConstructor, message, compileStateTracker.CurrentDSFileName, node.line, node.col ); inferedType.UID = (int)PrimitiveType.kTypeNull; EmitPushNull(); return procNode; } } inferedType = procNode.returntype; //if call is replication call if (procNode.isThisCallReplication) { inferedType.IsIndexable = true; inferedType.rank++; } if (ProtoCore.DSASM.Constants.kInvalidIndex != procNode.procId) { // // ==============Establishing graphnode links in modified arguments============= // // proc TraverseCall(node, graphnode) // ; Get the first procedure, this will only be the first visible procedure // ; Overloads will be handled at runtime // def fnode = getProcedure(node) // // ; For every argument in the function call, // ; attach the modified property list and append it to the graphnode update list // foreach arg in node.args // if fnode.updatedArgProps is not null // def noderef = arg.ident (or identlist) // noderef.append(fnode.updatedArgProps) // graphnode.pushUpdateRef(noderef) // end // end // end // // ============================================================================= // foreach (AssociativeNode paramNode in funcCall.FormalArguments) { // Get the lhs symbol list ProtoCore.Type ltype = new ProtoCore.Type(); ltype.UID = globalClassIndex; ProtoCore.AssociativeGraph.UpdateNodeRef argNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef(); DFSGetSymbolList(paramNode, ref ltype, argNodeRef); if (null != graphNode) { graphNode.updatedArguments.Add(argNodeRef); } } // The function is at block 0 if its a constructor, member or at the globals scope. // Its at block 1 if its inside a language block. // Its limited to block 1 as of R1 since we dont support nested function declarations yet int blockId = procNode.runtimeIndex; //push value-not-provided default argument for (int i = arglist.Count; i < procNode.argInfoList.Count; i++) { EmitDefaultArgNode(); } // Push the function declaration block and indexed array // Jun TODO: Implementeation of indexing into a function call: // x = f()[0][1] int dimensions = 0; EmitPushVarData(blockId, dimensions); // The function call EmitInstrConsole(ProtoCore.DSASM.kw.callr, procNode.name); // Do not emit breakpoints at built-in methods like _add/_sub etc. - pratapa if (procNode.isAssocOperator || procNode.name.Equals(ProtoCore.DSASM.Constants.kInlineConditionalMethodName)) { EmitCall(procNode.procId, type, depth, ProtoCore.DSASM.Constants.kInvalidIndex, ProtoCore.DSASM.Constants.kInvalidIndex, ProtoCore.DSASM.Constants.kInvalidIndex, ProtoCore.DSASM.Constants.kInvalidIndex, procNode.pc); } // Break at function call inside dynamic lang block created for a 'true' or 'false' expression inside an inline conditional else if (compileStateTracker.DebugProps.breakOptions.HasFlag(DebugProperties.BreakpointOptions.EmitInlineConditionalBreakpoint)) { Validity.Assert(compileStateTracker.DebugProps.highlightRange != null); ProtoCore.CodeModel.CodePoint startInclusive = compileStateTracker.DebugProps.highlightRange.StartInclusive; ProtoCore.CodeModel.CodePoint endExclusive = compileStateTracker.DebugProps.highlightRange.EndExclusive; EmitCall(procNode.procId, type, depth, startInclusive.LineNo, startInclusive.CharNo, endExclusive.LineNo, endExclusive.CharNo, procNode.pc); } // Use startCol and endCol of binary expression node containing function call except if it's a setter else if (bnode != null && !procNode.name.StartsWith(Constants.kSetterPrefix)) { EmitCall(procNode.procId, type, depth, bnode.line, bnode.col, bnode.endLine, bnode.endCol, procNode.pc); } else { EmitCall(procNode.procId, type, depth, funcCall.line, funcCall.col, funcCall.endLine, funcCall.endCol, procNode.pc); } // The function return value EmitInstrConsole(ProtoCore.DSASM.kw.push, ProtoCore.DSASM.kw.regRX); ProtoCore.DSASM.StackValue opReturn = new ProtoCore.DSASM.StackValue(); opReturn.optype = ProtoCore.DSASM.AddressType.Register; opReturn.opdata = (int)ProtoCore.DSASM.Registers.RX; EmitPush(opReturn); if (dotCallType.UID != (int)PrimitiveType.kTypeVar) { inferedType.UID = dotCallType.UID; } } } else { if (depth <= 0 && procName != ProtoCore.DSASM.Constants.kFunctionPointerCall) { string property; if (CoreUtils.TryGetPropertyName(procName, out property)) { string message = String.Format(ProtoCore.BuildData.WarningMessage.kPropertyNotFound, property); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kPropertyNotFound, message, compileStateTracker.CurrentDSFileName, funcCall.line, funcCall.col); } else { string message = String.Format(ProtoCore.BuildData.WarningMessage.kMethodNotFound, procName); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kFunctionNotFound, message, compileStateTracker.CurrentDSFileName, funcCall.line, funcCall.col); } inferedType.UID = (int)PrimitiveType.kTypeNull; EmitPushNull(); } else { if (procName == ProtoCore.DSASM.Constants.kFunctionPointerCall && depth == 0) { ProtoCore.DSASM.DynamicFunctionNode dynamicFunctionNode = new ProtoCore.DSASM.DynamicFunctionNode(procName, arglist, lefttype); compileStateTracker.DynamicFunctionTable.functionTable.Add(dynamicFunctionNode); var iNode = nodeBuilder.BuildIdentfier(funcCall.Function.Name); EmitIdentifierNode(iNode, ref inferedType); } else { ProtoCore.DSASM.DynamicFunctionNode dynamicFunctionNode = new ProtoCore.DSASM.DynamicFunctionNode(funcCall.Function.Name, arglist, lefttype); compileStateTracker.DynamicFunctionTable.functionTable.Add(dynamicFunctionNode); } // The function call EmitInstrConsole(ProtoCore.DSASM.kw.callr, funcCall.Function.Name + "[dynamic]"); EmitDynamicCall(compileStateTracker.DynamicFunctionTable.functionTable.Count - 1, globalClassIndex, depth, funcCall.line, funcCall.col, funcCall.endLine, funcCall.endCol); // The function return value EmitInstrConsole(ProtoCore.DSASM.kw.push, ProtoCore.DSASM.kw.regRX); ProtoCore.DSASM.StackValue opReturn = new ProtoCore.DSASM.StackValue(); opReturn.optype = ProtoCore.DSASM.AddressType.Register; opReturn.opdata = (int)ProtoCore.DSASM.Registers.RX; EmitPush(opReturn); //assign inferedType to var inferedType.UID = (int)PrimitiveType.kTypeVar; } } return procNode; }
public UpdateNodeRef(UpdateNodeRef rhs) { nodeList = new List<UpdateNode>(); if (null != rhs && null != rhs.nodeList) { foreach (UpdateNode node in rhs.nodeList) { PushUpdateNode(node); } } }
private ProtoCore.AssociativeGraph.UpdateNodeRef AutoGenerateUpdateReference(AssociativeNode node, ProtoCore.AssociativeGraph.GraphNode graphNode) { // Get the lhs symbol list ProtoCore.Type type = new ProtoCore.Type(); type.UID = globalClassIndex; ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef(); DFSGetSymbolList(node, ref type, leftNodeRef); // Auto-generate the updateNodeRefs for this graphnode given the list // stored in the first procedure found in the assignment expression if (functionCallStack.Count > 0) { ProtoCore.DSASM.ProcedureNode firstProc = functionCallStack[0]; if (!firstProc.isAutoGenerated) { foreach (ProtoCore.AssociativeGraph.UpdateNodeRef updateRef in firstProc.updatedProperties) { ProtoCore.AssociativeGraph.UpdateNodeRef autogenRef = leftNodeRef; autogenRef.PushUpdateNodeRef(updateRef); graphNode.updateNodeRefList.Add(autogenRef); } graphNode.firstProc = firstProc; } } ProtoCore.DSASM.SymbolNode firstSymbol = null; // See if the leftmost symbol(updateNodeRef) of the lhs expression is a property of the current class. // If it is, then push the lhs updateNodeRef to the list of modified properties in the procedure node if (null != localProcedure && leftNodeRef.nodeList.Count > 0) { firstSymbol = leftNodeRef.nodeList[0].symbol; if (null != firstSymbol && leftNodeRef.nodeList[0].nodeType != ProtoCore.AssociativeGraph.UpdateNodeType.kMethod) { if (firstSymbol.functionIndex == ProtoCore.DSASM.Constants.kGlobalScope) { // Does the symbol belong on the same class or class heirarchy as the function calling it if (firstSymbol.classScope == localProcedure.classScope) { localProcedure.updatedProperties.Push(leftNodeRef); } else { if (localProcedure.classScope > 0) { if (compileStateTracker.ClassTable.ClassNodes[localProcedure.classScope].IsMyBase(firstSymbol.classScope)) { localProcedure.updatedProperties.Push(leftNodeRef); } } } } } } return leftNodeRef; }
// // proc ResolveFinalNodeRefs() // foreach graphnode in graphnodeList // def firstproc = graphnode.firstproc // // Auto-generate the updateNodeRefs for this graphnode given the // // list stored in the first procedure found in the assignment expression // foreach noderef in firstProc.updatedProperties // def n = graphnode.firstProcRefIndex // def autogenRef = updateNodeRef[n] // autogenRef.append(noderef) // graphnode.pushUpdateRef(autogenRef) // end // end // end // private void ResolveFinalNodeRefs() { foreach (ProtoCore.AssociativeGraph.GraphNode graphNode in codeBlock.instrStream.dependencyGraph.GraphList) { ProtoCore.DSASM.ProcedureNode firstProc = graphNode.firstProc; if (null == firstProc || firstProc.isAutoGenerated) { continue; } // TODO: The following implementation is wrong. // Suppose for function call: x = foo().bar(); which converted // to x = %dot(foo(), bar(), ...); the following checking skips // it because %dot() is an internal function. -Yu Ke // Do this only for non auto-generated function calls //if any local var is depend on global var if (compileStateTracker.Options.localDependsOnGlobalSet) { if (!firstProc.name.ToCharArray()[0].Equals('_') && !firstProc.name.ToCharArray()[0].Equals('%')) { //for each node foreach (ProtoCore.AssociativeGraph.GraphNode gNode in codeBlock.instrStream.dependencyGraph.GraphList) { if (gNode.updateNodeRefList != null && gNode.updateNodeRefList.Count != 0) { if (gNode.procIndex == firstProc.procId && !gNode.updateNodeRefList[0].nodeList[0].symbol.name.ToCharArray()[0].Equals('%')) { foreach (ProtoCore.AssociativeGraph.GraphNode dNode in gNode.dependentList) { if (dNode.procIndex == ProtoCore.DSASM.Constants.kGlobalScope) { if (!dNode.updateNodeRefList[0].nodeList[0].symbol.name.ToCharArray()[0].Equals('%')) { graphNode.PushDependent(dNode); } } } } } } } } // For each property modified foreach (ProtoCore.AssociativeGraph.UpdateNodeRef updateRef in firstProc.updatedProperties) { int index = graphNode.firstProcRefIndex; // Is it a global function if (ProtoCore.DSASM.Constants.kGlobalScope == firstProc.classScope) { graphNode.updateNodeRefList.AddRange(firstProc.updatedGlobals); } else if (ProtoCore.DSASM.Constants.kInvalidIndex != index && ProtoCore.DSASM.Constants.kGlobalScope != firstProc.classScope) { foreach (ProtoCore.AssociativeGraph.GraphNode dependent in graphNode.dependentList) { // Do this only if first proc is a member function... ProtoCore.AssociativeGraph.UpdateNodeRef autogenRef = new ProtoCore.AssociativeGraph.UpdateNodeRef(dependent.updateNodeRefList[0]); autogenRef = autogenRef.GetUntilFirstProc(); // ... and the first symbol is an instance of a user-defined type int last = autogenRef.nodeList.Count - 1; Validity.Assert(autogenRef.nodeList[last].nodeType != ProtoCore.AssociativeGraph.UpdateNodeType.kMethod && null != autogenRef.nodeList[last].symbol); if (autogenRef.nodeList[last].symbol.datatype.UID >= (int)PrimitiveType.kMaxPrimitives) { autogenRef.PushUpdateNodeRef(updateRef); graphNode.updateNodeRefList.Add(autogenRef); } } } } if (graphNode.updatedArguments.Count > 0) { // For each argument modified int n = 0; // Create the current modified argument foreach (KeyValuePair<string, List<ProtoCore.AssociativeGraph.UpdateNodeRef>> argNameModifiedStatementsPair in firstProc.updatedArgumentProperties) { // For every single arguments' modified statements foreach (ProtoCore.AssociativeGraph.UpdateNodeRef nodeRef in argNameModifiedStatementsPair.Value) { ProtoCore.AssociativeGraph.UpdateNodeRef argNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef(); argNodeRef.PushUpdateNodeRef(graphNode.updatedArguments[n]); argNodeRef.PushUpdateNodeRef(nodeRef); graphNode.updateNodeRefList.Add(argNodeRef); } ++n; } } } }
public UpdateNodeRef GetUntilFirstProc() { Validity.Assert(null != nodeList); UpdateNodeRef newRef = new UpdateNodeRef(); foreach (UpdateNode node in nodeList) { if (node.nodeType != UpdateNodeType.kMethod) { newRef.nodeList.Add(node); } } return newRef; }
public override ProcedureNode TraverseFunctionCall( ProtoCore.AST.Node node, ProtoCore.AST.Node parentNode, int lefttype, int depth, ref ProtoCore.Type inferedType, GraphNode graphNode = null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone, ProtoCore.AST.Node bnode = null) { ProcedureNode procNode = null; if (node is FunctionDotCallNode) { procNode = TraverseDotFunctionCall(node, parentNode, lefttype, depth, graphNode, subPass, bnode as BinaryExpressionNode, ref inferedType); if (graphNode != null && procNode != null) { GenerateCallsiteIdentifierForGraphNode(graphNode, procNode.Name); } return procNode; } var arglist = new List<ProtoCore.Type>(); var funcCall = node as FunctionCallNode; var procName = funcCall.Function.Name; int classIndex = core.ClassTable.IndexOf(procName); // To support unamed constructor if (classIndex != Constants.kInvalidIndex) { bool isAccessible; int dummy; ProcedureNode constructor = core.ClassTable.ClassNodes[classIndex].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out dummy, true); if (constructor != null && constructor.IsConstructor) { var rhsFNode = node as FunctionCallNode; var classNode = AstFactory.BuildIdentifier(procName); var dotCallNode = CoreUtils.GenerateCallDotNode(classNode, rhsFNode, core); procNode = TraverseDotFunctionCall(dotCallNode, parentNode, lefttype, depth, graphNode, subPass, bnode as BinaryExpressionNode, ref inferedType); if (graphNode != null && procNode != null) { GenerateCallsiteIdentifierForGraphNode(graphNode, procNode.Name); } return procNode; } } foreach (AssociativeNode paramNode in funcCall.FormalArguments) { var paramType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, 0); // The range expression function does not need replication guides emitReplicationGuide = !procName.Equals(Constants.kFunctionRangeExpression) && !CoreUtils.IsGetterSetter(procName); // If it's a binary node then continue type check, otherwise // disable type check and just take the type of paramNode itself // f(1+2.0) -> type check enabled - param is typed as double // f(2) -> type check disabled - param is typed as int enforceTypeCheck = !(paramNode is BinaryExpressionNode); DfsTraverse(paramNode, ref paramType, false, graphNode, subPass, bnode); emitReplicationGuide = false; enforceTypeCheck = true; arglist.Add(paramType); } if (subPass == ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier) { return null; } int refClassIndex = Constants.kInvalidIndex; if (parentNode != null && parentNode is IdentifierListNode) { var leftnode = (parentNode as IdentifierListNode).LeftNode; if (leftnode != null && leftnode is IdentifierNode) { refClassIndex = core.ClassTable.IndexOf(leftnode.Name); } } int type = Constants.kInvalidIndex; // Check for the actual method, not the dot method // If lefttype is a valid class then check if calling a constructor if ((int)PrimitiveType.kInvalidType != inferedType.UID && (int)PrimitiveType.kTypeVoid != inferedType.UID && procName != Constants.kFunctionPointerCall) { bool isAccessible; int realType; bool isStaticOrConstructor = refClassIndex != Constants.kInvalidIndex; procNode = core.ClassTable.ClassNodes[inferedType.UID].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out realType, isStaticOrConstructor); if (procNode != null) { Validity.Assert(realType != Constants.kInvalidIndex); type = lefttype = realType; if (!isAccessible) { type = lefttype = realType; procNode = null; string message = String.Format(ProtoCore.Properties.Resources.kMethodIsInaccessible, procName); buildStatus.LogWarning(WarningID.kAccessViolation, message, core.CurrentDSFileName, funcCall.line, funcCall.col, graphNode); inferedType.UID = (int)PrimitiveType.kTypeNull; EmitPushNull(); if (graphNode != null && procNode != null) { GenerateCallsiteIdentifierForGraphNode(graphNode, procNode.Name); } return procNode; } } } // Try function pointer firstly if ((procNode == null) && (procName != ProtoCore.DSASM.Constants.kFunctionPointerCall)) { bool isAccessibleFp; SymbolNode symbolnode = null; bool isAllocated = VerifyAllocation(procName, globalClassIndex, globalProcIndex, out symbolnode, out isAccessibleFp); if (isAllocated) { // The graph node always depends on this function pointer if (null != graphNode) { PushSymbolAsDependent(symbolnode, graphNode); GenerateCallsiteIdentifierForGraphNode(graphNode, procName); } // not checking the type against function pointer, as the // type could be var procName = Constants.kFunctionPointerCall; } } // Always try global function firstly. Because we dont have syntax // support for calling global function (say, ::foo()), if we try // member function firstly, there is no way to call a global function // For member function, we can use this.foo() to distinguish it from // global function. if ((procNode == null) && (procName != Constants.kFunctionPointerCall)) { procNode = CoreUtils.GetFunctionBySignature(procName, arglist, codeBlock); if (null != procNode) { type = ProtoCore.DSASM.Constants.kGlobalScope; if (core.TypeSystem.IsHigherRank(procNode.ReturnType.UID, inferedType.UID)) { inferedType = procNode.ReturnType; } } } // Try member functions in global class scope if ((procNode == null) && (procName != Constants.kFunctionPointerCall) && (parentNode == null)) { if (globalClassIndex != Constants.kInvalidIndex) { int realType; bool isAccessible; bool isStaticOrConstructor = refClassIndex != Constants.kInvalidIndex; ProtoCore.DSASM.ProcedureNode memProcNode = core.ClassTable.ClassNodes[globalClassIndex].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out realType, isStaticOrConstructor); if (memProcNode != null) { Validity.Assert(realType != Constants.kInvalidIndex); procNode = memProcNode; inferedType = procNode.ReturnType; type = realType; if (!isAccessible) { string message = String.Format(ProtoCore.Properties.Resources.kMethodIsInaccessible, procName); buildStatus.LogWarning(WarningID.kAccessViolation, message, core.CurrentDSFileName, funcCall.line, funcCall.col, graphNode); inferedType.UID = (int)PrimitiveType.kTypeNull; EmitPushNull(); if (graphNode != null && procNode != null) { GenerateCallsiteIdentifierForGraphNode(graphNode, procNode.Name); } return procNode; } } } } if (null != procNode) { if (procNode.IsConstructor && (globalClassIndex != Constants.kInvalidIndex) && (globalProcIndex != Constants.kInvalidIndex) && (globalClassIndex == inferedType.UID)) { ProcedureNode contextProcNode = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Procedures[globalProcIndex]; if (contextProcNode.IsConstructor && string.Equals(contextProcNode.Name, procNode.Name) && contextProcNode.RuntimeIndex == procNode.RuntimeIndex) { string message = String.Format(ProtoCore.Properties.Resources.kCallingConstructorInConstructor, procName); buildStatus.LogWarning(WarningID.kCallingConstructorInConstructor, message, core.CurrentDSFileName, node.line, node.col, graphNode); inferedType.UID = (int)PrimitiveType.kTypeNull; EmitPushNull(); if (graphNode != null && procNode != null) { GenerateCallsiteIdentifierForGraphNode(graphNode, procNode.Name); } return procNode; } } inferedType = procNode.ReturnType; if (procNode.ID != Constants.kInvalidIndex) { foreach (AssociativeNode paramNode in funcCall.FormalArguments) { // Get the lhs symbol list ProtoCore.Type ltype = new ProtoCore.Type(); ltype.UID = globalClassIndex; UpdateNodeRef argNodeRef = new UpdateNodeRef(); DFSGetSymbolList(paramNode, ref ltype, argNodeRef); if (null != graphNode) { if (argNodeRef.nodeList.Count > 0) { graphNode.updatedArguments.Add(argNodeRef); } } } // The function is at block 0 if its a constructor, member // or at the globals scope. Its at block 1 if its inside a // language block. Its limited to block 1 as of R1 since we // dont support nested function declarations yet int blockId = procNode.RuntimeIndex; //push value-not-provided default argument for (int i = arglist.Count; i < procNode.ArgumentInfos.Count; i++) { EmitDefaultArgNode(); } // Push the function declaration block and indexed array // Jun TODO: Implementeation of indexing into a function call: // x = f()[0][1] int dimensions = 0; EmitPushVarData(dimensions); // Emit depth EmitInstrConsole(kw.push, depth + "[depth]"); EmitPush(StackValue.BuildInt(depth)); // The function call EmitInstrConsole(kw.callr, procNode.Name); // Do not emit breakpoints at built-in methods like _add/_sub etc. - pratapa if (procNode.IsAssocOperator || procNode.Name.Equals(Constants.kInlineConditionalMethodName)) { EmitCall(procNode.ID, blockId, type, Constants.kInvalidIndex, Constants.kInvalidIndex, Constants.kInvalidIndex, Constants.kInvalidIndex, procNode.PC); } // Break at function call inside dynamic lang block created for a 'true' or 'false' expression inside an inline conditional else if (core.DebuggerProperties.breakOptions.HasFlag(DebugProperties.BreakpointOptions.EmitInlineConditionalBreakpoint)) { var codeRange = core.DebuggerProperties.highlightRange; var startInclusive = codeRange.StartInclusive; var endExclusive = codeRange.EndExclusive; EmitCall(procNode.ID, blockId, type, startInclusive.LineNo, startInclusive.CharNo, endExclusive.LineNo, endExclusive.CharNo, procNode.PC); } // Use startCol and endCol of binary expression node containing function call except if it's a setter else if (bnode != null && !procNode.Name.StartsWith(Constants.kSetterPrefix)) { EmitCall(procNode.ID, blockId, type, bnode.line, bnode.col, bnode.endLine, bnode.endCol, procNode.PC); } else { EmitCall(procNode.ID, blockId, type, funcCall.line, funcCall.col, funcCall.endLine, funcCall.endCol, procNode.PC); } // The function return value EmitInstrConsole(kw.push, kw.regRX); StackValue opReturn = StackValue.BuildRegister(Registers.RX); EmitPush(opReturn); } } else { if (depth <= 0 && procName != ProtoCore.DSASM.Constants.kFunctionPointerCall) { string property; if (CoreUtils.TryGetPropertyName(procName, out property)) { string message = String.Format(ProtoCore.Properties.Resources.kPropertyNotFound, property); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kPropertyNotFound, message, core.CurrentDSFileName, funcCall.line, funcCall.col, graphNode); } else { string message = String.Format(ProtoCore.Properties.Resources.kMethodNotFound, procName); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kFunctionNotFound, message, core.CurrentDSFileName, funcCall.line, funcCall.col, graphNode); } inferedType.UID = (int)PrimitiveType.kTypeNull; EmitPushNull(); } else { DynamicFunction dynFunc = null; if (procName == Constants.kFunctionPointerCall && depth == 0) { if (!core.DynamicFunctionTable.TryGetFunction(procName, arglist.Count, lefttype, out dynFunc)) { dynFunc = core.DynamicFunctionTable.AddNewFunction(procName, arglist.Count, lefttype); } var iNode =AstFactory.BuildIdentifier(funcCall.Function.Name); EmitIdentifierNode(iNode, ref inferedType); } else { if (!core.DynamicFunctionTable.TryGetFunction(procName, arglist.Count, lefttype, out dynFunc)) { dynFunc = core.DynamicFunctionTable.AddNewFunction(procName, arglist.Count, lefttype); } } // Emit depth EmitInstrConsole(kw.push, depth + "[depth]"); EmitPush(StackValue.BuildInt(depth)); // The function call EmitInstrConsole(kw.callr, funcCall.Function.Name + "[dynamic]"); EmitDynamicCall(dynFunc.Index, globalClassIndex, funcCall.line, funcCall.col, funcCall.endLine, funcCall.endCol); // The function return value EmitInstrConsole(kw.push, kw.regRX); StackValue opReturn = StackValue.BuildRegister(Registers.RX); EmitPush(opReturn); //assign inferedType to var inferedType.UID = (int)PrimitiveType.kTypeVar; } } if (graphNode != null && procNode != null) { GenerateCallsiteIdentifierForGraphNode(graphNode, procNode.Name); } return procNode; }
public bool IsEqual(UpdateNodeRef rhs) { if (nodeList.Count != rhs.nodeList.Count) { return false; } for (int n = 0; n < nodeList.Count; ++n) { if (nodeList[n].dimensionNodeList.Count != rhs.nodeList[n].dimensionNodeList.Count) { return false; } else if (nodeList[n].dimensionNodeList.Count != 0) { for (int m = 0; m < nodeList[n].dimensionNodeList.Count; m++) { if (nodeList[n].dimensionNodeList[m].symbol.name != rhs.nodeList[n].dimensionNodeList[m].symbol.name) { return false; } } } if (!nodeList[n].IsEqual(rhs.nodeList[n])) { return false; } } return true; }
// // proc TraverseFunctionDef(node) // ... // def argList // foreach arg in node.argdefinition // ; Store not just the argument types, but also the argument identifier // def argtype = buildtype(arg) // argtype.name = arg.identname // argList.push(argtype) // end // ... // end // private ProtoCore.AssociativeGraph.UpdateNodeRef __To__Deprecate__AutoGenerateUpdateArgumentReference(AssociativeNode node, ProtoCore.AssociativeGraph.GraphNode graphNode) { // Get the lhs symbol list ProtoCore.Type type = new ProtoCore.Type(); type.UID = globalClassIndex; ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef(); DFSGetSymbolList(node, ref type, leftNodeRef); ProtoCore.DSASM.SymbolNode firstSymbol = null; // Check if we are inside a procedure if (null != localProcedure) { // Check if there are at least 2 symbols in the list if (leftNodeRef.nodeList.Count >= 2) { firstSymbol = leftNodeRef.nodeList[0].symbol; if (null != firstSymbol && leftNodeRef.nodeList[0].nodeType != ProtoCore.AssociativeGraph.UpdateNodeType.kMethod) { // Now check if the first element of the identifier list is an argument foreach (ProtoCore.DSASM.ArgumentInfo argInfo in localProcedure.ArgumentInfos) { if (argInfo.Name == firstSymbol.name) { leftNodeRef.nodeList.RemoveAt(0); List<ProtoCore.AssociativeGraph.UpdateNodeRef> refList = null; bool found = localProcedure.UpdatedArgumentProperties.TryGetValue(argInfo.Name, out refList); if (found) { refList.Add(leftNodeRef); } else { refList = new List<ProtoCore.AssociativeGraph.UpdateNodeRef>(); refList.Add(leftNodeRef); localProcedure.UpdatedArgumentProperties.Add(argInfo.Name, refList); } } } } } } return leftNodeRef; }
private void BuildSSADependency(Node node, AssociativeGraph.GraphNode graphNode) { // Jun Comment: set the graphNode dependent as this identifier list ProtoCore.Type type = new ProtoCore.Type(); type.UID = globalClassIndex; ProtoCore.AssociativeGraph.UpdateNodeRef nodeRef = new AssociativeGraph.UpdateNodeRef(); DFSGetSymbolList(node, ref type, nodeRef); if (null != graphNode && nodeRef.nodeList.Count > 0) { ProtoCore.AssociativeGraph.GraphNode dependentNode = new ProtoCore.AssociativeGraph.GraphNode(); dependentNode.updateNodeRefList.Add(nodeRef); graphNode.PushDependent(dependentNode); } }
private ProtoCore.AssociativeGraph.UpdateNodeRef AutoGenerateUpdateReference(AssociativeNode node, ProtoCore.AssociativeGraph.GraphNode graphNode) { // Get the lhs symbol list ProtoCore.Type type = new ProtoCore.Type(); type.UID = globalClassIndex; ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef(); DFSGetSymbolList(node, ref type, leftNodeRef); // Auto-generate the updateNodeRefs for this graphnode given the list // stored in the first procedure found in the assignment expression if (functionCallStack.Count > 0) { ProtoCore.DSASM.ProcedureNode firstProc = functionCallStack[0]; if (!firstProc.IsAutoGenerated) { graphNode.firstProc = firstProc; } } ProtoCore.DSASM.SymbolNode firstSymbol = null; // See if the leftmost symbol(updateNodeRef) of the lhs expression is a property of the current class. // If it is, then push the lhs updateNodeRef to the list of modified properties in the procedure node if (null != localProcedure && leftNodeRef.nodeList.Count > 0) { firstSymbol = leftNodeRef.nodeList[0].symbol; // Check if this symbol being modified in this function is allocated in the current scope. // If it is, then it means this symbol is not a member and is local to this function ProtoCore.DSASM.SymbolNode symbolnode = null; bool isAccessible = false; bool isLocalVariable = VerifyAllocationInScope(firstSymbol.name, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible); if (!isLocalVariable) { if (null != firstSymbol && leftNodeRef.nodeList[0].nodeType != ProtoCore.AssociativeGraph.UpdateNodeType.kMethod) { if (firstSymbol.functionIndex == ProtoCore.DSASM.Constants.kGlobalScope) { // Does the symbol belong on the same class or class heirarchy as the function calling it if (firstSymbol.classScope == localProcedure.ClassID) { localProcedure.UpdatedProperties.Push(leftNodeRef); } else { if (localProcedure.ClassID > 0) { if (core.ClassTable.ClassNodes[localProcedure.ClassID].IsMyBase(firstSymbol.classScope)) { localProcedure.UpdatedProperties.Push(leftNodeRef); } } } } } } } return leftNodeRef; }
public UpdateNodeRef GetUntilFirstProc() { UpdateNodeRef newRef = new UpdateNodeRef(); foreach (UpdateNode node in nodeList) { if (node.nodeType != UpdateNodeType.Method) { newRef.nodeList.Add(node); } } return newRef; }