/// <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); } }
static int callMain(Type t, Method m) { // check parameter type and build main arguments List args; List pars = m.@params(); if (pars.sz() == 0) { args = null; } else if (((Param)pars.get(0)).type().@is(Sys.StrType.toListOf()) && (pars.sz() == 1 || ((Param)pars.get(1)).hasDefault())) { args = new List(Sys.ObjType, new object[] { Env.cur().args() }); } else { System.Console.WriteLine("ERROR: Invalid parameters for main: " + m.signature()); return(-1); } // invoke try { if (m.isStatic()) { return(toResult(m.callList(args))); } else { return(toResult(m.callOn(t.make(), args))); } } catch (Err.Val ex) { ex.err().trace(); return(-1); } }
////////////////////////////////////////////////////////////////////////// // Complex ////////////////////////////////////////////////////////////////////////// /// <summary> /// complex := type [fields] /// fields := "{" field (eos field)* "}" /// field := name "=" obj /// </summary> private object readComplex(int line, Type t, bool root) { Map toSet = new Map(Sys.FieldType, Sys.ObjType.toNullable()); List toAdd = new List(Sys.ObjType.toNullable()); // read fields/collection into toSet/toAdd readComplexFields(t, toSet, toAdd); // get the make constructor Method makeCtor = t.method("make", false); if (makeCtor == null || !makeCtor.isPublic()) { throw err("Missing public constructor " + t.qname() + ".make", line); } // get argument lists List args = null; if (root && options != null) { args = (List)options.get("makeArgs"); } // construct object object obj = null; bool setAfterCtor = true; try { // if first parameter is an function then pass toSet // as an it-block for setting the fields Param p = (Param)makeCtor.@params().first(); if (args == null && p != null && p.type().fits(Sys.FuncType)) { args = new List(Sys.ObjType).add(Field.makeSetFunc(toSet)); setAfterCtor = false; } // invoke make to construct object obj = makeCtor.callList(args); } catch (System.Exception e) { throw err("Cannot make " + t + ": " + e, line, e); } // set fields (if not passed to ctor as it-block) if (setAfterCtor && toSet.size() > 0) { IDictionaryEnumerator en = toSet.pairsIterator(); while (en.MoveNext()) { complexSet(obj, (Field)en.Key, en.Value, line); } } // add if (toAdd.size() > 0) { Method addMethod = t.method("add", false); if (addMethod == null) { throw err("Method not found: " + t.qname() + ".add", line); } for (int i = 0; i < toAdd.sz(); ++i) { complexAdd(t, obj, addMethod, toAdd.get(i), line); } } return(obj); }