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