示例#1
0
        // TODO Jun: Merge TraverseFunctionCall with the associative version and implement in a codegen utils file
        //Fuqiang: Cannot merge the two functions. They are different. eg. Associative has "emitReplicationGuide = false;"
        public override void TraverseFunctionCall(ProtoCore.AST.Node node, ProtoCore.AST.Node parentNode, int lefttype, int depth, ref ProtoCore.Type inferedType, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone)
        {
            Debug.Assert(null == graphNode);

            FunctionCallNode funcCall = node as FunctionCallNode;
            string procName = funcCall.Function.Name;
            List<ProtoCore.Type> arglist = new List<ProtoCore.Type>();
            foreach (ImperativeNode paramNode in funcCall.FormalArguments)
            {
                ProtoCore.Type paramType = new ProtoCore.Type();
                paramType.UID = (int)ProtoCore.PrimitiveType.kTypeVoid;
                paramType.IsIndexable = false;

                // If it's a binary node then continue type check, otherwise disable type check and just take the type of paramNode itself
                // f(1+2.0) -> type check enabled - param is typed as double
                // f(2) -> type check disabled - param is typed as int
                enforceTypeCheck = !(paramNode is BinaryExpressionNode);

                DfsTraverse(paramNode, ref paramType);
                enforceTypeCheck = true;

                arglist.Add(paramType);
            }

            ProtoCore.DSASM.ProcedureNode procNode = null;
            int type = ProtoCore.DSASM.Constants.kInvalidIndex;
            bool isConstructor = false;
            bool isStatic = false;
            bool hasLogError = false;

            int refClassIndex = ProtoCore.DSASM.Constants.kInvalidIndex;
            if (parentNode != null && parentNode is ProtoCore.AST.AssociativeAST.IdentifierListNode)
            {
                ProtoCore.AST.Node leftnode = (parentNode as ProtoCore.AST.AssociativeAST.IdentifierListNode).LeftNode;
                if (leftnode != null && leftnode is ProtoCore.AST.AssociativeAST.IdentifierNode)
                {
                    refClassIndex = compileState.ClassTable.IndexOf(leftnode.Name);
                }
            }

            // If lefttype is a valid class then check if calling a constructor
            if ((int)ProtoCore.PrimitiveType.kInvalidType != inferedType.UID && (int)ProtoCore.PrimitiveType.kTypeVoid != inferedType.UID)
            {
                bool isAccessible;
                int realType;
                if (inferedType.UID > (int)PrimitiveType.kMaxPrimitives)
                {
                    //check if it is function pointer
                    ProtoCore.DSASM.SymbolNode symbolnode = null;
                    bool isAllocated = VerifyAllocation(procName, inferedType.UID, out symbolnode, out isAccessible);
                    if (isAllocated)
                    {
                        procName = ProtoCore.DSASM.Constants.kFunctionPointerCall;
                    }
                }
                if (procName != ProtoCore.DSASM.Constants.kFunctionPointerCall)
                {
                    procNode = compileState.ClassTable.ClassNodes[inferedType.UID].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out realType);

                    if (procNode != null)
                    {
                        Debug.Assert(realType != ProtoCore.DSASM.Constants.kInvalidIndex);
                        isConstructor = procNode.isConstructor;
                        isStatic = procNode.isStatic;
                        type = lefttype = realType;

                        if ((refClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex) && !procNode.isStatic && !procNode.isConstructor)
                        {
                            return;
                        }

                        if (!isAccessible)
                        {
                            type = lefttype = realType;
                            hasLogError = true;
                        }
                    }
                }
            }

            if (!isConstructor && !isStatic && procName != ProtoCore.DSASM.Constants.kFunctionPointerCall)
            {
                //check if it is function pointer
                bool isAccessibleFp;
                ProtoCore.DSASM.SymbolNode symbolnode = null;
                bool isAllocated = VerifyAllocation(procName, globalClassIndex, out symbolnode, out isAccessibleFp);
                if (isAllocated) // not checking the type against function pointer, as the type could be var
                {
                    procName = ProtoCore.DSASM.Constants.kFunctionPointerCall;
                }
                else
                {
                    procNode = compileState.GetFirstVisibleProcedure(procName, arglist, codeBlock);
                    if (null != procNode)
                    {
                        if ((int)ProtoCore.DSASM.Constants.kInvalidIndex != procNode.procId)
                        {
                            // A global function
                            if (compileState.TypeSystem.IsHigherRank((int)procNode.returntype.UID, inferedType.UID))
                            {
                                inferedType = procNode.returntype;
                            }
                        }
                        else
                        {
                            procNode = null;
                        }
                    }
                    else
                    {
                        type = (lefttype != ProtoCore.DSASM.Constants.kInvalidIndex) ? lefttype : globalClassIndex;
                        if (type != ProtoCore.DSASM.Constants.kInvalidIndex)
                        {
                            int realType;
                            bool isAccessible;
                            ProtoCore.DSASM.ProcedureNode memProcNode = compileState.ClassTable.ClassNodes[type].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out realType);

                            if (memProcNode != null)
                            {
                                Debug.Assert(realType != ProtoCore.DSASM.Constants.kInvalidIndex);
                                procNode = memProcNode;
                                inferedType = procNode.returntype;
                                type = realType;

                                if ((refClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex) && !procNode.isStatic && !procNode.isConstructor)
                                {
                                    inferedType.UID = (int)PrimitiveType.kTypeNull;
                                    return;
                                }

                                if (!isAccessible)
                                {
                                    procNode = null;
                                    if (!hasLogError)
                                    {
                                        hasLogError = true;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (null != procNode)
            {
                //if call is replication call
                if (procNode.isThisCallReplication)
                {
                    inferedType.IsIndexable = true;
                    inferedType.rank++;
                }
            }
            else
            {

                if (depth <= 0 && procName != ProtoCore.DSASM.Constants.kFunctionPointerCall)
                {
                    inferedType.UID = (int)PrimitiveType.kTypeNull;
                }
                else
                {
                    if (procName == ProtoCore.DSASM.Constants.kFunctionPointerCall && depth == 0)
                    {
                        ProtoCore.DSASM.DynamicFunctionNode dynamicFunctionNode = new ProtoCore.DSASM.DynamicFunctionNode(procName, arglist, lefttype);
                        compileState.DynamicFunctionTable.functionTable.Add(dynamicFunctionNode);
                        IdentifierNode iNode = new IdentifierNode()
                        {
                            Value = funcCall.Function.Name,
                            Name = funcCall.Function.Name,
                            datatype = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, false)
                        };
                        EmitIdentifierNode(iNode, ref inferedType);
                    }
                    else
                    {
                        ProtoCore.DSASM.DynamicFunctionNode dynamicFunctionNode = new ProtoCore.DSASM.DynamicFunctionNode(funcCall.Function.Name, arglist, lefttype);
                        compileState.DynamicFunctionTable.functionTable.Add(dynamicFunctionNode);
                    }

                    //assign inferedType to var
                    inferedType.UID = (int)PrimitiveType.kTypeVar;
                }
            }
        }
示例#2
0
        public override void TraverseFunctionCall(ProtoCore.AST.Node node, ProtoCore.AST.Node parentNode, int lefttype, int depth, ref ProtoCore.Type inferedType, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone)
        {
            FunctionCallNode funcCall = node as FunctionCallNode;
            string procName = funcCall.Function.Name;
            List<ProtoCore.Type> arglist = new List<ProtoCore.Type>();
            ProtoCore.Type dotCallType = new ProtoCore.Type();
            dotCallType.UID = (int)PrimitiveType.kTypeVar;
            dotCallType.IsIndexable = false;
            if (procName == "%dot")
            {
                if (funcCall.FormalArguments[0] is IdentifierNode)
                {
                    int ci = core.ClassTable.IndexOf((funcCall.FormalArguments[0] as IdentifierNode).Name);
                    if (ci != ProtoCore.DSASM.Constants.kInvalidIndex)
                    {
                        funcCall.FormalArguments[0] = new IntNode() { value = ci.ToString() };
                        dotCallType.UID = ci;
                    }

                    if (funcCall.FormalArguments.Count > 4)
                    {
                        int dynamicRhsIndex = int.Parse((funcCall.FormalArguments[1] as IntNode).value);
                        core.DynamicFunctionTable.functionTable[dynamicRhsIndex].classIndex = globalClassIndex;
                    }
                    else if (subPass != ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier)
                    {
                        ProtoCore.DSASM.SymbolNode symbolnode = null;
                        bool isAccessible = false;
                        bool isAllocated = VerifyAllocation((funcCall.FormalArguments[0] as IdentifierNode).Name, globalClassIndex, out symbolnode, out isAccessible);
                        if (isAllocated && symbolnode.datatype.UID != (int)PrimitiveType.kTypeVar)
                        {
                            int rhsIndex = int.Parse((funcCall.FormalArguments[1] as IntNode).value);
                            string rhsName = core.DynamicVariableTable.variableTable[rhsIndex].variableName;
                            isAllocated = VerifyAllocation(rhsName, symbolnode.datatype.UID, out symbolnode, out isAccessible);
                            if (null == symbolnode)    //unbound identifier
                            {
                                if (isAllocated && !isAccessible)
                                {
                                    ProtoCore.Type leftType = new ProtoCore.Type();
                                    leftType.UID = (int)PrimitiveType.kInvalidType;
                                    leftType.IsIndexable = false;
                                    bool isFirstIdent = true;
                                    DfsEmitIdentList(funcCall.FormalArguments[0], null, globalClassIndex, ref leftType, ref depth, ref inferedType, false, ref isFirstIdent, graphNode, subPass);
                                    inferedType.UID = (int)PrimitiveType.kTypeNull;
                                    return;
                                }
                            }
                        }
                    }
                }
                else if (funcCall.FormalArguments[0] is IntNode)
                {
                    dotCallType.UID = int.Parse((funcCall.FormalArguments[0] as IntNode).value);
                }
            }

            foreach (AssociativeNode paramNode in funcCall.FormalArguments)
            {
                ProtoCore.Type paramType = new ProtoCore.Type();
                paramType.UID = (int)ProtoCore.PrimitiveType.kTypeVoid;
                paramType.IsIndexable = false;

                //emitReplicationGuide = paramNode is IdentifierNode || paramNode is ExprListNode;

                // If it's a binary node then continue type check, otherwise disable type check and just take the type of paramNode itself
                // f(1+2.0) -> type check enabled - param is typed as double
                // f(2) -> type check disabled - param is typed as int
                enforceTypeCheck = !(paramNode is BinaryExpressionNode);

                DfsTraverse(paramNode, ref paramType, false, graphNode, subPass);
                enforceTypeCheck = true;

                arglist.Add(paramType);
            }

            if (subPass == ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier)
            {
                return;
            }

            ProtoCore.DSASM.ProcedureNode procNode = null;
            int type = ProtoCore.DSASM.Constants.kInvalidIndex;
            bool isConstructor = false;
            bool isStatic = false;
            bool hasLogError = false;

            int refClassIndex = ProtoCore.DSASM.Constants.kInvalidIndex;
            if (parentNode != null && parentNode is ProtoCore.AST.AssociativeAST.IdentifierListNode)
            {
                ProtoCore.AST.Node leftnode = (parentNode as ProtoCore.AST.AssociativeAST.IdentifierListNode).LeftNode;
                if (leftnode != null && leftnode is ProtoCore.AST.AssociativeAST.IdentifierNode)
                {
                    refClassIndex = core.ClassTable.IndexOf(leftnode.Name);
                }
            }

            // If lefttype is a valid class then check if calling a constructor
            if ((int)ProtoCore.PrimitiveType.kInvalidType != inferedType.UID && (int)ProtoCore.PrimitiveType.kTypeVoid != inferedType.UID)
            {
                bool isAccessible;
                int realType;
                if (inferedType.UID > (int)PrimitiveType.kMaxPrimitives)
                {
                    //check if it is function pointer
                    ProtoCore.DSASM.SymbolNode symbolnode = null;
                    bool isAllocated = VerifyAllocation(procName, inferedType.UID, out symbolnode, out isAccessible);
                    if (isAllocated)
                    {
                        procName = ProtoCore.DSASM.Constants.kFunctionPointerCall;
                    }
                }
                if (procName != ProtoCore.DSASM.Constants.kFunctionPointerCall)
                {
                    procNode = core.ClassTable.ClassNodes[inferedType.UID].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out realType);

                    if (procNode != null)
                    {
                        Debug.Assert(realType != ProtoCore.DSASM.Constants.kInvalidIndex);
                        isConstructor = procNode.isConstructor;
                        isStatic = procNode.isStatic;
                        type = lefttype = realType;

                        if ((refClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex) && !procNode.isStatic && !procNode.isConstructor)
                        {
                            inferedType.UID = (int)PrimitiveType.kTypeNull;
                            return;
                        }

                        if (!isAccessible)
                        {
                            type = lefttype = realType;
                            procNode = null;
                            hasLogError = true;
                        }
                    }
                }
            }

            if (!isConstructor && !isStatic && procName != ProtoCore.DSASM.Constants.kFunctionPointerCall)
            {
                //check if it is function pointer
                bool isAccessibleFp;
                ProtoCore.DSASM.SymbolNode symbolnode = null;
                bool isAllocated = VerifyAllocation(procName, globalClassIndex, out symbolnode, out isAccessibleFp);
                if (isAllocated) // not checking the type against function pointer, as the type could be var
                {
                    procName = ProtoCore.DSASM.Constants.kFunctionPointerCall;
                }
                else
                {
                    procNode = core.GetFirstVisibleProcedure(procName, arglist, codeBlock);
                    if (null != procNode)
                    {
                        if ((int)ProtoCore.DSASM.Constants.kInvalidIndex != procNode.procId)
                        {
                            // A global function
                            if (core.TypeSystem.IsHigherRank((int)procNode.returntype.UID, inferedType.UID))
                            {
                                inferedType = procNode.returntype;
                            }
                        }
                        else
                        {
                            procNode = null;
                        }
                    }
                    else
                    {
                        type = (lefttype != ProtoCore.DSASM.Constants.kInvalidIndex) ? lefttype : globalClassIndex;
                        if (type != ProtoCore.DSASM.Constants.kInvalidIndex)
                        {
                            int realType;
                            bool isAccessible;
                            ProtoCore.DSASM.ProcedureNode memProcNode = core.ClassTable.ClassNodes[type].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out realType);

                            if (memProcNode != null)
                            {
                                Debug.Assert(realType != ProtoCore.DSASM.Constants.kInvalidIndex);
                                procNode = memProcNode;
                                inferedType = procNode.returntype;
                                type = realType;

                                if ((refClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex) && !procNode.isStatic && !procNode.isConstructor)
                                {
                                    inferedType.UID = (int)PrimitiveType.kTypeNull;
                                    return;
                                }

                                if (!isAccessible)
                                {
                                    procNode = null;
                                    if (!hasLogError)
                                    {
                                        hasLogError = true;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (null != procNode)
            {
                //if call is replication call
                if (procNode.isThisCallReplication)
                {
                    inferedType.IsIndexable = true;
                    inferedType.rank++;
                }

                if ((int)ProtoCore.DSASM.Constants.kInvalidIndex != procNode.procId)
                {
                    if (dotCallType.UID != (int)PrimitiveType.kTypeVar)
                    {
                        inferedType.UID = dotCallType.UID;
                    }
                }
            }
            else
            {
                if (depth <= 0 && procName != ProtoCore.DSASM.Constants.kFunctionPointerCall)
                {
                    // At compile time we only check if function name and the number of parameter are
                    // both matched, so if it is a global function call but we still can't get procNode,
                    // it is hopeless to resolve that at run-time. Then we should return null. -yu ke
                    inferedType.UID = (int)PrimitiveType.kTypeNull;
                }
                else
                {
                    if (procName == ProtoCore.DSASM.Constants.kFunctionPointerCall && depth == 0)
                    {
                        ProtoCore.DSASM.DynamicFunctionNode dynamicFunctionNode = new ProtoCore.DSASM.DynamicFunctionNode(procName, arglist, lefttype);
                        core.DynamicFunctionTable.functionTable.Add(dynamicFunctionNode);
                        IdentifierNode iNode = new IdentifierNode()
                        {
                            Value = funcCall.Function.Name,
                            Name = funcCall.Function.Name,
                            datatype = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeVar, false)
                        };
                        EmitIdentifierNode(iNode, ref inferedType);
                    }
                    else
                    {
                        ProtoCore.DSASM.DynamicFunctionNode dynamicFunctionNode = new ProtoCore.DSASM.DynamicFunctionNode(funcCall.Function.Name, arglist, lefttype);
                        core.DynamicFunctionTable.functionTable.Add(dynamicFunctionNode);
                    }
                    inferedType.UID = (int)PrimitiveType.kTypeVar;
                }
            }
        }