Exemple #1
0
        internal bool TryLookupSlotInBases(ICallerContext context, SymbolId name, out object ret)
        {
            Tuple resOrder = MethodResolutionOrder;

            for (int i = 1; i < resOrder.Count; i++)    // skip our own type...
            {
                object type = resOrder[i];

                PythonType pt = type as PythonType;
                if (pt != null)
                {
                    if (pt.TryGetSlot(context, name, out ret))
                    {
                        // respect MRO for base class lookups: method wrappers are
                        // logically a member of a super type, but are available on
                        // derived types for quick access.  We only want to return a method
                        // wrapper here if it's actually exposed on our type.

                        MethodWrapper mw = ret as MethodWrapper;
                        if (mw == null || !mw.IsSuperTypeMethod())
                        {
                            return(true);
                        }
                    }
                }
                else if (Ops.TryGetAttr(context, type, name, out ret))
                {
                    return(true);
                }
            }
            ret = null;
            return(false);
        }
Exemple #2
0
        public List GetAttrNames(ICallerContext context)
        {
            FieldIdDict attrs = new FieldIdDict(__dict__);

            OldClass.RecurseAttrHierarchy(this.__class__, attrs);
            return(List.Make(attrs));
        }
Exemple #3
0
        public static Tuple OpenPipedCommandAll(ICallerContext context, string command, string mode, int bufsize)
        {
            if (String.IsNullOrEmpty(mode))
            {
                mode = "t";
            }
            if (mode != "t" && mode != "b")
            {
                throw Ops.ValueError("mode must be 't' or 'b' (default is t)");
            }
            if (mode == "t")
            {
                mode = String.Empty;
            }

            ProcessStartInfo psi = GetProcessInfo(command);

            psi.RedirectStandardInput  = true;
            psi.RedirectStandardOutput = true;
            psi.RedirectStandardError  = true;
            Process p = Process.Start(psi);

            return(Tuple.MakeTuple(new POpenFile(context, command, p, p.StandardInput.BaseStream, "w" + mode),
                                   new POpenFile(context, command, p, p.StandardOutput.BaseStream, "r" + mode),
                                   new POpenFile(context, command, p, p.StandardError.BaseStream, "r+" + mode)));
        }
Exemple #4
0
        public static PythonFile OpenPipedCommand(ICallerContext context, string command, string mode, int bufsize)
        {
            if (String.IsNullOrEmpty(mode))
            {
                mode = "r";
            }
            ProcessStartInfo psi = GetProcessInfo(command);
            Process          p;
            PythonFile       res;

            switch (mode)
            {
            case "r":
                psi.RedirectStandardOutput = true;
                p = Process.Start(psi);

                res = new POpenFile(context, command, p, p.StandardOutput.BaseStream, "r");
                break;

            case "w":
                psi.RedirectStandardInput = true;
                p = Process.Start(psi);

                res = new POpenFile(context, command, p, p.StandardInput.BaseStream, "w");
                break;

            default:
                throw Ops.ValueError("expected 'r' or 'w' for mode, got {0}", mode);
            }

            return(res);
        }
        public List GetAttrNames(ICallerContext context)
        {
            List ret = new List(((IDictionary <object, object>)__dict__).Keys);

            ret.Extend(TypeCache.SystemState.GetAttrNames(context, this));
            return(ret);
        }
Exemple #6
0
        public static object Open(ICallerContext context, string filename, int flag, int mode)
        {
            FileStream fs = File.Open(filename, FileModeFromFlags(flag), FileAccessFromFlags(flag));
            PythonFile pf = PythonFile.Make(context, null, fs);

            return(PythonFileManager.GetIdFromFile(pf));
        }
Exemple #7
0
        public virtual bool TryGetAttr(ICallerContext context, SymbolId name, out object value)
        {
            switch (name.Id)
            {
            case SymbolTable.NameId: value = __name__; return(true);

            case SymbolTable.BasesId: value = BaseClasses; return(true);

            case SymbolTable.ClassId: value = Ops.GetDynamicType(this); return(true);

            case SymbolTable.SubclassesId:
                ReflectedMethod rm = new ReflectedMethod("__subclasses__", typeof(ReflectedType).GetMethod("__subclasses__"), FunctionType.PythonVisible | FunctionType.Method);;
                rm.inst = this;
                value   = rm;
                return(true);

            default:
                if (TryLookupSlot(context, name, out value))
                {
                    value = Ops.GetDescriptor(value, null, this);
                    return(true);
                }
                break;
            }

            return(false);
        }
Exemple #8
0
        /// <summary>
        /// Gateway into importing ... called from Ops.  This is called after
        /// importing the module and is used to return individual items from
        /// the module.  The outer modules dictionary is then updated with the
        /// result.
        /// </summary>
        internal static object ImportFrom(ICallerContext context, object mod, string name)
        {
            PythonModule from = mod as PythonModule;

            if (from != null)
            {
                object ret;
                if (from.TryGetAttr(from, SymbolTable.StringToId(name), out ret))
                {
                    return(ret);
                }
                else
                {
                    return(ImportNested(from, name));
                }
            }
            else
            {
                object ret;
                if (Ops.TryGetAttr(context, mod, SymbolTable.StringToId(name), out ret))
                {
                    return(ret);
                }
                else
                {
                    throw Ops.ImportError("No module named {0}", name);
                }
            }
        }
