Ejemplo n.º 1
0
        private void EmitFunctionDefinitionNode(AssociativeNode node, ref ProtoCore.Type inferedType, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone, GraphNode graphNode = null)
        {
            bool parseGlobalFunctionBody = null == localProcedure && ProtoCore.CompilerDefinitions.Associative.CompilePass.kGlobalFuncBody == compilePass;
            bool parseMemberFunctionBody = ProtoCore.DSASM.Constants.kGlobalScope != globalClassIndex && ProtoCore.CompilerDefinitions.Associative.CompilePass.kClassMemFuncBody == compilePass;

            FunctionDefinitionNode funcDef = node as FunctionDefinitionNode;
            localFunctionDefNode = funcDef;

            if (funcDef.IsAssocOperator)
            {
                isAssocOperator = true;
            }
            else
            {
                isAssocOperator = false;
            }

            bool hasReturnStatement = false;
            ProtoCore.DSASM.CodeBlockType origCodeBlockType = codeBlock.blockType;
            codeBlock.blockType = ProtoCore.DSASM.CodeBlockType.kFunction;
            if (IsParsingGlobalFunctionSig() || IsParsingMemberFunctionSig())
            {
                Validity.Assert(null == localProcedure);
                localProcedure = new ProtoCore.DSASM.ProcedureNode();

                localProcedure.Name = funcDef.Name;
                localProcedure.PC = ProtoCore.DSASM.Constants.kInvalidIndex;
                localProcedure.LocalCount = 0; // Defer till all locals are allocated
                var uid = core.TypeSystem.GetType(funcDef.ReturnType.Name);
                var rank = funcDef.ReturnType.rank;
                var returnType = core.TypeSystem.BuildTypeObject(uid, rank); 
                if (returnType.UID == (int)PrimitiveType.kInvalidType)
                {
                    string message = String.Format(ProtoCore.Properties.Resources.kReturnTypeUndefined, funcDef.ReturnType.Name, funcDef.Name);
                    buildStatus.LogWarning(WarningID.kTypeUndefined, message, core.CurrentDSFileName, funcDef.line, funcDef.col, graphNode);
                    returnType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, rank);
                }
                localProcedure.ReturnType = returnType;
                localProcedure.IsConstructor = false;
                localProcedure.IsStatic = funcDef.IsStatic;
                localProcedure.RuntimeIndex = codeBlock.codeBlockId;
                localProcedure.AccessModifier = funcDef.Access;
                localProcedure.IsExternal = funcDef.IsExternLib;
                localProcedure.IsAutoGenerated = funcDef.IsAutoGenerated;
                localProcedure.ClassID = globalClassIndex;
                localProcedure.IsAssocOperator = funcDef.IsAssocOperator;
                localProcedure.IsAutoGeneratedThisProc = funcDef.IsAutoGeneratedThisProc;

                localProcedure.MethodAttribute = funcDef.MethodAttributes;

                int peekFunctionindex = ProtoCore.DSASM.Constants.kInvalidIndex;

                if (ProtoCore.DSASM.Constants.kInvalidIndex == globalClassIndex)
                {
                    peekFunctionindex = codeBlock.procedureTable.Procedures.Count;
                }
                else
                {
                    peekFunctionindex = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Procedures.Count;
                }

                // Append arg symbols
                List<KeyValuePair<string, ProtoCore.Type>> argsToBeAllocated = new List<KeyValuePair<string, ProtoCore.Type>>();
                string functionDescription = localProcedure.Name;
                if (null != funcDef.Signature)
                {
                    foreach (VarDeclNode argNode in funcDef.Signature.Arguments)
                    {
                        var argInfo = BuildArgumentInfoFromVarDeclNode(argNode);
                        localProcedure.ArgumentInfos.Add(argInfo);

                        var argType = BuildArgumentTypeFromVarDeclNode(argNode, graphNode);
                        localProcedure.ArgumentTypes.Add(argType);

                        argsToBeAllocated.Add(new KeyValuePair<string, ProtoCore.Type>(argInfo.Name, argType));

                        functionDescription += argNode.ArgumentType.ToString();
                    }
                    localProcedure.HashID = functionDescription.GetHashCode();
                    localProcedure.IsVarArg = funcDef.Signature.IsVarArg;
                }

                if (ProtoCore.DSASM.Constants.kInvalidIndex == globalClassIndex)
                {
                    globalProcIndex = codeBlock.procedureTable.Append(localProcedure);
                }
                else
                {
                    globalProcIndex = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Append(localProcedure);
                }

                // Comment Jun: Catch this assert given the condition as this type of mismatch should never occur
                if (ProtoCore.DSASM.Constants.kInvalidIndex != globalProcIndex)
                {
                    argsToBeAllocated.ForEach(arg =>
                    {
                        int symbolIndex = AllocateArg(arg.Key, globalProcIndex, arg.Value);
                        if (ProtoCore.DSASM.Constants.kInvalidIndex == symbolIndex)
                        {
                            throw new BuildHaltException("B2CB2093");
                        }
                    });                   
                }
                else
                {
                    string message = String.Format(ProtoCore.Properties.Resources.kMethodAlreadyDefined, localProcedure.Name);
                    buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kFunctionAlreadyDefined, message, core.CurrentDSFileName, funcDef.line, funcDef.col, graphNode);
                    funcDef.skipMe = true;
                }
            }
            else if (parseGlobalFunctionBody || parseMemberFunctionBody)
            {
                if (CoreUtils.IsDisposeMethod(node.Name))
                {
                    core.Options.EmitBreakpoints = false;
                }

                // Build arglist for comparison
                List<ProtoCore.Type> argList = new List<ProtoCore.Type>();
                if (null != funcDef.Signature)
                {
                    foreach (VarDeclNode argNode in funcDef.Signature.Arguments)
                    {
                        ProtoCore.Type argType = BuildArgumentTypeFromVarDeclNode(argNode, graphNode);
                        argList.Add(argType);
                    }
                }

                // Get the exisitng procedure that was added on the previous pass
                if (ProtoCore.DSASM.Constants.kInvalidIndex == globalClassIndex)
                {
                    var procNode = codeBlock.procedureTable.GetFunctionBySignature(funcDef.Name, argList);
                    globalProcIndex = procNode == null ? Constants.kInvalidIndex : procNode.ID;
                    localProcedure = codeBlock.procedureTable.Procedures[globalProcIndex];
                }
                else
                {
                    var procNode = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.GetFunctionBySignature(funcDef.Name, argList);
                    globalProcIndex = procNode == null ? Constants.kInvalidIndex : procNode.ID;
                    localProcedure = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Procedures[globalProcIndex];
                }

                Validity.Assert(null != localProcedure);

                // code gen the attribute 
                localProcedure.Attributes = PopulateAttributes(funcDef.Attributes);
                // Its only on the parse body pass where the real pc is determined. Update this procedures' pc
                //Validity.Assert(ProtoCore.DSASM.Constants.kInvalidIndex == localProcedure.pc);
                localProcedure.PC = pc;

                // Copy the active function to the core so nested language blocks can refer to it
                core.ProcNode = localProcedure;

                ProtoCore.FunctionEndPoint fep = null;
                if (!funcDef.IsExternLib)
                {
                    //Traverse default argument
                    emitDebugInfo = false;
                    foreach (ProtoCore.DSASM.ArgumentInfo argNode in localProcedure.ArgumentInfos)
                    {
                        if (!argNode.IsDefault)
                        {
                            continue;
                        }
                        BinaryExpressionNode bNode = argNode.DefaultExpression as BinaryExpressionNode;
                        // build a temporay node for statement : temp = defaultarg;
                        var iNodeTemp = AstFactory.BuildIdentifier(core.GenerateTempVar());
                        var bNodeTemp = AstFactory.BuildAssignment(iNodeTemp, bNode.LeftNode);
                        bNodeTemp.IsProcedureOwned = true;
                        EmitBinaryExpressionNode(bNodeTemp, ref inferedType, false, null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier);
                        //duild an inline conditional node for statement: defaultarg = (temp == DefaultArgNode) ? defaultValue : temp;
                        InlineConditionalNode icNode = new InlineConditionalNode();
                        icNode.IsAutoGenerated = true;
                        BinaryExpressionNode cExprNode = new BinaryExpressionNode();
                        cExprNode.Optr = ProtoCore.DSASM.Operator.eq;
                        cExprNode.LeftNode = iNodeTemp;
                        cExprNode.RightNode = new DefaultArgNode();
                        icNode.ConditionExpression = cExprNode;
                        icNode.TrueExpression = bNode.RightNode;
                        icNode.FalseExpression = iNodeTemp;
                        bNodeTemp.LeftNode = bNode.LeftNode;
                        bNodeTemp.RightNode = icNode;
                        EmitBinaryExpressionNode(bNodeTemp, ref inferedType, false, null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier);
                    }
                    emitDebugInfo = true;

                    EmitCompileLogFunctionStart(GetFunctionSignatureString(funcDef.Name, funcDef.ReturnType, funcDef.Signature));

                    ProtoCore.Type itype = new ProtoCore.Type();

                    hasReturnStatement = EmitCodeBlock(funcDef.FunctionBody.Body, ref itype, subPass, true);

                    // Build dependency within the function
                    ProtoCore.AssociativeEngine.Utils.BuildGraphNodeDependencies(
                        codeBlock.instrStream.dependencyGraph.GetGraphNodesAtScope(globalClassIndex, globalProcIndex));


                    EmitCompileLogFunctionEnd();

                    // All locals have been stack allocated, update the local count of this function
                    localProcedure.LocalCount = core.BaseOffset;

                    if (ProtoCore.DSASM.Constants.kInvalidIndex == globalClassIndex)
                    {
                        localProcedure.LocalCount = core.BaseOffset;

                        // Update the param stack indices of this function
                        foreach (ProtoCore.DSASM.SymbolNode symnode in codeBlock.symbolTable.symbolList.Values)
                        {
                            if (symnode.functionIndex == localProcedure.ID && symnode.isArgument)
                            {
                                symnode.index -= localProcedure.LocalCount;
                            }
                        }
                    }
                    else
                    {
                        core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Procedures[localProcedure.ID].LocalCount = core.BaseOffset;

                        // Update the param stack indices of this function
                        foreach (ProtoCore.DSASM.SymbolNode symnode in core.ClassTable.ClassNodes[globalClassIndex].Symbols.symbolList.Values)
                        {
                            if (symnode.functionIndex == localProcedure.ID && symnode.isArgument)
                            {
                                symnode.index -= localProcedure.LocalCount;
                            }
                        }
                    }

                    ProtoCore.Lang.JILActivationRecord record = new ProtoCore.Lang.JILActivationRecord();
                    record.pc = localProcedure.PC;
                    record.locals = localProcedure.LocalCount;
                    record.classIndex = globalClassIndex;
                    record.funcIndex = localProcedure.ID;
                    fep = new ProtoCore.Lang.JILFunctionEndPoint(record);
                }
                else if (funcDef.BuiltInMethodId != ProtoCore.Lang.BuiltInMethods.MethodID.kInvalidMethodID)
                {
                    fep = new ProtoCore.Lang.BuiltInFunctionEndPoint(funcDef.BuiltInMethodId);
                }
                else
                {
                    ProtoCore.Lang.JILActivationRecord jRecord = new ProtoCore.Lang.JILActivationRecord();
                    jRecord.pc = localProcedure.PC;
                    jRecord.locals = localProcedure.LocalCount;
                    jRecord.classIndex = globalClassIndex;
                    jRecord.funcIndex = localProcedure.ID;

                    ProtoCore.Lang.FFIActivationRecord record = new ProtoCore.Lang.FFIActivationRecord();
                    record.JILRecord = jRecord;
                    record.FunctionName = funcDef.Name;
                    record.ModuleName = funcDef.ExternLibName;
                    record.ModuleType = "dll";
                    record.IsDNI = funcDef.IsDNI;
                    record.ReturnType = funcDef.ReturnType;
                    record.ParameterTypes = localProcedure.ArgumentTypes;
                    fep = new ProtoCore.Lang.FFIFunctionEndPoint(record);
                }

                // Construct the fep arguments
                fep.FormalParams = new ProtoCore.Type[localProcedure.ArgumentTypes.Count];
                fep.BlockScope = codeBlock.codeBlockId;
                fep.ClassOwnerIndex = localProcedure.ClassID;
                fep.procedureNode = localProcedure;
                localProcedure.ArgumentTypes.CopyTo(fep.FormalParams, 0);

                // 'classIndexAtCallsite' is the class index as it is stored at the callsite function tables
                int classIndexAtCallsite = globalClassIndex + 1;
                core.FunctionTable.InitGlobalFunctionEntry(classIndexAtCallsite);

                // Get the function group of the current class and see if the current function exists
                Dictionary<string, FunctionGroup> fgroup = core.FunctionTable.GlobalFuncTable[classIndexAtCallsite];
                if (!fgroup.ContainsKey(funcDef.Name))
                {
                    // If any functions in the base class have the same name, append them here
                    int ci = classIndexAtCallsite - 1;
                    if (ProtoCore.DSASM.Constants.kInvalidIndex != ci)
                    {
                        ProtoCore.DSASM.ClassNode cnode = core.ClassTable.ClassNodes[ci];
                        if (cnode.Bases.Count > 0)
                        {
                            Validity.Assert(1 == cnode.Bases.Count, "We don't support multiple inheritance yet");

                            ci = cnode.Bases[0];

                            Dictionary<string, FunctionGroup> tgroup = new Dictionary<string, FunctionGroup>();
                            int callsiteCI = ci + 1;
                            bool bSucceed = core.FunctionTable.GlobalFuncTable.TryGetValue(callsiteCI, out tgroup);
                            if (bSucceed)
                            {
                                if (tgroup.ContainsKey(funcDef.Name))
                                {
                                    // Get that base group - the group of function from the baseclass
                                    FunctionGroup basegroup = new FunctionGroup();
                                    bSucceed = tgroup.TryGetValue(funcDef.Name, out basegroup);
                                    if (bSucceed)
                                    {
                                        // Copy all non-private feps from the basegroup into this the new group
                                        FunctionGroup newGroup = new FunctionGroup();
                                        newGroup.CopyVisible(basegroup.FunctionEndPoints);

                                        // Append the new fep 
                                        newGroup.FunctionEndPoints.Add(fep);

                                        // Copy the new group to this class table
                                        core.FunctionTable.GlobalFuncTable[classIndexAtCallsite].Add(funcDef.Name, newGroup);
                                    }
                                }
                                else
                                {
                                    // Create a new function group in this class
                                    ProtoCore.FunctionGroup funcGroup = new ProtoCore.FunctionGroup();
                                    funcGroup.FunctionEndPoints.Add(fep);

                                    // Add this group to the class function tables
                                    core.FunctionTable.GlobalFuncTable[classIndexAtCallsite].Add(funcDef.Name, funcGroup);
                                }
                            }
                            else
                            {
                                // Create a new function group in this class
                                ProtoCore.FunctionGroup funcGroup = new ProtoCore.FunctionGroup();
                                funcGroup.FunctionEndPoints.Add(fep);

                                // Add this group to the class function tables
                                core.FunctionTable.GlobalFuncTable[classIndexAtCallsite].Add(funcDef.Name, funcGroup);
                            }
                            cnode = core.ClassTable.ClassNodes[ci];
                        }
                        else
                        {
                            // Create a new function group in this class
                            ProtoCore.FunctionGroup funcGroup = new ProtoCore.FunctionGroup();
                            funcGroup.FunctionEndPoints.Add(fep);

                            // Add this group to the class function tables
                            core.FunctionTable.GlobalFuncTable[classIndexAtCallsite].Add(funcDef.Name, funcGroup);
                        }
                    }
                    else
                    {
                        // Create a new function group in this class
                        ProtoCore.FunctionGroup funcGroup = new ProtoCore.FunctionGroup();
                        funcGroup.FunctionEndPoints.Add(fep);

                        // Add this group to the class function tables
                        core.FunctionTable.GlobalFuncTable[classIndexAtCallsite].Add(funcDef.Name, funcGroup);
                    }
                }
                else
                {
                    // Add this fep into the exisitng function group
                    core.FunctionTable.GlobalFuncTable[classIndexAtCallsite][funcDef.Name].FunctionEndPoints.Add(fep);
                }

                if (!hasReturnStatement && !funcDef.IsExternLib)
                {
                    if (!core.Options.SuppressFunctionResolutionWarning)
                    {
                        string message = String.Format(ProtoCore.Properties.Resources.kFunctionNotReturnAtAllCodePaths, localProcedure.Name);
                        buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kMissingReturnStatement, message, core.CurrentDSFileName, funcDef.line, funcDef.col, graphNode);
                    }
                    EmitReturnNull();
                }

                if (CoreUtils.IsDisposeMethod(node.Name))
                {
                    core.Options.EmitBreakpoints = true;
                }
            }

            core.ProcNode = localProcedure = null;
            codeBlock.blockType = origCodeBlockType;
            globalProcIndex = ProtoCore.DSASM.Constants.kGlobalScope;
            localFunctionDefNode = null;
            core.BaseOffset = 0;
            argOffset = 0;
            isAssocOperator = false;
        }
