/// <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); } }
private PERWAPI.CILInstructions doEmit(string[] localNames, string[] localTypes) { int paramCount = paramLen; if (self) { paramCount++; } string[] parNames = new string[paramCount]; string[] parTypes = new string[paramCount]; for (int i = 0; i < paramCount; i++) { int z = i; if (self) { z--; } if (self && i == 0) { parNames[0] = "self"; parTypes[0] = selfName; } else { parNames[i] = method.m_vars[z].name; parTypes[i] = emit.nname(method.m_vars[z].type); } } if (localNames == null) { localNames = new string[method.m_localCount]; localTypes = new string[method.m_localCount]; for (int i = 0; i < method.m_localCount; i++) { int z = i + paramCount; if (self) { z--; } localNames[i] = method.m_vars[z].name; localTypes[i] = emit.nname(method.m_vars[z].type); } } /* * PERWAPI.MethAttr attr; * if (isPrivate) attr = PERWAPI.MethAttr.Public; //PERWAPI.MethAttr.Private; * else if (isInternal) attr = PERWAPI.MethAttr.Assembly; * else attr = PERWAPI.MethAttr.Public; */ PERWAPI.MethAttr attr = isInternal ? PERWAPI.MethAttr.Assembly : PERWAPI.MethAttr.Public; if (isStatic) { attr |= PERWAPI.MethAttr.Static; } if (isAbstract) { attr |= PERWAPI.MethAttr.Abstract; } if (isVirtual) { attr |= PERWAPI.MethAttr.Virtual; } if (isOverride) { attr |= PERWAPI.MethAttr.Virtual; } if (isHide) { attr |= PERWAPI.MethAttr.HideBySig; } PERWAPI.CILInstructions code = emitter.emitMethod(name, ret.nname(), parNames, parTypes, attr, localNames, localTypes); if (this.code != null) { new FCodeEmit(emit, method, code).emit(); } return(code); }