Пример #1
0
        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()));
        }