コード例 #1
0
        /// <summary>
        /// Makes a new static field slot.  Type is ignored.  If we ever change ignoring type then we
        /// need to make BuiltinWrapper generic and update StaticFieldBuiltinSlot to get the correct
        /// type.
        /// </summary>
        public override Slot MakeSlot(Name name, Type type)
        {
            StaticFieldSlot fs;
            object          builtin;

            if (!fields.TryGetValue(name, out fs))
            {
                if (!TypeCache.Builtin.TryGetSlot(DefaultContext.Default, SymbolTable.StringToId(name.GetString()), out builtin))
                {
                    // name does not collide w/ a built-in name, define a real field.

                    FieldBuilder fb = typeGen.myType.DefineField(name.GetString(), typeof(object), FieldAttributes.Public | FieldAttributes.Static);
                    fs = new StaticFieldSlot(fb);
                }
                else
                {
                    // name collides w/ a built-in name.  Our field becomes strongly typed to
                    // BuiltinWrapper.  We then return a
                    // StaticFieldBuiltinSlot which checks the value to see if it's a built-in or
                    // not.

                    FieldBuilder fb = typeGen.myType.DefineField(name.GetString(), typeof(BuiltinWrapper), FieldAttributes.Public | FieldAttributes.Static);
                    fs = new StaticFieldBuiltinSlot(fb);
                }
                fields[name] = fs;
            }
            return(fs);
        }
コード例 #2
0
        //
        // This generates a method like the following:
        //
        //  TryGetExtraValue(int name, object out value) {
        //      if (name1 == name) {
        //          value = type.name1Slot;
        //          return true;
        //      }
        //      if (name2 == name) {
        //          value = type.name2Slot;
        //          return true;
        //      }
        //      ...
        //      return false
        //  }

        private void MakeGetMethod()
        {
            CodeGen cg = tg.DefineMethodOverride(typeof(CustomFieldIdDict).GetMethod("TryGetExtraValue"));

            foreach (KeyValuePair <Name, Slot> entry in names.Slots)
            {
                cg.EmitSymbolIdInt(entry.Key.GetString());
                cg.EmitArgAddr(0);
                cg.EmitFieldGet(typeof(SymbolId), "Id");

                Label next = cg.DefineLabel();
                cg.Emit(OpCodes.Bne_Un, next);

                cg.EmitArgGet(1);

                // ugly special casing builtins this way, but they're special...
                // Builtins can be in one of two states:
                //      Not defined, but available internally to the module
                //      Defined, and exposed externally from the module.
                // In both cases we have static fields for these, and we're in the custom dict.
                //
                // Therefore we keep track of which state they're in w/ a wrapper object,
                // and here we need to emit the real value, not the value that's availble
                // internally to the module.

                StaticFieldBuiltinSlot builtin = entry.Value as StaticFieldBuiltinSlot;
                if (builtin == null)
                {
                    entry.Value.EmitGet(cg);
                }
                else
                {
                    builtin.EmitGetRaw(cg);
                }

                cg.Emit(OpCodes.Stind_Ref);
                cg.EmitInt(1);
                cg.EmitReturn();
                cg.MarkLabel(next);
            }
            cg.EmitInt(0);
            cg.EmitReturn();
            cg.Finish();
        }