Ejemplo n.º 2
0
        private void ResolveFunctionGroups()
        {
            // foreach class in classtable
            foreach (ProtoCore.DSASM.ClassNode cnode in core.ClassTable.ClassNodes)
            {
                if (cnode.Bases.Count > 0)
                {
                    // Get the current class functiongroup
                    int ci = cnode.ID;
                    Dictionary<string, FunctionGroup> groupList = new Dictionary<string, FunctionGroup>();
                    if (!core.FunctionTable.GlobalFuncTable.TryGetValue(ci + 1, out groupList))
                    {
                        continue;
                    }

                    // If it has a baseclass, get its function group 'basegroup'
                    int baseCI = cnode.Bases[0];
                    Dictionary<string, FunctionGroup> baseGroupList = new Dictionary<string, FunctionGroup>();
                    bool groupListExists = core.FunctionTable.GlobalFuncTable.TryGetValue(baseCI + 1, out baseGroupList);
                    if (groupListExists)
                    {
                        // If it has a baseclass, get its list of function group 'basegrouplist'
                        // for every group, check if this already exisits in the current class
                        foreach (KeyValuePair<string, FunctionGroup> baseGroup in baseGroupList)
                        {
                           if (groupList.ContainsKey(baseGroup.Key))
                           {
                               // If this class has this function group, append the visible feps from the basegoup
                               FunctionGroup currentGroup = new FunctionGroup();
                               if (groupList.TryGetValue(baseGroup.Key, out currentGroup))
                               {
                                   // currentGroup is this class's current function group given the current name
                                   currentGroup.CopyVisible(baseGroup.Value.FunctionEndPoints);
                               }
                           }
                           else
                           {
                               // If this class doesnt have basegroup, create a new group and append the visible feps from the basegoup
                               FunctionGroup newGroup = new FunctionGroup();
                               newGroup.CopyVisible(baseGroup.Value.FunctionEndPoints);
                               if (newGroup.FunctionEndPoints.Count > 0)
                               {
                                   groupList.Add(baseGroup.Key, newGroup);
                               }
                           }
                        }
                    }
                }
            }
        }
