Example #1
0
        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++);
        }
Example #2
0
        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
        }
Example #3
0
        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);
        }