private static void GetTypesAndAttrs(FunctionDefinition node, SignatureInfo sigInfo, int offset, out Type[] typeArr, out CustomAttributeBuilder[] cabs)
            {
                typeArr = CompilerHelpers.MakeRepeatedArray(typeof(object), sigInfo.ParamNames.Length - offset);
                cabs = null;
                int curIndex = typeArr.Length - 1;
                if ((node.Flags & FunctionAttributes.KeywordDictionary) != 0) {
                    typeArr[curIndex] = typeof(Dict);
                    cabs = new CustomAttributeBuilder[typeArr.Length];
                    cabs[curIndex] = new CustomAttributeBuilder(typeof(ParamDictAttribute).GetConstructor(new Type[0]), Ops.EMPTY);

                    curIndex--;
                }
                if ((node.Flags & FunctionAttributes.ArgumentList) != 0) {
                    if (cabs == null) cabs = new CustomAttributeBuilder[typeArr.Length];

                    typeArr[curIndex] = typeof(object[]);
                    cabs[curIndex] = new CustomAttributeBuilder(typeof(ParamArrayAttribute).GetConstructor(new Type[0]), Ops.EMPTY);

                    curIndex--;
                }
            }
            private CodeGen CreateNewMethod(FunctionDefinition node, CodeGen typeCctor, SignatureInfo sigInfo)
            {
                string strName = node.Name.GetString();
                MethodAttributes attrs = GetMethodAttributes(node, strName);

                int offset = (sigInfo.HasContext ? 2 : 1);
                if ((attrs & MethodAttributes.Static) != 0) offset--;

                if (node.Parameters.Count == 0 && (attrs & MethodAttributes.Static) == 0)
                    throw new CompilerException(String.Format("defining non-static method {0} with no parameters.  Add self or @staticmethod decorator", node.Name), node, this.compctx.SourceFile);

                Debug.Assert(sigInfo.ParamNames.Length >= offset,
                    "less param names then offset",
                    String.Format("Params: {0} Offset: {1}: Context: {2} Attrs: {3} Name: {4}",
                        sigInfo.ParamNames.Length, offset, sigInfo.HasContext, attrs, strName));

                string[] paramNames = new string[sigInfo.ParamNames.Length - offset];
                for (int i = 0; i < paramNames.Length; i++)
                    paramNames[i] = sigInfo.ParamNames[i + offset].GetString();

                Type[] typeArr;
                CustomAttributeBuilder[] cabs;
                GetTypesAndAttrs(node, sigInfo, offset, out typeArr, out cabs);

                object[] funcDefaults = GetStaticDefaults(node, paramNames.Length);
                MethodInfo baseMethod = GetMethodOverload(strName, attrs);

                Type retType;
                if (baseMethod == null) {
                    // Check whether the method has a return statement, to decide whether it should
                    // return void or object
                    ReturnStatementFinder finder = new ReturnStatementFinder(node);
                    node.Walk(finder);
                    retType = finder.FoundReturnStatement ? typeof(object) : typeof(void);
                } else {
                    // Get the return and param types from the base method
                    typeArr = CompilerHelpers.GetTypes(baseMethod.GetParameters());
                    retType = baseMethod.ReturnType;
                    attrs |= MethodAttributes.Virtual;
                }

                CodeGen icg = typeCctor.typeGen.DefineMethod(attrs,
                         strName,
                         retType,
                         typeArr,
                         paramNames,
                         funcDefaults,
                         cabs);

                icg.Context = compctx;

                if (baseMethod != null) icg.methodToOverride = baseMethod;

                icg.Names = CodeGen.CreateLocalNamespace(icg);
                for (int arg = offset; arg < sigInfo.ParamNames.Length; arg++) {
                    icg.Names.SetSlot(sigInfo.ParamNames[arg], icg.GetArgumentSlot(arg - offset));
                }

                if ((attrs & MethodAttributes.Static) == 0) {
                    icg.Names.SetSlot(sigInfo.ParamNames[offset - 1], new ArgSlot(0, typeCctor.typeGen.myType, icg));
                }

                icg.ContextSlot = stack.Peek().Type.moduleSlot;

                EmitArgsToTuple(node, icg, sigInfo, paramNames.Length);
                return icg;
            }
            private static void EmitArgsToTuple(FunctionDefinition fd, CodeGen icg, SignatureInfo sigInfo, int cnt)
            {
                if ((fd.Flags & FunctionAttributes.ArgumentList) != 0) {
                    // transform params object[] into tuple on call...

                    LocalBuilder lb = icg.DeclareLocal(typeof(object));
                    Slot argsSlot = new LocalSlot(lb, icg);
                    int index;

                    if ((fd.Flags & FunctionAttributes.KeywordDictionary) != 0) {
                        index = sigInfo.ParamNames.Length - 2;
                        icg.EmitArgGet(cnt - 2);
                    } else {
                        index = sigInfo.ParamNames.Length - 1;
                        icg.EmitArgGet(cnt - 1);
                    }

                    icg.EmitCall(typeof(Tuple), "MakeTuple");
                    argsSlot.EmitSet(icg);
                    lb.SetLocalSymInfo(sigInfo.ParamNames[index].GetString());
                    icg.Names.SetSlot(sigInfo.ParamNames[index], argsSlot);
                }
            }