Exemple #9
0
        public int GetExitCode(ICallerContext context)
        {
            object pyObj = ExceptionConverter.ToPython(this);

            object args;

            if (!Ops.TryGetAttr(pyObj, SymbolTable.Arguments, out args))
            {
                return(0);
            }
            Tuple t = args as Tuple;

            if (t == null || t.Count == 0)
            {
                return(0);
            }

            try {
                return(Converter.ConvertToInt32(t[0]));
            } catch {
            }

            try {
                Ops.PrintWithDest(context.SystemState, context.SystemState.stderr, t[0]);
            } catch {
            }

            return(1);
        }
Exemple #10
0
        public bool TryGetAttr(ICallerContext context, SymbolId name, out object value)
        {
            if (name.Id == SymbolTable.DictId)
            {
                //!!! user code can modify __del__ property of __dict__ behind our back
                value = __dict__;
                return(true);
            }
            else if (name.Id == SymbolTable.Class.Id)
            {
                value = __class__;
                return(true);
            }

            if (TryRawGetAttr(name, out value))
            {
                return(true);
            }

            if (name.Id != SymbolTable.GetAttrId)
            {
                object getattr;
                if (TryRawGetAttr(SymbolTable.GetAttr, out getattr))
                {
                    value = Ops.Call(getattr, SymbolTable.IdToString(name));
                    return(true);
                }
            }

            return(false);
        }
Exemple #11
0
        object ICallableWithCallerContext.Call(ICallerContext context, object[] args)
        {
            object newMethod, newObject;


            newMethod = Ops.GetAttr(context, this, SymbolTable.NewInst);
            newObject = Ops.CallWithContext(context, newMethod, PrependThis(args));

            if (newObject == null)
            {
                return(null);
            }

            if (Ops.GetDynamicType(newObject).IsSubclassOf(this))
            {
                object init;
                if (PythonType.TryLookupSpecialMethod(DefaultContext.Default, newObject, SymbolTable.Init, out init))
                {
                    switch (args.Length)
                    {
                    case 0: Ops.CallWithContext(context, init); break;

                    case 1: Ops.CallWithContext(context, init, args[0]); break;

                    case 2: Ops.CallWithContext(context, init, args[0], args[1]); break;

                    default: Ops.CallWithContext(context, init, args); break;
                    }
                }
            }

            return(newObject);
        }
Exemple #12
0
        public List GetAttrNames(ICallerContext context)
        {
            List list;

            if (dict == null)
            {
                list = List.Make();
            }
            else
            {
                list = List.Make(dict);
            }
            list.AddNoLock(SymbolTable.Module.ToString());

            List reflectedAttrs = GetDynamicType().GetAttrNames(context, this);

            foreach (object o in reflectedAttrs)
            {
                if (list.Contains(o))
                {
                    continue;
                }
                list.AddNoLock(o);
            }
            return(list);
        }
Exemple #13
0
        public override void SetAttr(ICallerContext context, object self, SymbolId name, object value)
        {
            if (name == SymbolTable.Class)
            {
                // check that this is a legal new class
                UserType newType = value as UserType;
                if (newType == null)
                {
                    throw Ops.TypeError("__class__ must be set to new-style class, not '{0}' object", Ops.GetDynamicType(value).__name__);
                }
                if (newType.type != this.type)
                {
                    throw Ops.TypeError("__class__ assignment: '{0}' object layout differs from '{1}'", __name__, newType.__name__);
                }
                ((ISuperDynamicObject)self).SetDynamicType(newType);
                return;
            }

            if (__setattr__F.IsObjectMethod())
            {
                BaseSetAttr(context, (ISuperDynamicObject)self, name, value);
            }
            else
            {
                __setattr__F.Invoke(self, SymbolTable.IdToString(name), value);
            }
        }
Exemple #14
0
        public void SetAttr(ICallerContext context, SymbolId name, object value)
        {
            switch (name.Id)
            {
            case SymbolTable.BasesId: __bases__ = ValidateBases(value); break;

            case SymbolTable.NameId:
                string n = value as string;
                if (n == null)
                {
                    throw Ops.TypeError("TypeError: __name__ must be a string object");
                }
                __name__ = n;
                break;

            case SymbolTable.DictId:
                IAttributesDictionary d = value as IAttributesDictionary;
                if (d == null)
                {
                    throw Ops.TypeError("__dict__ must be set to dictionary");
                }
                __dict__ = d;
                break;

            case SymbolTable.UnassignId:
                hasFinalizer = true;
                goto default;

            default:
                __dict__[name] = value;
                break;
            }
        }
Exemple #15
0
        public static List Dir(ICallerContext context, object o)
        {
            List ret = Ops.GetAttrNames(context, o);

            ret.Sort();
            return(ret);
        }
Exemple #16
0
        public void DeleteAttr(ICallerContext context, SymbolId name)
        {
            switch (name.Id)
            {
            case SymbolTable.ClassId: throw Ops.TypeError("__class__ must be set to class");

            case SymbolTable.DictId: throw Ops.TypeError("__dict__ must be set to a dictionary");

            default:
                if (name == SymbolTable.Unassign)
                {
                    // removing finalizer
                    if (HasFinalizer() && !__class__.HasFinalizer)
                    {
                        ClearFinalizer();
                    }
                }

                if (!__dict__.Remove(name))
                {
                    throw Ops.AttributeError("{0} is not a valid attribute", SymbolTable.IdToString(name));
                }
                break;
            }
        }
 public void DeleteAttr(ICallerContext context, SymbolId name)
 {
     if (!GetTypeMap().Remove(name))
     {
         throw Ops.AttributeError("namespace {0} has no type/nested namespace {1}", myNamespace, name);
     }
 }
