private void EmitBinaryExpressionNode(ImperativeNode node, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.AST.ImperativeAST.BinaryExpressionNode parentNode = null) { if (!IsParsingGlobal()) return; bool isBooleanOperation = false; BinaryExpressionNode b = node as BinaryExpressionNode; ProtoCore.Type leftType = new ProtoCore.Type(); leftType.UID = (int)ProtoCore.PrimitiveType.Var; ProtoCore.Type rightType = new ProtoCore.Type(); rightType.UID = (int)ProtoCore.PrimitiveType.Var; if (ProtoCore.DSASM.Operator.assign != b.Optr) { isBooleanOperation = ProtoCore.DSASM.Operator.lt == b.Optr || ProtoCore.DSASM.Operator.gt == b.Optr || ProtoCore.DSASM.Operator.le == b.Optr || ProtoCore.DSASM.Operator.ge == b.Optr || ProtoCore.DSASM.Operator.eq == b.Optr || ProtoCore.DSASM.Operator.nq == b.Optr || ProtoCore.DSASM.Operator.and == b.Optr || ProtoCore.DSASM.Operator.or == b.Optr; DfsTraverse(b.LeftNode, ref inferedType, isBooleanOperation, graphNode, ProtoCore.CompilerDefinitions.SubCompilePass.None, parentNode); if (inferedType.UID == (int)PrimitiveType.FunctionPointer && emitDebugInfo) { buildStatus.LogSemanticError(Resources.FunctionPointerNotAllowedAtBinaryExpression, core.CurrentDSFileName, b.LeftNode.line, b.LeftNode.col); } leftType.UID = inferedType.UID; leftType.rank = inferedType.rank; } else { if (b.LeftNode is IdentifierListNode) { ProtoCore.AST.Node lnode = b.LeftNode; bool isCollapsed; if (parentNode != null) { NodeUtils.SetNodeLocation(lnode, parentNode, parentNode); } else { NodeUtils.SetNodeLocation(lnode, b, b); } EmitGetterSetterForIdentList(lnode, ref inferedType, null, ProtoCore.CompilerDefinitions.SubCompilePass.None, out isCollapsed, b.RightNode); // Get the lhs symbol list ProtoCore.Type type = new ProtoCore.Type(); type.UID = globalClassIndex; ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef(); DFSGetSymbolList(lnode, ref type, leftNodeRef); // Get the first identifier symbol runtime index as it is required for the pushdep List<ProtoCore.DSASM.SymbolNode> symbolList = new List<ProtoCore.DSASM.SymbolNode>(); symbolList.Add(leftNodeRef.nodeList[0].symbol); int runtimeIndex = leftNodeRef.nodeList[0].symbol.runtimeTableIndex; // Append the rest of the symbols in the identifierlist for (int n = 1; n < leftNodeRef.nodeList.Count; ++n) { if (leftNodeRef.nodeList[n].symbol != null) symbolList.Add(leftNodeRef.nodeList[n].symbol); } EmitPushDepData(symbolList); EmitPushDep(runtimeIndex, symbolList.Count, globalClassIndex); return; } } if ((ProtoCore.DSASM.Operator.assign == b.Optr) && (b.RightNode is LanguageBlockNode)) { inferedType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.Var, 0); } if (b.RightNode == null && b.Optr == Operator.assign && b.LeftNode is IdentifierNode) { IdentifierNode t = b.LeftNode as IdentifierNode; ProtoCore.DSASM.SymbolNode symbolnode = null; bool isAccessible = false; bool hasAllocated = VerifyAllocation(t.Value, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible); if (hasAllocated) { b.RightNode = nodeBuilder.BuildIdentfier(t.Value); } else { b.RightNode = new NullNode(); } } if (parentNode != null) { DfsTraverse(b.RightNode, ref inferedType, isBooleanOperation, graphNode, ProtoCore.CompilerDefinitions.SubCompilePass.None, parentNode); } else { DfsTraverse(b.RightNode, ref inferedType, isBooleanOperation, graphNode, ProtoCore.CompilerDefinitions.SubCompilePass.None, b); } rightType.UID = inferedType.UID; rightType.rank = inferedType.rank; BinaryExpressionNode rightNode = b.RightNode as BinaryExpressionNode; if ((rightNode != null) && (ProtoCore.DSASM.Operator.assign == rightNode.Optr)) DfsTraverse(rightNode.LeftNode, ref inferedType); if (b.Optr != ProtoCore.DSASM.Operator.assign) { if (inferedType.UID == (int)PrimitiveType.FunctionPointer && emitDebugInfo) { buildStatus.LogSemanticError(Resources.FunctionPointerNotAllowedAtBinaryExpression, core.CurrentDSFileName, b.RightNode.line, b.RightNode.col); } EmitBinaryOperation(leftType, rightType, b.Optr); isBooleanOp = false; return; } if (b.LeftNode is IdentifierNode) { IdentifierNode t = b.LeftNode as IdentifierNode; ProtoCore.DSASM.SymbolNode symbolnode = null; string s = t.Value; bool isReturn = (s == ProtoCore.DSDefinitions.Keyword.Return); if (isReturn) { EmitReturnStatement(node, inferedType); } else { // check whether the variable name is a function name if (globalClassIndex != ProtoCore.DSASM.Constants.kGlobalScope) { bool isAccessibleFp; int realType; var procNode = core.ClassTable.ClassNodes[globalClassIndex].GetMemberFunction(t.Name, null, globalClassIndex, out isAccessibleFp, out realType); if (procNode != null && procNode.ID != Constants.kInvalidIndex && emitDebugInfo) { buildStatus.LogSemanticError(String.Format(Resources.FunctionAsVaribleError, t.Name), core.CurrentDSFileName, t.line, t.col); } } bool isAccessible = false; bool isAllocated = false; bool isLocalDeclaration = t.IsLocal; if (isLocalDeclaration) { isAllocated = VerifyAllocationInScope(t.Value, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible); } else { isAllocated = VerifyAllocation(t.Value, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible); } if (!string.IsNullOrEmpty(t.ArrayName) && symbolnode != null) { // if it's forloop, verify allocation with its original arrayname symbolnode.forArrayName = t.ArrayName; } int runtimeIndex = (!isAllocated) ? codeBlock.symbolTable.RuntimeIndex : symbolnode.runtimeTableIndex; // Comment Jun: Add modifeid properties into the updatedProperties list of the current function // This propagates upated of mproperties taht were modified in an imperative block if (null != localProcedure && ProtoCore.DSASM.Constants.kGlobalScope != localProcedure.ClassID) { if (isAllocated) { Validity.Assert(null != symbolnode); // Get the lhs symbol list ProtoCore.Type type = new ProtoCore.Type(); type.UID = globalClassIndex; ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef(); DFSGetSymbolList(b.LeftNode, ref type, leftNodeRef); } } int dimensions = 0; if (null != t.ArrayDimensions) { dimensions = DfsEmitArrayIndexHeap(t.ArrayDimensions); } ProtoCore.Type castType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.Var, 0); var tident = b.LeftNode as TypedIdentifierNode; if (tident != null) { int castUID = tident.DataType.UID; if ((int)PrimitiveType.InvalidType == castUID) { castUID = core.ClassTable.IndexOf(tident.DataType.Name); } if ((int)PrimitiveType.InvalidType == castUID) { string message = String.Format(ProtoCore.Properties.Resources.kTypeUndefined, tident.DataType.Name); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.TypeUndefined, message, core.CurrentDSFileName, b.line, b.col, graphNode); castType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.InvalidType, 0); castType.Name = tident.DataType.Name; castType.rank = tident.DataType.rank; } else { castType = core.TypeSystem.BuildTypeObject(castUID, tident.DataType.rank); } } if (globalClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex) { int symbol = ProtoCore.DSASM.Constants.kInvalidIndex; for (int n = 0; n < core.ClassTable.ClassNodes[globalClassIndex].Symbols.symbolList.Count; ++n) { //Fuqiang: Not a member variable if it is a local variable inside a function with the same name bool localVarInMemFunc = false; if (localProcedure != null) { if (symbolnode == null) { if (!isAllocated) // if isAllocated, inaccessible member variable { localVarInMemFunc = true; } } else if (symbolnode.functionIndex != ProtoCore.DSASM.Constants.kGlobalScope && !localProcedure.IsConstructor) { localVarInMemFunc = true; } } bool isMemberVar = ProtoCore.DSASM.Constants.kGlobalScope == core.ClassTable.ClassNodes[globalClassIndex].Symbols.symbolList[n].functionIndex && core.ClassTable.ClassNodes[globalClassIndex].Symbols.symbolList[n].name == t.Name && !localVarInMemFunc; if (isMemberVar) { if (t.ArrayDimensions == null) core.ClassTable.ClassNodes[globalClassIndex].Symbols.symbolList[n].datatype = inferedType; else if (dimensions == inferedType.rank) core.ClassTable.ClassNodes[globalClassIndex].Symbols.symbolList[n].datatype.UID = inferedType.UID; symbol = symbolnode.symbolTableIndex; break; } } if (symbol == ProtoCore.DSASM.Constants.kInvalidIndex) { if (!isAllocated) { symbolnode = Allocate(t.Name, globalProcIndex, inferedType); } symbol = symbolnode.symbolTableIndex; if (b.LeftNode is TypedIdentifierNode) { EmitCast(castType.UID, castType.rank); } if (dimensions == 0) { EmitInstrConsole(kw.pop, s); EmitPopForSymbol(symbolnode, runtimeIndex, node.line, node.col, node.endLine, node.endCol); } else { EmitPushDimensions(dimensions); EmitInstrConsole(kw.setelement, t.Name); EmitSetElement(symbolnode, runtimeIndex, node.line, node.col, node.endLine, node.endCol); } } else { if (b.LeftNode is TypedIdentifierNode) { EmitCast(castType.UID, castType.rank); } StackValue operand = symbolnode.isStatic ? StackValue.BuildStaticMemVarIndex(symbol) : StackValue.BuildMemVarIndex(symbol); if (dimensions == 0) { EmitInstrConsole(kw.popm, t.Name); EmitPopm(operand, runtimeIndex, node.line, node.col, node.endLine, node.endCol); } else { EmitPushDimensions(dimensions); EmitInstrConsole(kw.setmemelement, t.Name); EmitSetMemElement(operand, runtimeIndex, node.line, node.col, node.endLine, node.endCol); } } } else { if (!isAllocated) { symbolnode = Allocate(t.Value, globalProcIndex, inferedType); if (dimensions > 0) { symbolnode.datatype.rank = dimensions; } } else if (dimensions == 0) { if (core.TypeSystem.IsHigherRank(inferedType.UID, symbolnode.datatype.UID)) { symbolnode.datatype = inferedType; } } if (b.LeftNode is TypedIdentifierNode) { EmitCast(castType.UID, castType.rank); } if (parentNode != null) { if (dimensions == 0) { EmitInstrConsole(kw.pop, t.Value); EmitPopForSymbol(symbolnode, runtimeIndex, parentNode.line, parentNode.col, parentNode.endLine, parentNode.endCol); } else { EmitPushDimensions(dimensions); EmitInstrConsole(kw.setelement, t.Value); EmitSetElement(symbolnode, runtimeIndex); } } else { if (dimensions == 0) { EmitInstrConsole(kw.pop, t.Value); EmitPopForSymbol(symbolnode, runtimeIndex, node.line, node.col, node.endLine, node.endCol); } else { EmitPushDimensions(dimensions); EmitInstrConsole(kw.setelement, t.Value); EmitSetElement(symbolnode, runtimeIndex); } } // Check if the symbol was not here, only then it becomes a valid propagation symbol // TODO Jun: check if the symbol was allocated from an associative block if (!ProtoCore.Utils.CoreUtils.IsAutoGeneratedVar(symbolnode.name)) { if (codeBlock.symbolTable.RuntimeIndex != symbolnode.runtimeTableIndex) { List<ProtoCore.DSASM.SymbolNode> symbolList = new List<ProtoCore.DSASM.SymbolNode>(); symbolList.Add(symbolnode); EmitPushDepData(symbolList); EmitPushDep(runtimeIndex, symbolList.Count, globalClassIndex); } } } } } else if (b.LeftNode is IdentifierListNode) { // keyu: the left hand side of an assignment statement won't be an // identifier list anymore after replacing all properties (not // including the left-most property) with getters/setter. // // If this case really happens, we need to look into that. Validity.Assert(false, "The left hand of an assignment statement never will be an identifier list node"); } else { string message = "Illegal assignment (38A37EA5)"; buildStatus.LogSemanticError(message, core.CurrentDSFileName, b.line, b.col); throw new BuildHaltException(message); } if ((node as BinaryExpressionNode).Optr == Operator.assign) EmitSetExpressionUID(core.ExpressionUID++); }
private void EmitBinaryExpressionNode(ImperativeNode node, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.AST.ImperativeAST.BinaryExpressionNode parentNode = null) { if (!IsParsingGlobal() && !IsParsingGlobalFunctionBody()) return; bool isBooleanOperation = false; BinaryExpressionNode b = node as BinaryExpressionNode; ProtoCore.Type leftType = new ProtoCore.Type(); leftType.UID = (int)ProtoCore.PrimitiveType.kTypeVar; ProtoCore.Type rightType = new ProtoCore.Type(); rightType.UID = (int)ProtoCore.PrimitiveType.kTypeVar; if (ProtoCore.DSASM.Operator.assign != b.Optr) { isBooleanOperation = ProtoCore.DSASM.Operator.lt == b.Optr || ProtoCore.DSASM.Operator.gt == b.Optr || ProtoCore.DSASM.Operator.le == b.Optr || ProtoCore.DSASM.Operator.ge == b.Optr || ProtoCore.DSASM.Operator.eq == b.Optr || ProtoCore.DSASM.Operator.nq == b.Optr || ProtoCore.DSASM.Operator.and == b.Optr || ProtoCore.DSASM.Operator.or == b.Optr; DfsTraverse(b.LeftNode, ref inferedType, isBooleanOperation, graphNode, AssociativeSubCompilePass.kNone, parentNode); if (inferedType.UID == (int)PrimitiveType.kTypeFunctionPointer && emitDebugInfo) { buildStatus.LogSemanticError("Function pointer is not allowed at binary expression other than assignment!", compileStateTracker.CurrentDSFileName, b.LeftNode.line, b.LeftNode.col); } leftType.UID = inferedType.UID; leftType.IsIndexable = inferedType.IsIndexable; } else { if (b.LeftNode is IdentifierListNode) { ProtoCore.AST.Node lnode = b.LeftNode; bool isCollapsed; if (parentNode != null) { NodeUtils.SetNodeLocation(lnode, parentNode, parentNode); } else { NodeUtils.SetNodeLocation(lnode, b, b); } EmitGetterSetterForIdentList(lnode, ref inferedType, null, ProtoCore.DSASM.AssociativeSubCompilePass.kNone, out isCollapsed, b.RightNode); // Get the lhs symbol list ProtoCore.Type type = new ProtoCore.Type(); type.UID = globalClassIndex; ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef(); DFSGetSymbolList(lnode, ref type, leftNodeRef); // Get the first identifier symbol runtime index as it is required for the pushdep List<ProtoCore.DSASM.SymbolNode> symbolList = new List<ProtoCore.DSASM.SymbolNode>(); symbolList.Add(leftNodeRef.nodeList[0].symbol); int runtimeIndex = leftNodeRef.nodeList[0].symbol.runtimeTableIndex; // Append the rest of the symbols in the identifierlist for (int n = 1; n < leftNodeRef.nodeList.Count; ++n) { if (leftNodeRef.nodeList[n].symbol != null) symbolList.Add(leftNodeRef.nodeList[n].symbol); } EmitPushDepData(symbolList); EmitPushDep(runtimeIndex, symbolList.Count, globalClassIndex); return; } } // (Ayush) in case of PostFixNode, only traverse the identifier now. Post fix operation will be applied later. #if ENABLE_INC_DEC_FIX if (b.RightNode is PostFixNode) DfsTraverse((b.RightNode as PostFixNode).Identifier, ref inferedType, isBooleanOperation); else { #endif if ((ProtoCore.DSASM.Operator.assign == b.Optr) && (b.RightNode is LanguageBlockNode)) { inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeVar; inferedType.IsIndexable = false; } if (b.RightNode == null && b.Optr == Operator.assign && b.LeftNode is IdentifierNode) { IdentifierNode t = b.LeftNode as IdentifierNode; ProtoCore.DSASM.SymbolNode symbolnode = null; bool isAccessible = false; bool hasAllocated = VerifyAllocation(t.Value, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible); if (hasAllocated) { b.RightNode = nodeBuilder.BuildIdentfier(t.Value); } else { b.RightNode = new NullNode(); } } if (parentNode != null) { DfsTraverse(b.RightNode, ref inferedType, isBooleanOperation, graphNode, ProtoCore.DSASM.AssociativeSubCompilePass.kNone, parentNode); } else { DfsTraverse(b.RightNode, ref inferedType, isBooleanOperation, graphNode, ProtoCore.DSASM.AssociativeSubCompilePass.kNone, b); } #if ENABLE_INC_DEC_FIX } #endif rightType.UID = inferedType.UID; rightType.IsIndexable = inferedType.IsIndexable; BinaryExpressionNode rightNode = b.RightNode as BinaryExpressionNode; if ((rightNode != null) && (ProtoCore.DSASM.Operator.assign == rightNode.Optr)) DfsTraverse(rightNode.LeftNode, ref inferedType); if (b.Optr != ProtoCore.DSASM.Operator.assign) { if (inferedType.UID == (int)PrimitiveType.kTypeFunctionPointer && emitDebugInfo) { buildStatus.LogSemanticError("Function pointer is not allowed at binary expression other than assignment!", compileStateTracker.CurrentDSFileName, b.RightNode.line, b.RightNode.col); } EmitBinaryOperation(leftType, rightType, b.Optr); isBooleanOp = false; //if post fix, now traverse the post fix #if ENABLE_INC_DEC_FIX if (b.RightNode is PostFixNode) EmitPostFixNode(b.RightNode, ref inferedType); #endif return; } if (b.LeftNode is IdentifierNode) { IdentifierNode t = b.LeftNode as IdentifierNode; ProtoCore.DSASM.SymbolNode symbolnode = null; string s = t.Value; bool isReturn = (s == ProtoCore.DSDefinitions.Kw.kw_return); if (isReturn) { EmitReturnStatement(node, inferedType); } else { { // check whether the variable name is a function name bool isAccessibleFp; int realType; ProtoCore.DSASM.ProcedureNode procNode = null; if (globalClassIndex != ProtoCore.DSASM.Constants.kGlobalScope) { procNode = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].GetMemberFunction(t.Name, null, globalClassIndex, out isAccessibleFp, out realType); } if (procNode == null) { procNode = compileStateTracker.GetFirstVisibleProcedure(t.Name, null, codeBlock); } if (procNode != null) { if (ProtoCore.DSASM.Constants.kInvalidIndex != procNode.procId && emitDebugInfo) { buildStatus.LogSemanticError("\"" + t.Name + "\"" + "is a function and not allowed as a variable name", compileStateTracker.CurrentDSFileName, t.line, t.col); } } } bool isAccessible = false; bool isAllocated = false; // if it's forloop, verify allocation with its original arrayname if (t.ArrayName != null && !t.ArrayName.Equals("")) { isAllocated = VerifyAllocation(t.Value, t.ArrayName, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible); } else { isAllocated = VerifyAllocation(t.Value, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible); } int runtimeIndex = (!isAllocated) ? codeBlock.symbolTable.runtimeIndex : symbolnode.runtimeTableIndex; // Comment Jun: Add modifeid properties into the updatedProperties list of the current function // This propagates upated of mproperties taht were modified in an imperative block if (null != localProcedure && ProtoCore.DSASM.Constants.kGlobalScope != localProcedure.classScope) { if (isAllocated) { Validity.Assert(null != symbolnode); // Get the lhs symbol list ProtoCore.Type type = new ProtoCore.Type(); type.UID = globalClassIndex; ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef(); DFSGetSymbolList(b.LeftNode, ref type, leftNodeRef); localProcedure.updatedProperties.Push(leftNodeRef); } } // TODO Jun: Update mechanism work in progress - a flag to manually enable update bool enableUpdate = false; if (enableUpdate) { bool isExternal = false; // isAllocated && currentLangBlock != codeBlockId; //bool isAssociative = ProtoCore.Language.kAssociative == core.exeList[currentLangBlock].language; bool isAssociative = false; if (isExternal && isAssociative) { // Check if this is a modifier variable bool isVariableAModifierStack = false; if (isVariableAModifierStack) { // Check if modifying a named modifier state bool isNameModifierState = false; if (isNameModifierState) { //bool isStateIntermediate = false; } else { } //targetLangBlock = blockId; } } } int dimensions = 0; if (null != t.ArrayDimensions) { dimensions = DfsEmitArrayIndexHeap(t.ArrayDimensions); } ProtoCore.Type castType = compileStateTracker.TypeSystem.BuildTypeObject((int)PrimitiveType.kTypeVar, false); var tident = b.LeftNode as TypedIdentifierNode; if (tident != null) { int castUID = tident.datatype.UID; if ((int)PrimitiveType.kInvalidType == castUID) { castUID = compileStateTracker.ClassTable.IndexOf(tident.datatype.Name); } if ((int)PrimitiveType.kInvalidType == castUID) { string message = String.Format(ProtoCore.BuildData.WarningMessage.kTypeUndefined, tident.datatype.Name); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kTypeUndefined, message, compileStateTracker.CurrentDSFileName, b.line, b.col); castType = compileStateTracker.TypeSystem.BuildTypeObject((int)PrimitiveType.kInvalidType, false); castType.Name = tident.datatype.Name; castType.rank = tident.datatype.rank; castType.IsIndexable = (castType.rank != 0); } else { castType = compileStateTracker.TypeSystem.BuildTypeObject(castUID, tident.datatype.IsIndexable, tident.datatype.rank); } } if (globalClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex) { int symbol = ProtoCore.DSASM.Constants.kInvalidIndex; for (int n = 0; n < compileStateTracker.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList.Count; ++n) { //Fuqiang: Not a member variable if it is a local variable inside a function with the same name bool localVarInMemFunc = false; if (localProcedure != null) { if (symbolnode == null) { if (!isAllocated) // if isAllocated, inaccessible member variable { localVarInMemFunc = true; } } else if (symbolnode.functionIndex != ProtoCore.DSASM.Constants.kGlobalScope && !localProcedure.isConstructor) { localVarInMemFunc = true; } } bool isMemberVar = ProtoCore.DSASM.Constants.kGlobalScope == compileStateTracker.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList[n].functionIndex && compileStateTracker.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList[n].name == t.Name && !localVarInMemFunc; if (isMemberVar) { if (t.ArrayDimensions == null) compileStateTracker.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList[n].datatype = inferedType; else if (dimensions == inferedType.rank) compileStateTracker.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList[n].datatype.UID = inferedType.UID; symbol = symbolnode.symbolTableIndex; break; } } if (symbol == ProtoCore.DSASM.Constants.kInvalidIndex) { if (!isAllocated) { symbolnode = Allocate(t.Name, globalProcIndex, inferedType); } symbol = symbolnode.symbolTableIndex; if (b.LeftNode is TypedIdentifierNode) { symbolnode.SetStaticType(castType); } castType = symbolnode.staticType; EmitPushVarData(runtimeIndex, dimensions, castType.UID, castType.rank); EmitInstrConsole(ProtoCore.DSASM.kw.pop, s); ProtoCore.DSASM.StackValue operand = new ProtoCore.DSASM.StackValue(); operand.optype = ProtoCore.DSASM.AddressType.VarIndex; operand.opdata = symbol; EmitPop(operand, symbolnode.classScope, node.line, node.col, node.endLine, node.endCol); } else { if (b.LeftNode is TypedIdentifierNode) { symbolnode.SetStaticType(castType); } castType = symbolnode.staticType; EmitPushVarData(runtimeIndex, dimensions, castType.UID, castType.rank); EmitInstrConsole(ProtoCore.DSASM.kw.popm, t.Name); ProtoCore.DSASM.StackValue operand = new ProtoCore.DSASM.StackValue(); operand.optype = symbolnode.isStatic ? ProtoCore.DSASM.AddressType.StaticMemVarIndex : ProtoCore.DSASM.AddressType.MemVarIndex; operand.opdata = symbol; EmitPopm(operand, node.line, node.col, node.endLine, node.endCol); } } else { if (!isAllocated) { symbolnode = Allocate(t.Value, globalProcIndex, inferedType); if (dimensions > 0) { symbolnode.datatype.rank = dimensions; } } else if (dimensions == 0) { if (compileStateTracker.TypeSystem.IsHigherRank(inferedType.UID, symbolnode.datatype.UID)) { symbolnode.datatype = inferedType; } } if (b.LeftNode is TypedIdentifierNode) { symbolnode.SetStaticType(castType); } castType = symbolnode.staticType; EmitPushVarData(runtimeIndex, dimensions, castType.UID, castType.rank); EmitInstrConsole(ProtoCore.DSASM.kw.pop, t.Value); if (parentNode != null) { EmitPopForSymbol(symbolnode, parentNode.line, parentNode.col, parentNode.endLine, parentNode.endCol); } else { EmitPopForSymbol(symbolnode, node.line, node.col, node.endLine, node.endCol); } // Check if the symbol was not here, only then it becomes a valid propagation symbol // TODO Jun: check if the symbol was allocated from an associative block if (!ProtoCore.Utils.CoreUtils.IsAutoGeneratedVar(symbolnode.name)) { if (codeBlock.symbolTable.runtimeIndex != symbolnode.runtimeTableIndex) { List<ProtoCore.DSASM.SymbolNode> symbolList = new List<ProtoCore.DSASM.SymbolNode>(); symbolList.Add(symbolnode); EmitPushDepData(symbolList); EmitPushDep(runtimeIndex, symbolList.Count, globalClassIndex); } } } } } else if (b.LeftNode is IdentifierListNode) { // keyu: the left hand side of an assignment statement won't be an // identifier list anymore after replacing all properties (not // including the left-most property) with getters/setter. // // If this case really happens, we need to look into that. Debug.Assert(false, "The left hand of an assignment statement never will be an identifier list node"); /* int depth = 0; ProtoCore.Type lastType = new ProtoCore.Type(); lastType.UID = (int)PrimitiveType.kInvalidType; lastType.IsIndexable = false; bool isFirstIdent = false; bool isIdentReference = DfsEmitIdentList(b.LeftNode, b, globalClassIndex, ref lastType, ref depth, ref inferedType, true, ref isFirstIdent); inferedType.UID = isBooleanOp ? (int)PrimitiveType.kTypeBool : inferedType.UID; if (!isIdentReference) { buildStatus.LogSemanticError("The left hand side of an operation cannot be a function call", core.CurrentDSFileName, b.LeftNode.line, b.LeftNode.col); throw new BuildHaltException(); } EmitInstrConsole(ProtoCore.DSASM.kw.poplist, depth.ToString(), globalClassIndex.ToString()); // TODO Jun: Get blockid int blockId = 0; EmitPopList(depth, globalClassIndex, blockId, node.line, node.col, node.endLine, node.endCol); */ } else { string message = "Illegal assignment (38A37EA5)"; buildStatus.LogSemanticError(message, compileStateTracker.CurrentDSFileName, b.line, b.col); throw new BuildHaltException(message); } if ((node as BinaryExpressionNode).Optr == Operator.assign) EmitSetExpressionUID(compileStateTracker.ExpressionUID++); //if post fix, now traverse the post fix #if ENABLE_INC_DEC_FIX if (b.RightNode is PostFixNode) EmitPostFixNode(b.RightNode, ref inferedType); #endif }
public bool DependsOn(ProtoCore.AssociativeGraph.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 == ProtoCore.DSASM.Constants.kInvalidIndex) { inImperative = inImperative && (depNodeRef.nodeList[m].symbol.functionIndex == ProtoCore.DSASM.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 == ProtoCore.DSASM.Constants.kInvalidIndex) { inImperative = inImperative && (depNodeRef.nodeList[m].symbol.functionIndex == ProtoCore.DSASM.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.IsEqualAtScope(depNodeRef.nodeList[0].symbol); bothSymbolsStatic = modifiedRef.nodeList[0].symbol.memregion == DSASM.MemoryRegion.kMemStatic && depNodeRef.nodeList[0].symbol.memregion == DSASM.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.IsEqualAtScope(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.IsEqualAtScope(depNodeRef.nodeList[m].symbol); bothSymbolsStatic = modifiedRef.nodeList[m].symbol.memregion == DSASM.MemoryRegion.kMemStatic && depNodeRef.nodeList[m].symbol.memregion == DSASM.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); }