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); } }