/// <summary> /// Emit a mixin router from a class to the mixin body methods. /// </summary> public void emitMixinRouter(Method m) { string parent = FanUtil.toDotnetTypeName(m.parent()); string name = FanUtil.toDotnetMethodName(m.name()); string ret = FanUtil.toDotnetTypeName(m.inheritedReturns()); string[] parTypes = new string[] { parent }; List pars = m.@params(); int paramCount = pars.sz(); // find first param with default value int firstDefault = paramCount; for (int i = 0; i < paramCount; i++) { if (((Param)pars.get(i)).hasDefault()) { firstDefault = i; break; } } // generate routers for (int i = firstDefault; i <= paramCount; i++) { string[] myParams = new string[i]; string[] myParamNames = new string[i]; string[] implParams = new string[i + 1]; implParams[0] = parent; for (int j = 0; j < i; j++) { Param param = (Param)m.@params().get(j); Type pt = param.type(); string s = FanUtil.toDotnetTypeName(pt); myParams[j] = s; myParamNames[j] = param.name(); implParams[j + 1] = s; } // CLR requires public virtual PERWAPI.MethAttr attr = PERWAPI.MethAttr.Public | PERWAPI.MethAttr.Virtual; PERWAPI.CILInstructions code = emitter.emitMethod(name, ret, myParamNames, myParams, attr, new string[0], new string[0]); code.Inst(PERWAPI.Op.ldarg_0); // push this for (int p = 0; p < i; p++) { // push args Param param = (Param)m.@params().get(p); FCodeEmit.loadVar(code, FanUtil.toDotnetStackType(param.type()), p + 1); } PERWAPI.Method meth = emitter.findMethod(parent + "_", name, implParams, ret); code.MethInst(PERWAPI.MethodOp.call, meth); code.Inst(PERWAPI.Op.ret); } }
////////////////////////////////////////////////////////////////////////// // Code Utils ////////////////////////////////////////////////////////////////////////// /// <summary> /// Push the specified number of arguments onto the stack. /// </summary> private void pushArgs(PERWAPI.CILInstructions code, bool self, int count) { if (self) { code.Inst(PERWAPI.Op.ldarg_0); } for (int i = 0; i < count; i++) { FTypeRef var = emit.pod.typeRef(method.m_vars[i].type); FCodeEmit.loadVar(code, var.stackType, self ? i + 1 : i); } }