Ejemplo n.º 3
0
        private void EmitFunctionDefinitionNode(AssociativeNode node, ref ProtoCore.Type inferedType, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone)
        {
            bool parseGlobalFunctionBody = null == localProcedure && ProtoCore.DSASM.AssociativeCompilePass.kGlobalFuncBody == compilePass;
            bool parseMemberFunctionBody = ProtoCore.DSASM.Constants.kGlobalScope != globalClassIndex && ProtoCore.DSASM.AssociativeCompilePass.kClassMemFuncBody == compilePass;

            FunctionDefinitionNode funcDef = node as FunctionDefinitionNode;
            localFunctionDefNode = funcDef;

            if (funcDef.IsAssocOperator)
            {
                isAssocOperator = true;
            }
            else
            {
                isAssocOperator = false;
            }

            bool hasReturnStatement = false;
            ProtoCore.DSASM.CodeBlockType origCodeBlockType = codeBlock.blockType;
            codeBlock.blockType = ProtoCore.DSASM.CodeBlockType.kFunction;
            if (IsParsingGlobalFunctionSig() || IsParsingMemberFunctionSig())
            {
                Debug.Assert(null == localProcedure);
                localProcedure = new ProtoCore.DSASM.ProcedureNode();

                localProcedure.name = funcDef.Name;
                localProcedure.pc = ProtoCore.DSASM.Constants.kInvalidIndex;
                localProcedure.localCount = 0; // Defer till all locals are allocated
                localProcedure.returntype.UID = compileStateTracker.TypeSystem.GetType(funcDef.ReturnType.Name);
                if (localProcedure.returntype.UID == (int)PrimitiveType.kInvalidType)
                {
                    string message = String.Format(ProtoCore.BuildData.WarningMessage.kReturnTypeUndefined, funcDef.ReturnType.Name, funcDef.Name);
                    buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kTypeUndefined, message, compileStateTracker.CurrentDSFileName, funcDef.line, funcDef.col);
                    localProcedure.returntype.UID = (int)PrimitiveType.kTypeVar;
                }
                localProcedure.returntype.IsIndexable = funcDef.ReturnType.IsIndexable;
                localProcedure.returntype.rank = funcDef.ReturnType.rank;
                localProcedure.isConstructor = false;
                localProcedure.isStatic = funcDef.IsStatic;
                localProcedure.runtimeIndex = codeBlock.codeBlockId;
                localProcedure.access = funcDef.access;
                localProcedure.isExternal = funcDef.IsExternLib;
                localProcedure.isAutoGenerated = funcDef.IsAutoGenerated;
                localProcedure.classScope = globalClassIndex;
                localProcedure.isAssocOperator = funcDef.IsAssocOperator;
                localProcedure.isAutoGeneratedThisProc = funcDef.IsAutoGeneratedThisProc;

                int peekFunctionindex = ProtoCore.DSASM.Constants.kInvalidIndex;

                if (ProtoCore.DSASM.Constants.kInvalidIndex == globalClassIndex)
                {
                    peekFunctionindex = codeBlock.procedureTable.procList.Count;
                }
                else
                {
                    peekFunctionindex = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].vtable.procList.Count;
                }

                // Append arg symbols
                List<KeyValuePair<string, ProtoCore.Type>> argsToBeAllocated = new List<KeyValuePair<string, ProtoCore.Type>>();
                if (null != funcDef.Singnature)
                {
                    int argNumber = 0;
                    foreach (VarDeclNode argNode in funcDef.Singnature.Arguments)
                    {
                        ++argNumber;

                        IdentifierNode paramNode = null;
                        bool aIsDefault = false;
                        ProtoCore.AST.Node aDefaultExpression = null;
                        if (argNode.NameNode is IdentifierNode)
                        {
                            paramNode = argNode.NameNode as IdentifierNode;
                        }
                        else if (argNode.NameNode is BinaryExpressionNode)
                        {
                            BinaryExpressionNode bNode = argNode.NameNode as BinaryExpressionNode;
                            paramNode = bNode.LeftNode as IdentifierNode;
                            aIsDefault = true;
                            aDefaultExpression = bNode;
                            //buildStatus.LogSemanticError("Defualt parameters are not supported");
                            //throw new BuildHaltException();
                        }
                        else
                        {
                            Debug.Assert(false, "Check generated AST");
                        }

                        ProtoCore.Type argType = BuildArgumentTypeFromVarDeclNode(argNode);
                        // We dont directly allocate arguments now
                        argsToBeAllocated.Add(new KeyValuePair<string, ProtoCore.Type>(paramNode.Value, argType));

                        localProcedure.argTypeList.Add(argType);
                        ProtoCore.DSASM.ArgumentInfo argInfo = new ProtoCore.DSASM.ArgumentInfo { Name = paramNode.Value, isDefault = aIsDefault, defaultExpression = aDefaultExpression };
                        localProcedure.argInfoList.Add(argInfo);
                    }
                }

                if (ProtoCore.DSASM.Constants.kInvalidIndex == globalClassIndex)
                {
                    globalProcIndex = codeBlock.procedureTable.Append(localProcedure);
                }
                else
                {
                    globalProcIndex = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].vtable.Append(localProcedure);
                }

                // Comment Jun: Catch this assert given the condition as this type of mismatch should never occur
                if (ProtoCore.DSASM.Constants.kInvalidIndex != globalProcIndex)
                {
                    Debug.Assert(peekFunctionindex == localProcedure.procId);

                    argsToBeAllocated.ForEach(arg =>
                    {
                        int symbolIndex = AllocateArg(arg.Key, globalProcIndex, arg.Value);
                        if (ProtoCore.DSASM.Constants.kInvalidIndex == symbolIndex)
                        {
                            throw new BuildHaltException("B2CB2093");
                        }
                    });

                    // TODO Jun: Remove this once agree that alltest cases assume the default assoc block is block 0
                    // NOTE: Only affects mirror, not actual execution
                    if (null == codeBlock.parent && pc <= 0)
                    {
                        // The first node in the top level block is a function
                        compileStateTracker.DSExecutable.isSingleAssocBlock = false;
                    }

            #if ENABLE_EXCEPTION_HANDLING
                    core.ExceptionHandlingManager.Register(codeBlock.codeBlockId, globalProcIndex, globalClassIndex);
            #endif
                }
                else
                {
                    string message = String.Format(ProtoCore.BuildData.WarningMessage.kMethodAlreadyDefined, localProcedure.name);
                    buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kFunctionAlreadyDefined, message, compileStateTracker.CurrentDSFileName, funcDef.line, funcDef.col);
                    funcDef.skipMe = true;
                }
            }
            else if (parseGlobalFunctionBody || parseMemberFunctionBody)
            {
                if (compileStateTracker.Options.DisableDisposeFunctionDebug)
                {
                    if (node.Name.Equals(ProtoCore.DSDefinitions.Keyword.Dispose))
                    {
                        compileStateTracker.Options.EmitBreakpoints = false;
                    }
                }

                // Build arglist for comparison
                List<ProtoCore.Type> argList = new List<ProtoCore.Type>();
                if (null != funcDef.Singnature)
                {
                    foreach (VarDeclNode argNode in funcDef.Singnature.Arguments)
                    {
                        ProtoCore.Type argType = BuildArgumentTypeFromVarDeclNode(argNode);
                        argList.Add(argType);
                    }
                }

                // Get the exisitng procedure that was added on the previous pass
                if (ProtoCore.DSASM.Constants.kInvalidIndex == globalClassIndex)
                {
                    globalProcIndex = codeBlock.procedureTable.IndexOfExact(funcDef.Name, argList);
                    localProcedure = codeBlock.procedureTable.procList[globalProcIndex];
                }
                else
                {
                    globalProcIndex = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].vtable.IndexOfExact(funcDef.Name, argList);
                    localProcedure = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].vtable.procList[globalProcIndex];
                }

                Debug.Assert(null != localProcedure);

                // code gen the attribute
                localProcedure.Attributes = PopulateAttributes(funcDef.Attributes);
                // Its only on the parse body pass where the real pc is determined. Update this procedures' pc
                //Debug.Assert(ProtoCore.DSASM.Constants.kInvalidIndex == localProcedure.pc);
                localProcedure.pc = pc;

                // Copy the active function to the core so nested language blocks can refer to it
                compileStateTracker.ProcNode = localProcedure;

                ProtoCore.FunctionEndPoint fep = null;
                if (!funcDef.IsExternLib)
                {
                    //Traverse default argument
                    emitDebugInfo = false;
                    foreach (ProtoCore.DSASM.ArgumentInfo argNode in localProcedure.argInfoList)
                    {
                        if (!argNode.isDefault)
                        {
                            continue;
                        }
                        BinaryExpressionNode bNode = argNode.defaultExpression as BinaryExpressionNode;
                        // build a temporay node for statement : temp = defaultarg;
                        var iNodeTemp = nodeBuilder.BuildTempVariable();
                        var bNodeTemp = nodeBuilder.BuildBinaryExpression(iNodeTemp, bNode.LeftNode) as BinaryExpressionNode;
                        EmitBinaryExpressionNode(bNodeTemp, ref inferedType, false, null, AssociativeSubCompilePass.kUnboundIdentifier);
                        //duild an inline conditional node for statement: defaultarg = (temp == DefaultArgNode) ? defaultValue : temp;
                        InlineConditionalNode icNode = new InlineConditionalNode();
                        icNode.IsAutoGenerated = true;
                        BinaryExpressionNode cExprNode = new BinaryExpressionNode();
                        cExprNode.Optr = ProtoCore.DSASM.Operator.eq;
                        cExprNode.LeftNode = iNodeTemp;
                        cExprNode.RightNode = new DefaultArgNode();
                        icNode.ConditionExpression = cExprNode;
                        icNode.TrueExpression = bNode.RightNode;
                        icNode.FalseExpression = iNodeTemp;
                        bNodeTemp.LeftNode = bNode.LeftNode;
                        bNodeTemp.RightNode = icNode;
                        EmitBinaryExpressionNode(bNodeTemp, ref inferedType, false, null, AssociativeSubCompilePass.kUnboundIdentifier);
                    }
                    emitDebugInfo = true;

                    EmitCompileLogFunctionStart(GetFunctionSignatureString(funcDef.Name, funcDef.ReturnType, funcDef.Singnature));

                    // Traverse definition
                    foreach (AssociativeNode bnode in funcDef.FunctionBody.Body)
                    {

                        //
                        // TODO Jun:    Handle stand alone language blocks
                        //              Integrate the subPass into a proper pass
                        //

                        ProtoCore.Type itype = new ProtoCore.Type();
                        itype.UID = (int)PrimitiveType.kTypeVar;

                        if (bnode is LanguageBlockNode)
                        {
                            // Build a binaryn node with a temporary lhs for every stand-alone language block
                            BinaryExpressionNode langBlockNode = new BinaryExpressionNode();
                            langBlockNode.LeftNode = nodeBuilder.BuildIdentfier(compileStateTracker.GenerateTempLangageVar());
                            langBlockNode.Optr = ProtoCore.DSASM.Operator.assign;
                            langBlockNode.RightNode = bnode;

                            //DfsTraverse(bnode, ref itype, false, null, ProtoCore.DSASM.AssociativeSubCompilePass.kNone);
                            DfsTraverse(langBlockNode, ref itype, false, null, subPass);
                        }
                        else
                        {
                            DfsTraverse(bnode, ref itype, false, null, subPass);
                        }

                        if (NodeUtils.IsReturnExpressionNode(bnode))
                            hasReturnStatement = true;
                    }
                    EmitCompileLogFunctionEnd();

                    // All locals have been stack allocated, update the local count of this function
                    localProcedure.localCount = compileStateTracker.BaseOffset;

                    if (ProtoCore.DSASM.Constants.kInvalidIndex == globalClassIndex)
                    {
                        localProcedure.localCount = compileStateTracker.BaseOffset;

                        // Update the param stack indices of this function
                        foreach (ProtoCore.DSASM.SymbolNode symnode in codeBlock.symbolTable.symbolList.Values)
                        {
                            if (symnode.functionIndex == localProcedure.procId && symnode.isArgument)
                            {
                                symnode.index -= localProcedure.localCount;
                            }
                        }
                    }
                    else
                    {
                        compileStateTracker.ClassTable.ClassNodes[globalClassIndex].vtable.procList[localProcedure.procId].localCount = compileStateTracker.BaseOffset;

                        // Update the param stack indices of this function
                        foreach (ProtoCore.DSASM.SymbolNode symnode in compileStateTracker.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList.Values)
                        {
                            if (symnode.functionIndex == localProcedure.procId && symnode.isArgument)
                            {
                                symnode.index -= localProcedure.localCount;
                            }
                        }
                    }

                    ProtoCore.Lang.JILActivationRecord record = new ProtoCore.Lang.JILActivationRecord();
                    record.pc = localProcedure.pc;
                    record.locals = localProcedure.localCount;
                    record.classIndex = globalClassIndex;
                    record.funcIndex = localProcedure.procId;
                    fep = new ProtoCore.Lang.JILFunctionEndPoint(record);
                }
                else if (funcDef.BuiltInMethodId != ProtoCore.Lang.BuiltInMethods.MethodID.kInvalidMethodID)
                {
                    fep = new ProtoCore.Lang.BuiltInFunctionEndPoint(funcDef.BuiltInMethodId);
                }
                else
                {
                    ProtoCore.Lang.JILActivationRecord jRecord = new ProtoCore.Lang.JILActivationRecord();
                    jRecord.pc = localProcedure.pc;
                    jRecord.locals = localProcedure.localCount;
                    jRecord.classIndex = globalClassIndex;
                    jRecord.funcIndex = localProcedure.procId;

                    // TODO Jun/Luke: Wrap this into Core.Options and extend if needed
                  /*  bool isCSFFI = false;
                    if (isCSFFI)
                    {
                        ProtoCore.Lang.CSFFIActivationRecord record = new ProtoCore.Lang.CSFFIActivationRecord();
                        record.JILRecord = jRecord;
                        record.FunctionName = funcDef.Name;
                        record.ModuleName = funcDef.ExternLibName;
                        record.ModuleType = "dll";
                        record.IsDNI = funcDef.IsDNI;
                        record.ReturnType = funcDef.ReturnType;
                        record.ParameterTypes = localProcedure.argTypeList;
                        fep = new ProtoCore.Lang.CSFFIFunctionEndPoint(record);
                    }
                    else
                    {*/
                        ProtoCore.Lang.FFIActivationRecord record = new ProtoCore.Lang.FFIActivationRecord();
                        record.JILRecord = jRecord;
                        record.FunctionName = funcDef.Name;
                        record.ModuleName = funcDef.ExternLibName;
                        record.ModuleType = "dll";
                        record.IsDNI = funcDef.IsDNI;
                        record.ReturnType = funcDef.ReturnType;
                        record.ParameterTypes = localProcedure.argTypeList;
                        fep = new ProtoCore.Lang.FFIFunctionEndPoint(record);
                    //}
                }

                // Construct the fep arguments
                fep.FormalParams = new ProtoCore.Type[localProcedure.argTypeList.Count];
                fep.BlockScope = codeBlock.codeBlockId;
                fep.ClassOwnerIndex = localProcedure.classScope;
                fep.procedureNode = localProcedure;
                localProcedure.argTypeList.CopyTo(fep.FormalParams, 0);

                // TODO Jun: 'classIndexAtCallsite' is the class index as it is stored at the callsite function tables
                // Determine whether this still needs to be aligned to the actual 'classIndex' variable
                // The factors that will affect this is whether the 2 function tables (compiler and callsite) need to be merged
                int classIndexAtCallsite = globalClassIndex + 1;
                FunctionGroup functionGroup = compileStateTracker.FunctionTable.GetFunctionGroup(classIndexAtCallsite, funcDef.Name);
                if (functionGroup != null)
                {
                    functionGroup.FunctionEndPoints.Add(fep);
                }
                else
                {
                    // If any functions in the base class have the same name, append them here
                    FunctionGroup basegroup = null;

                    int ci = classIndexAtCallsite - 1;
                    if (ci != Constants.kInvalidIndex)
                    {
                        ProtoCore.DSASM.ClassNode cnode = compileStateTracker.ClassTable.ClassNodes[ci];
                        if (cnode.baseList.Count > 0)
                        {
                            Validity.Assert(1 == cnode.baseList.Count, "We don't support multiple inheritance yet");
                            basegroup = compileStateTracker.FunctionTable.GetFunctionGroup(cnode.baseList[0] + 1, funcDef.Name);
                        }
                    }

                    if (basegroup == null)
                    {
                        compileStateTracker.FunctionTable.AddFunctionEndPointer(classIndexAtCallsite, funcDef.Name, fep);
                    }
                    else
                    {
                        // Copy all non-private feps from the basegroup into this the new group
                        FunctionGroup newGroup = new FunctionGroup();
                        newGroup.CopyVisible(basegroup.FunctionEndPoints);
                        newGroup.FunctionEndPoints.Add(fep);

                        foreach (var newfep in newGroup.FunctionEndPoints)
                        {
                            compileStateTracker.FunctionTable.AddFunctionEndPointer(classIndexAtCallsite, funcDef.Name, newfep);
                        }

                    }
                }

                if (!hasReturnStatement && !funcDef.IsExternLib)
                {
                    if (!compileStateTracker.Options.SuppressFunctionResolutionWarning)
                    {
                        string message = String.Format(ProtoCore.BuildData.WarningMessage.kFunctionNotReturnAtAllCodePaths, localProcedure.name);
                        buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kMissingReturnStatement, message, compileStateTracker.CurrentDSFileName, funcDef.line, funcDef.col);
                    }
                    EmitReturnNull();
                }

                if (compileStateTracker.Options.DisableDisposeFunctionDebug)
                {
                    if (node.Name.Equals(ProtoCore.DSDefinitions.Keyword.Dispose))
                    {
                        compileStateTracker.Options.EmitBreakpoints = true;
                    }
                }
            }

            compileStateTracker.ProcNode = localProcedure = null;
            codeBlock.blockType = origCodeBlockType;
            globalProcIndex = ProtoCore.DSASM.Constants.kGlobalScope;
            localFunctionDefNode = null;
            compileStateTracker.BaseOffset = 0;
            argOffset = 0;
            isAssocOperator = false;
        }