/* * synchronized Class emit() * { * if (cls == null) * cls = FPodEmit.emitAndLoad(fpod); * return cls; * } * * synchronized void precompiled(Class cls) * throws Exception * { * this.cls = cls; * FPodEmit.initFields(fpod, cls); * } */ internal Type findType(int qname) { if (qname == 0xFFFF || qname == -1) { return(null); } // lookup type with typeRef index FTypeRef reference = fpod.typeRef(qname); // if generic instance, then this type must be used in a method // signature, not type meta-data (b/c I can't subclass generic types), // so it's safe that my pod has been loaded and is now registered (in // case the generic type is parameterized via types in my pod) if (reference.isGenericInstance()) { return(TypeParser.load(reference.signature, true, this)); } // otherwise I need to handle if I am loading my own pod, because // I might not yet be added to the system namespace if I'm just // loading my own hollow types string podName = reference.podName; string typeName = reference.typeName; Pod pod = podName == m_name ? this : doFind(podName, true, null); Type type = pod.type(typeName, false); if (type != null) { if (reference.isNullable()) { type = type.toNullable(); } return(type); } // handle generic parameter types (for sys pod only) if (m_name == "sys") { type = Sys.genericParamType(typeName); if (type != null) { if (reference.isNullable()) { type = type.toNullable(); } return(type); } } // lost cause throw UnknownTypeErr.make(podName + "::" + typeName).val; }
private void loadType(FTypeRef tref) { string podName = tref.podName; string typeName = tref.typeName; // if pod is "sys", then we can perform a shortcut and use // one of the predefined fields in Sys if (!tref.isGenericInstance() && podName == "sys") { PERWAPI.Field field = emitter.findField("Fan.Sys.Sys", typeName + "Type", "Fan.Sys.Type"); code.FieldInst(FieldOp.ldsfld, field); if (tref.isNullable()) { typeToNullable(); } return; } // lazy allocate my parent's type literal map: sig -> fieldName if (parent.typeLiteralFields == null) { parent.typeLiteralFields = new Hashtable(); } Hashtable map = parent.typeLiteralFields; // types are lazy loaded and then cached in a private static field called // type$literal$count which will get generated by FTypeEmit (we keep track of signature // to fieldname in the typeConstFields map) string sig = tref.signature; string fieldName = (string)map[sig]; if (fieldName == null) { fieldName = "type$literal$" + map.Count; map[sig] = fieldName; } //int fieldRef = emit.field(parent.className + "." + fieldName + ":Lfan/sys/Type;"); //code.op2(GETSTATIC, fieldRef); //code.op(DUP); //int nonNull = code.branch(IFNONNULL); //code.op(POP); //code.op2(LDC_W, emit.strConst(sig)); //code.op(ICONST_1); //code.op2(INVOKESTATIC, parent.sysFindType()); //code.op(DUP); //code.op2(PUTSTATIC, fieldRef); //code.mark(nonNull); //emitter.EmitField(string name, string type, FieldAttr attr) //PERWAPI.Field field = emitter.EmitField("Fan.Sys.Sys", typeName + "Type", "Fan.Sys.Type"); //code.FieldInst(FieldOp.ldsfld, field); // TODO - store in static field (all that crap above this) code.ldstr(sig); Method method = emitter.findMethod("Fan.Sys.Type", "find", new string[] { "System.String" }, "Fan.Sys.Type"); code.MethInst(MethodOp.call, method); }
////////////////////////////////////////////////////////////////////////// // Compare ////////////////////////////////////////////////////////////////////////// private void compareEQ() { FTypeRef lhs = pod.typeRef(u2()); FTypeRef rhs = pod.typeRef(u2()); // if this is a.equals(b) and we know a is non-null, then just call equals if (lhs.isRef() && !lhs.isNullable() && rhs.isRef()) { PERWAPI.Method m = emitter.findMethod("System.Object", "Equals", new string[] { "System.Object" }, "System.Boolean"); m.AddCallConv(CallConv.Instance); code.MethInst(MethodOp.callvirt, m); return; } doCompare("EQ", lhs, rhs); }
private void coerce() { FTypeRef from = pod.typeRef(u2()); FTypeRef to = pod.typeRef(u2()); // Bool boxing/unboxing if (from.isBoolPrimitive()) { if (to.isRef()) { boolBox(); return; } throw new Exception("Coerce " + from + " => " + to); } if (to.isBoolPrimitive()) { if (from.isRef()) { boolUnbox(!from.isBool()); return; } throw new Exception("Coerce " + from + " => " + to); } // Int boxing/unboxing if (from.isIntPrimitive()) { if (to.isRef()) { intBox(); return; } throw new Exception("Coerce " + from + " => " + to); } if (to.isIntPrimitive()) { if (from.isRef()) { intUnbox(!from.isInt()); return; } throw new Exception("Coerce " + from + " => " + to); } // Float boxing/unboxing if (from.isFloatPrimitive()) { if (to.isRef()) { floatBox(); return; } throw new Exception("Coerce " + from + " => " + to); } if (to.isFloatPrimitive()) { if (from.isRef()) { floatUnbox(!from.isFloat()); return; } throw new Exception("Coerce " + from + " => " + to); } // check nullable => non-nullable if (from.isNullable() && !to.isNullable()) { CILLabel nonnull = code.NewLabel(); code.Inst(Op.dup); code.Inst(Op.ldnull); code.Branch(BranchOp.bne_un_s, nonnull); if (parent.NullErrMakeCoerce == null) { parent.NullErrMakeCoerce = emitter.findMethod("Fan.Sys.NullErr", "makeCoerce", new string[0], "Fan.Sys.Err/Val"); } code.MethInst(MethodOp.call, parent.NullErrMakeCoerce); code.Inst(Op.throwOp); code.CodeLabel(nonnull); } // don't bother casting to obj if (to.isObj()) { return; } code.TypeInst(TypeOp.castclass, emitter.findType(to.nname())); }