Exemple #18
0
        private void Initialize(ICallerContext context)
        {
            int prevVal = Interlocked.CompareExchange(ref initialized, 1, 0);

            if (prevVal == 2)
            {
                return;                 // fully initialized, leave...
            }
            if (prevVal != 0)
            {
                while (Thread.VolatileRead(ref initialized) != 2)
                {
                    Thread.SpinWait(10000);
                }
                return;
            }

            try {
                AddInterfaces(context);
                Interlocked.Exchange(ref initialized, 2);
            } catch {
                // initialization failed.
                Interlocked.Exchange(ref initialized, 0);
                throw;
            }
        }
Exemple #19
0
        private static Type GetInterfaceForGuid(ICallerContext context, Guid typeInfoGuid, IntPtr typeInfoPtr)
        {
            Type interfaceType;

            if (ComTypeCache.TryGetValue(typeInfoGuid, out interfaceType) == false)
            {
                Assembly interopAssembly = SearchForInteropAssembly(typeInfoGuid);

                if (interopAssembly != null)
                {
                    context.SystemState.TopPackage.LoadAssembly(context.SystemState, interopAssembly, false);
                    ComTypeCache.TryGetValue(typeInfoGuid, out interfaceType);
                }

                if (interfaceType == null && typeInfoPtr != IntPtr.Zero)
                {
                    // This can be very slow. Hence we call SearchForInteropAssembly before we do this.
                    interfaceType = Marshal.GetTypeForITypeInfo(typeInfoPtr);

                    if (interfaceType != null)
                    {
                        ComTypeCache[typeInfoGuid] = interfaceType;
                    }
                }
            }

            return(interfaceType);
        }
Exemple #20
0
        internal List GetAttrNames(ICallerContext context)
        {
            Initialize(context);

            List list = List.Make();

            if (HaveInterfaces)
            {
                foreach (DynamicType type in interfaces)
                {
                    List names = type.GetAttrNames(context, obj);
                    foreach (object o in names)
                    {
                        if (!list.Contains(o))
                        {
                            list.AddNoLock(o);
                        }
                    }
                }
            }
            else
            {
                //return GetDynamicType().GetAttrNames(context, this);
            }
            return(list);
        }
 public override object Call(ICallerContext context, params object[] args)
 {
     switch (args.Length) {
         case 0: return Call(context);
         default: throw BadArgumentError(args.Length);
     }
 }
Exemple #22
0
        public override Dict GetAttrDict(ICallerContext context, object self)
        {
            // Get the entries from the type
            Dict res = new Dict(GetAttrDict(context));

            // Add the entries from the instance
            ISuperDynamicObject sdo = self as ISuperDynamicObject;

            if (sdo != null)
            {
                IAttributesDictionary dict = sdo.GetDict();
                if (dict != null)
                {
                    foreach (KeyValuePair <object, object> val in dict)
                    {
                        object fieldName = val.Key;
                        if (!res.ContainsKey(fieldName))
                        {
                            res.Add(new KeyValuePair <object, object>(fieldName, val.Value));
                        }
                    }
                }
            }
            return(res);
        }
Exemple #23
0
        public bool TryGetAttr(ICallerContext context, SymbolId name, out object value)
        {
            if (name == SymbolTable.Dict)
            {
                value = EnsureDict();
                return(true);
            }

            if (dict != null)
            {
                if (dict.TryGetValue(name, out value))
                {
                    return(true);
                }
            }

            // We check for SymbolTable.Module as the user code can modify it
            if (name == SymbolTable.Module)
            {
                value = Module.ModuleName;
                return(true);
            }

            return(GetDynamicType().TryGetAttr(context, this, name, out value));
        }
Exemple #24
0
 public override bool TryGetAttr(ICallerContext context, object self, SymbolId name, out object ret)
 {
     if (__getattribute__F.IsObjectMethod())
     {
         ISuperDynamicObject sdo = self as ISuperDynamicObject;
         if (sdo != null)
         {
             return(TryBaseGetAttr(context, sdo, name, out ret));
         }
         else
         {
             ret = null;
             return(false);
         }
     }
     else
     {
         try {
             ret = __getattribute__F.Invoke(self, SymbolTable.IdToString(name));
             return(true);
         } catch (MissingMemberException) {
             ret = null;
             return(false);
         }
     }
 }
Exemple #25
0
 public override object Call(ICallerContext context, object arg0, object arg1, object arg2, object arg3, object arg4)
 {
     if (HasInstance)
     {
         return(target(new object[] { Instance, arg0, arg1, arg2, arg3, arg4 }));
     }
     return(target(new object[] { arg0, arg1, arg2, arg3, arg4 }));
 }
        public List GetAttrNames(ICallerContext context)
        {
            LoadAllTypes();

            List res = new List(((IDictionary<object, object>)__dict__).Keys);
            res.Sort();
            return res;
        }
