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