Exemple #27
0
 public override object Call(ICallerContext context, object arg0, object arg1, object arg2, object arg3, object arg4)
 {
     if ((this.FunctionType & FunctionType.Function) == 0 && HasInstance)
     {
         throw BadArgumentError(5);
     }
     return(target(arg0, arg1, arg2, arg3, arg4));
 }
Exemple #28
0
 public override object Call(ICallerContext context, object arg0, object arg1, object arg2)
 {
     if (!HasInstance || !IsContextAware)
     {
         throw BadArgumentError(3);
     }
     return(target(context, Instance, arg0, arg1, arg2));
 }
Exemple #29
0
 public override object Call(ICallerContext context, object arg0)
 {
     if (HasInstance)
     {
         return(target(new object[] { Instance, arg0 }));
     }
     return(target(new object[] { arg0 }));
 }
 public KwArgBinder(ICallerContext context, object[] args, string[] keyNames, bool allowUnboundArgs)
 {
     arguments = args;
     kwNames = keyNames;
     Debug.Assert(keyNames.Length <= args.Length);
     fAllowUnboundArgs = allowUnboundArgs;
     ctx = context;
 }
Exemple #31
0
 public ThreadObj(ICallerContext context, object function, Tuple args, object kwargs)
 {
     Debug.Assert(args != null);
     func         = function;
     this.kwargs  = kwargs;
     this.args    = args;
     this.context = context;
 }
Exemple #32
0
 public static Tuple FindModule(ICallerContext context, string name, List path)
 {
     if (path == null) {
         return FindBuiltinOrSysPath(context, name);
     } else {
         return FindModulePath(context, name, path);
     }
 }
Exemple #33
0
 protected bool TryLookupSlot(ICallerContext context, SymbolId name, out object ret)
 {
     if (TryGetSlot(context, name, out ret))
     {
         return(true);
     }
     return(TryLookupSlotInBases(context, name, out ret));
 }
Exemple #34
0
 public IDictionary <object, object> GetAttrDict(ICallerContext context)
 {
     if (dict == null)
     {
         return(new Dict(0));
     }
     return((IDictionary <object, object>)dict);
 }
 public override object Call(ICallerContext context)
 {
     if (!EnforceRecursion) return target();
     PushFrame();
     try {
         return target();
     } finally {
         PopFrame();
     }
 }
        public override bool TryGetAttr(ICallerContext context, object self, SymbolId name, out object ret)
        {
            if (base.TryGetAttr(context, self, name, out ret)) {
                return true;
            }

            // This will force creation of the instances dict
            IAttributesDictionary dict = ((ISuperDynamicObject)self).GetDict();
            return dict.TryGetValue(name, out ret);
        }
        public object Call(ICallerContext context, object[] args, string[] names)
        {
            object targetMethod;
            if (!Ops.GetDynamicType(target).TryLookupBoundSlot(context, target, name, out targetMethod))
                throw Ops.AttributeError("type {0} has no attribute {1}",
                    Ops.GetDynamicType(target.Target),
                    name.ToString());

            return Ops.Call(context, targetMethod, args, names);
        }
        public override List GetAttrNames(ICallerContext context, object self)
        {
            Assembly asm = self as Assembly;
            TopReflectedPackage reflectedAssembly = GetReflectedAssembly(context.SystemState, asm);

            List ret = base.GetAttrNames(context, self);

            ret.AddRange(reflectedAssembly.GetAttrNames(context));
            return ret;
        }
        public override Dict GetAttrDict(ICallerContext context, object self)
        {
            List attrs = GetAttrNames(context, self);

            Dict res = new Dict();
            foreach (string o in attrs) {
                res[o] = GetAttr(context, self, SymbolTable.StringToId(o));
            }

            return res;
        }
        public override void SetAttr(ICallerContext context, object self, SymbolId name, object value)
        {
            object slot;
            bool success = TryGetSlot(context, name, out slot);
            if (success) {
                success = Ops.SetDescriptor(slot, self, value);
            }

            if (!success) {
                // otherwise update the instance
                IAttributesDictionary dict = ((ISuperDynamicObject)self).GetDict();
                dict[name] = value;
            }
        }
        public override bool TryGetAttr(ICallerContext context, object self, SymbolId name, out object ret)
        {
            Assembly asm = self as Assembly;
            TopReflectedPackage reflectedAssembly = GetReflectedAssembly(context.SystemState, asm);

            if (name == SymbolTable.Dict) {
                ret = reflectedAssembly.GetAttrDict(context);
                return true;
            }

            if (base.TryGetAttr(context, self, name, out ret)) {
                return true;
            }

            if (!reflectedAssembly.TryGetAttr(context, name, out ret))
                throw Ops.AttributeError("assembly {0} has no type {1}", asm.GetName().Name, name);

            return true;
        }
        public static object Reduce(ICallerContext context, object self, object protocol)
        {
            object objectReduce = Ops.GetAttr(DefaultContext.Default, Ops.GetDynamicTypeFromType(typeof(object)), SymbolTable.Reduce);
            object myReduce;
            if (Ops.TryGetAttr(DefaultContext.Default, Ops.GetDynamicType(self), SymbolTable.Reduce, out myReduce)) {
                if (!Ops.IsRetBool(myReduce, objectReduce)) {
                    // A derived class overrode __reduce__ but not __reduce_ex__, so call
                    // specialized __reduce__ instead of generic __reduce_ex__.
                    // (see the "The __reduce_ex__ API" section of PEP 307)
                    return Ops.Call(myReduce, self);
                }
            }

            if (Converter.ConvertToInt32(protocol) < 2) {
                return ReduceProtocol0(context, self);
            } else {
                return ReduceProtocol2(context, self);
            }
        }
            private void SaveLong(ICallerContext context, object obj)
            {
                Debug.Assert(Ops.GetDynamicType(obj).Equals(TypeCache.BigInteger), "arg must be long");

                if (protocol < 2) {
                    Write(Opcode.Long);
                    WriteLongAsString(obj);
                } else {
                    if (((BigInteger)obj).IsZero()) {
                        Write(Opcode.Long1);
                        WriteUInt8(0);
                    } else {
                        byte[] dataBytes = ((BigInteger)obj).ToByteArray();
                        if (dataBytes.Length < 256) {
                            Write(Opcode.Long1);
                            WriteUInt8(dataBytes.Length);
                        } else {
                            Write(Opcode.Long4);
                            WriteInt32(dataBytes.Length);
                        }

                        foreach (byte b in dataBytes) {
                            WriteUInt8(b);
                        }
                    }
                }
            }
        /// <summary>
        /// Implements the default __reduce_ex__ method as specified by PEP 307 case 3 (new-style instance, protocol 2)
        /// </summary>
        private static Tuple ReduceProtocol2(ICallerContext context, object self)
        {
            DynamicType myType = Ops.GetDynamicType(self);

            object func, state, listIterator, dictIterator;
            object[] funcArgs;

            func = PythonCopyReg.PythonNewObject;

            object getNewArgsCallable;
            if (Ops.TryGetAttr(myType, SymbolTable.GetNewArgs, out getNewArgsCallable)) {
                // TypeError will bubble up if __getnewargs__ isn't callable
                Tuple newArgs = Ops.Call(getNewArgsCallable, self) as Tuple;
                if (newArgs == null) {
                    throw Ops.TypeError("__getnewargs__ should return a tuple");
                }
                funcArgs = new object[1 + newArgs.Count];
                funcArgs[0] = myType;
                for (int i = 0; i < newArgs.Count; i++) funcArgs[i + 1] = newArgs[i];
            } else {
                funcArgs = new object[] { myType };
            }

            if (!Ops.TryInvokeSpecialMethod(self, SymbolTable.GetState, out state)) {
                object dict;
                if (!Ops.TryGetAttr(self, SymbolTable.Dict, out dict)) {
                    dict = null;
                }

                Dict initializedSlotValues = GetInitializedSlotValues(self);
                if (initializedSlotValues != null && initializedSlotValues.Count == 0) {
                    initializedSlotValues = null;
                }

                if (dict == null && initializedSlotValues == null) state = null;
                else if (dict != null && initializedSlotValues == null) state = dict;
                else if (dict != null && initializedSlotValues != null) state = Tuple.MakeTuple(dict, initializedSlotValues);
                else   /*dict == null && initializedSlotValues != null*/ state = Tuple.MakeTuple(null, initializedSlotValues);
            }

            listIterator = null;
            if (self is List) {
                listIterator = Ops.GetEnumerator(self);
            }

            dictIterator = null;
            if (self is Dict) {
                dictIterator = Ops.Invoke(self, SymbolTable.IterItems, Ops.EMPTY);
            }

            return Tuple.MakeTuple(func, Tuple.MakeTuple(funcArgs), state, listIterator, dictIterator);
        }
 public static object Reduce(ICallerContext context, object self)
 {
     return Reduce(context, self, 0);
 }
            private void SaveDict(ICallerContext context, object obj)
            {
                Debug.Assert(Ops.GetDynamicType(obj).Equals(TypeCache.Dict), "arg must be dict");
                Debug.Assert(!memo.Contains(Ops.Id(obj)));
                Memoize(obj);

                if (protocol < 1) {
                    Write(Opcode.Mark);
                    Write(Opcode.Dict);
                } else {
                    Write(Opcode.EmptyDict);
                }

                WritePut(obj);
                BatchSetItems(context, (DictOps.IterItems((IDictionary<object, object>)obj)));
            }
        /// <summary>
        /// Implements the default __reduce_ex__ method as specified by PEP 307 case 2 (new-style instance, protocol 0 or 1)
        /// </summary>
        private static Tuple ReduceProtocol0(ICallerContext context, object self)
        {
            // CPython implements this in copy_reg._reduce_ex

            DynamicType myType = Ops.GetDynamicType(self); // PEP 307 calls this "D"
            ThrowIfNativelyPickable(myType);

            object getState;
            bool hasGetState = Ops.TryGetAttr(self, SymbolTable.GetState, out getState);

            object slots;
            if (Ops.TryGetAttr(myType, SymbolTable.Slots, out slots) && Ops.Length(slots) > 0 && !hasGetState) {
                // ??? does this work with superclass slots?
                throw Ops.TypeError("a class that defines __slots__ without defining __getstate__ cannot be pickled with protocols 0 or 1");
            }

            DynamicType closestNonPythonBase = FindClosestNonPythonBase(myType); // PEP 307 calls this "B"

            object func = PythonCopyReg.PythonReconstructor;

            object funcArgs = Tuple.MakeTuple(
                myType,
                closestNonPythonBase,
                TypeCache.Object == closestNonPythonBase ? null : Ops.Call(closestNonPythonBase, self)
            );

            object state;
            if (hasGetState) {
                state = Ops.Call(getState);
            } else {
                Ops.TryGetAttr(self, SymbolTable.Dict, out state);
            }
            if (!Ops.IsTrue(state)) state = null;

            return Tuple.MakeTuple(func, funcArgs, state);
        }
 private void Save(ICallerContext context, object obj)
 {
     if (memo.Contains(Ops.Id(obj))) {
         WriteGet(obj);
     } else {
         PickleFunction pickleFunction;
         DynamicType objType = Ops.GetDynamicType(obj);
         if (!dispatchTable.TryGetValue(objType, out pickleFunction)) {
             if (objType.IsSubclassOf(TypeCache.DynamicType)) {
                 // treat classes with metaclasses like regular classes
                 pickleFunction = SaveGlobal;
             } else {
                 pickleFunction = SaveObject;
             }
         }
         pickleFunction(context, obj);
     }
 }
            private void SaveFloat(ICallerContext context, object obj)
            {
                Debug.Assert(Ops.GetDynamicType(obj).Equals(TypeCache.Double), "arg must be float");

                if (protocol < 1) {
                    Write(Opcode.Float);
                    WriteFloatAsString(obj);
                } else {
                    Write(Opcode.BinFloat);
                    WriteFloat64(obj);
                }
            }
            private void SaveGlobal(ICallerContext context, object obj)
            {
                Debug.Assert(
                    Ops.GetDynamicType(obj).Equals(TypeCache.OldClass) ||
                    Ops.GetDynamicType(obj).Equals(TypeCache.Function) ||
                    Ops.GetDynamicType(obj).Equals(TypeCache.BuiltinFunction) ||
                    Ops.GetDynamicType(obj).Equals(TypeCache.DynamicType) ||
                    Ops.GetDynamicType(obj).IsSubclassOf(TypeCache.DynamicType),
                    "arg must be classic class, function, built-in function or method, or new-style type"
                );

                object name;
                if (Ops.TryGetAttr(obj, SymbolTable.Name, out name)) {
                    SaveGlobalByName(context, obj, name);
                } else {
                    throw CannotPickle(obj, "could not determine its __name__");
                }
            }
            private void SaveList(ICallerContext context, object obj)
            {
                Debug.Assert(Ops.GetDynamicType(obj).Equals(TypeCache.List), "arg must be list");
                Debug.Assert(!memo.Contains(Ops.Id(obj)));
                Memoize(obj);
                if (protocol < 1) {
                    Write(Opcode.Mark);
                    Write(Opcode.List);
                } else {
                    Write(Opcode.EmptyList);
                }

                WritePut(obj);
                BatchAppends(context, ((IEnumerable)obj).GetEnumerator());
            }
 private void SaveInteger(ICallerContext context, object obj)
 {
     Debug.Assert(Ops.GetDynamicType(obj).Equals(TypeCache.Int32), "arg must be int");
     if (protocol < 1) {
         Write(Opcode.Int);
         WriteIntAsString(obj);
     } else {
         if (IsUInt8(obj)) {
             Write(Opcode.BinInt1);
             WriteUInt8(obj);
         } else if (IsUInt16(obj)) {
             Write(Opcode.BinInt2);
             WriteUInt16(obj);
         } else if (IsInt32(obj)) {
             Write(Opcode.BinInt);
             WriteInt32(obj);
         } else {
             throw Ops.RuntimeError("unrecognized integer format");
         }
     }
 }
            private void SaveInstance(ICallerContext context, object obj)
            {
                Debug.Assert(Ops.GetDynamicType(obj).Equals(TypeCache.OldInstance), "arg must be old-class instance");
                Debug.Assert(!memo.Contains(Ops.Id(obj)));

                Write(Opcode.Mark);

                // Memoize() call isn't in the usual spot to allow class to be memoized before
                // instance (when using proto other than 0) to match CPython's bytecode output

                object objClass;
                if (!Ops.TryGetAttr(obj, SymbolTable.Class, out objClass)) {
                    throw CannotPickle(obj, "could not determine its __class__");
                }

                if (protocol < 1) {
                    object className, classModuleName;
                    if (!Ops.TryGetAttr(objClass, SymbolTable.Name, out className)) {
                        throw CannotPickle(obj, "its __class__ has no __name__");
                    }
                    classModuleName = FindModuleForGlobal(context, objClass, className);

                    Memoize(obj);
                    WriteInitArgs(context, obj);
                    Write(Opcode.Inst);
                    WriteStringPair(classModuleName, className);
                } else {
                    Save(context, objClass);
                    Memoize(obj);
                    WriteInitArgs(context, obj);
                    Write(Opcode.Obj);
                }

                WritePut(obj);

                object getStateCallable;
                if (Ops.TryGetAttr(obj, SymbolTable.GetState, out getStateCallable)) {
                    Save(context, Ops.Call(getStateCallable));
                } else {
                    Save(context, Ops.GetAttr(context, obj, SymbolTable.Dict));
                }

                Write(Opcode.Build);
            }
            private void SaveGlobalByName(ICallerContext context, object obj, object name)
            {
                Debug.Assert(!memo.Contains(Ops.Id(obj)));

                object moduleName = FindModuleForGlobal(context, obj, name);

                if (protocol >= 2) {
                    object code;
                    if (PythonCopyReg.ExtensionRegistry.TryGetValue(Tuple.MakeTuple(moduleName, name), out code)) {
                        int intCode = (int)code;
                        if (IsUInt8(code)) {
                            Write(Opcode.Ext1);
                            WriteUInt8(code);
                        } else if (IsUInt16(code)) {
                            Write(Opcode.Ext2);
                            WriteUInt16(code);
                        } else if (IsInt32(code)) {
                            Write(Opcode.Ext4);
                            WriteInt32(code);
                        } else {
                            throw Ops.RuntimeError("unrecognized integer format");
                        }
                        return;
                    }
                }

                Memoize(obj);

                Write(Opcode.Global);
                WriteStringPair(moduleName, name);
                WritePut(obj);
            }
 private void SaveNone(ICallerContext context, object obj)
 {
     Debug.Assert(Ops.GetDynamicType(obj).Equals(TypeCache.None), "arg must be None");
     Write(Opcode.NoneValue);
 }
            /// <summary>
            /// Call the appropriate reduce method for obj and pickle the object using
            /// the resulting data. Use the first available of
            /// copy_reg.dispatch_table[type(obj)], obj.__reduce_ex__, and obj.__reduce__.
            /// </summary>
            private void SaveObject(ICallerContext context, object obj)
            {
                Debug.Assert(!memo.Contains(Ops.Id(obj)));
                Memoize(obj);

                object reduceCallable, result;
                DynamicType objType = Ops.GetDynamicType(obj);

                if (PythonCopyReg.DispatchTable.TryGetValue(objType, out reduceCallable)) {
                    result = Ops.Call(reduceCallable, obj);
                } else if (Ops.TryGetAttr(obj, SymbolTable.ReduceEx, out reduceCallable)) {
                    if (obj is DynamicType) {
                        result = Ops.Call(reduceCallable, obj, protocol);
                    } else {
                        result = Ops.Call(reduceCallable, protocol);
                    }
                } else if (Ops.TryGetAttr(obj, SymbolTable.Reduce, out reduceCallable)) {
                    if (obj is DynamicType) {
                        result = Ops.Call(reduceCallable, obj);
                    } else {
                        result = Ops.Call(reduceCallable);
                    }
                } else {
                    throw Ops.AttributeError("no reduce function found for {0}", obj);
                }

                if (objType.Equals(TypeCache.String)) {
                    if (memo.Contains(Ops.Id(obj))) {
                        WriteGet(obj);
                    } else {
                        SaveGlobalByName(context, obj, result);
                    }
                } else if (result is Tuple) {
                    Tuple rt = (Tuple)result;
                    switch (rt.Count) {
                        case 2:
                            SaveReduce(context, obj, reduceCallable, rt[0], rt[1], null, null, null);
                            break;
                        case 3:
                            SaveReduce(context, obj, reduceCallable, rt[0], rt[1], rt[2], null, null);
                            break;
                        case 4:
                            SaveReduce(context, obj, reduceCallable, rt[0], rt[1], rt[2], rt[3], null);
                            break;
                        case 5:
                            SaveReduce(context, obj, reduceCallable, rt[0], rt[1], rt[2], rt[3], rt[4]);
                            break;
                        default:
                            throw CannotPickle(obj, "tuple returned by {0} must have to to five elements", reduceCallable);
                    }
                } else {
                    throw CannotPickle(obj, "{0} must return string or tuple", reduceCallable);
                }
            }
            /// <summary>
            /// Find the module for obj and ensure that obj is reachable in that module by the given name.
            /// 
            /// Throw PicklingError if any of the following are true:
            ///  - The module couldn't be determined.
            ///  - The module couldn't be loaded.
            ///  - The given name doesn't exist in the module.
            ///  - The given name is a different object than obj.
            /// 
            /// Otherwise, return the name of the module.
            /// 
            /// To determine which module obj lives in, obj.__module__ is used if available. The
            /// module named by obj.__module__ is loaded if needed. If obj has no __module__
            /// attribute, then each loaded module is searched. If a loaded module has an
            /// attribute with the given name, and that attribute is the same object as obj,
            /// then that module is used.
            /// </summary>
            private object FindModuleForGlobal(ICallerContext context, object obj, object name)
            {
                object module;
                object moduleName;
                if (Ops.TryGetAttr(obj, SymbolTable.Module, out moduleName)) {
                    if (!Importer.TryGetExistingModule(context.SystemState, Converter.ConvertToString(moduleName), out module)) {
                        module = Builtin.__import__(context, Converter.ConvertToString(moduleName));
                    }

                    object foundObj;
                    if (Ops.TryGetAttr(module, SymbolTable.StringToId(Converter.ConvertToString(name)), out foundObj)) {
                        if (Ops.IsRetBool(foundObj, obj)) {
                            return moduleName;
                        } else {
                            throw CannotPickle(obj, "it's not the same object as {0}.{1}", moduleName, name);
                        }
                    } else {
                        throw CannotPickle(obj, "it's not found as {0}.{1}", moduleName, name);
                    }
                } else {
                    // No obj.__module__, so crawl through all loaded modules looking for obj
                    foreach (KeyValuePair<object, object> modulePair in context.SystemState.modules) {
                        moduleName = modulePair.Key;
                        module = modulePair.Value;
                        object foundObj;
                        if (Ops.TryGetAttr(module, SymbolTable.StringToId(Converter.ConvertToString(name)), out foundObj) &&
                            Ops.IsRetBool(foundObj, obj)
                        ) {
                            return moduleName;
                        }
                    }
                    throw CannotPickle(obj, "could not determine its module");
                }
            }
            /// <summary>
            /// Pickle the result of a reduce function.
            /// 
            /// Only context, obj, func, and reduceCallable are required; all other arguments may be null.
            /// </summary>
            private void SaveReduce(ICallerContext context, object obj, object reduceCallable, object func, object args, object state, object listItems, object dictItems)
            {
                if (!Ops.IsCallable(func)) {
                    throw CannotPickle(obj, "func from reduce() should be callable");
                } else if (!(args is Tuple) && args != null) {
                    throw CannotPickle(obj, "args from reduce() should be a tuple");
                } else if (listItems != null && !(listItems is IEnumerator)) {
                    throw CannotPickle(obj, "listitems from reduce() should be a list iterator");
                } else if (dictItems != null && !(dictItems is IEnumerator)) {
                    throw CannotPickle(obj, "dictitems from reduce() should be a dict iterator");
                }

                object funcName;
                string funcNameString;
                if (!Ops.TryGetAttr(func, SymbolTable.Name, out funcName)) {
                    throw CannotPickle(obj, "func from reduce() ({0}) should have a __name__ attribute");
                } else if (!Converter.TryConvertToString(funcName, out funcNameString) || funcNameString == null) {
                    throw CannotPickle(obj, "__name__ of func from reduce() must be string");
                }

                if (protocol >= 2 && "__newobj__" == funcNameString) {
                    if (args == null) {
                        throw CannotPickle(obj, "__newobj__ arglist is None");
                    }
                    Tuple argsTuple = (Tuple)args;
                    if (argsTuple.Count == 0) {
                        throw CannotPickle(obj, "__newobj__ arglist is empty");
                    } else if (!Ops.GetDynamicType(obj).Equals(argsTuple[0])) {
                        throw CannotPickle(obj, "args[0] from __newobj__ args has the wrong class");
                    }
                    Save(context, argsTuple[0]);
                    Save(context, argsTuple[new Slice(1, null)]);
                    Write(Opcode.NewObj);
                } else {
                    Save(context, func);
                    Save(context, args);
                    Write(Opcode.Reduce);
                }

                WritePut(obj);

                if (state != null) {
                    Save(context, state);
                    Write(Opcode.Build);
                }

                if (listItems != null) {
                    BatchAppends(context, (IEnumerator)listItems);
                }

                if (dictItems != null) {
                    BatchSetItems(context, (IEnumerator)dictItems);
                }
            }
            /// <summary>
            /// Emit a series of opcodes that will set all (key, value) pairs indexed by
            /// iter in the object at the top of the stack. Use SETITEMS if possible,
            /// but append no more than BatchSize items at a time.
            /// </summary>
            private void BatchSetItems(ICallerContext context, IEnumerator enumerator)
            {
                Tuple kvTuple;
                if (protocol < 1) {
                    while (enumerator.MoveNext()) {
                        kvTuple = (Tuple)enumerator.Current;
                        Save(context, kvTuple[0]);
                        Save(context, kvTuple[1]);
                        Write(Opcode.SetItem);
                    }
                } else {
                    object nextKey, nextValue;
                    if (enumerator.MoveNext()) {
                        kvTuple = (Tuple)enumerator.Current;
                        nextKey = kvTuple[0];
                        nextValue = kvTuple[1];
                    } else {
                        return;
                    }

                    int batchCompleted = 0;
                    object curKey, curValue;

                    // We do a one-item lookahead to avoid emitting a SETITEMS for a
                    // single remaining item.
                    while (enumerator.MoveNext()) {
                        curKey = nextKey;
                        curValue = nextValue;
                        kvTuple = (Tuple)enumerator.Current;
                        nextKey = kvTuple[0];
                        nextValue = kvTuple[1];

                        if (batchCompleted == BatchSize) {
                            Write(Opcode.SetItems);
                            batchCompleted = 0;
                        }

                        if (batchCompleted == 0) {
                            Write(Opcode.Mark);
                        }

                        Save(context, curKey);
                        Save(context, curValue);
                        batchCompleted++;
                    }

                    if (batchCompleted == BatchSize) {
                        Write(Opcode.SetItems);
                        batchCompleted = 0;
                    }
                    Save(context, nextKey);
                    Save(context, nextValue);
                    batchCompleted++;

                    if (batchCompleted > 1) {
                        Write(Opcode.SetItems);
                    } else {
                        Write(Opcode.SetItem);
                    }
                }
            }
 private void SaveBoolean(ICallerContext context, object obj)
 {
     Debug.Assert(Ops.GetDynamicType(obj).Equals(TypeCache.Boolean), "arg must be bool");
     if (protocol < 2) {
         Write(Opcode.Int);
         Write(String.Format("0{0}", ((bool)obj) ? 1 : 0));
         Write(Newline);
     } else {
         if ((bool)obj) {
             Write(Opcode.NewTrue);
         } else {
             Write(Opcode.NewFalse);
         }
     }
 }