Python for .NET is a completely new implementation of Python. Although many facilities could be implemented simply by extending Python (that is, by using the existing CPython implementation and writing an extension module), there were two primary reasons for creating a completely new implementation:
An alternative strategy that could be employed is discussed later in this appendix. Current StatusThe current state of the compiler and the runtime systems shows that it is possible to have compiled Python programs fully supported within the .NET Framework. Most of the basic infrastructure is in place, with full bidirectional cross-language support (i.e., Python can inherit or call objects created in other languages, and other languages can inherit from or call objects created in Python). There are three categories of problems that preclude Python for .NET from being truly useful to a large number of people:
If these issues are addressed, we feel that Python for .NET would become a viable , interesting technology to use within .NET. ArchitectureThe Python for .NET implementation consists of three semi-discrete areas: the compiler, the runtime, and the library. Although there is obviously significant interaction between these parts , each has a distinct architecture. The CompilerThe Python for .NET compiler is written using CPython. It compiles Python source code and uses the .NET Reflection::Emit library to generate a .NET assembly. The COM Interoperability features of .NET are used to access the Reflection::Emit library. This particular strategy was chosen to minimize the implementation time. Python's parser is built into the CPython runtime, and the existing Python2C project [3] had infrastructure we could borrow . Greg Stein was involved in the Python2C project and so provided the expertise needed to get up and running quickly.
The key benefits to this approach are the rapid implementation of a simple compiler and the rapid development obtained by coding the compiler in CPython. The primary drawback is the speed of the compiler. Much of the abstract syntax tree manipulation code is also written in Python code, and as this is one of the most CPU- intensive areas of the compiler, we suffer a significant speed penalty. However, the core Python2C code has been integrated into a standard Python module, and it is hoped that there will be general improvements in the speed of this library as more users turn to this standard module. Further, the use of Reflection::Emit via COM is also causing some performance problems. Some of these problems are due to the speed of the Python COM bindings, but Reflection::Emit itself and/or the COM Interoperability layers are costing significant time as well. Although currently implemented using CPython, it is envisioned that in the future this compiler will be capable of running under Python for .NET. This will allow the dynamic Python language features, such as exec and eval() , to be exploited by having the compiler invoked at runtime. However, the functionality provided by the Python for .NET compiler must be enhanced and a number of existing C-implemented Python modules must be ported before this is possible. Python for .NET RuntimeDue to the dynamic nature of Python, the compiler will often generate code that references the Python for .NET runtime. Even for a simple Python expression such as " a + b ", if the types of the variables are not known by the compiler, it will generate code to ensure that Python for .NET determines the correct semantics at runtime. One of the most important jobs of the runtime environment is to ensure that the Python language semantics are faithfully implemented. For this reason, the design and implementation of the Python for .NET runtime borrows heavily from the CPython implementation. The Python for .NET runtime is written in C#. The Python for .NET runtime defines a .NET interface ( IPyType ) that captures Python's semantics. The definition of this interface is almost identical to the existing CPython type object , which is the object primarily responsible for object semantics in CPython. The IPyType interface defines the semantics for a Python type independent of an object instance. For example, the type definition for a string or integer defines the behavior of strings and integers without reference to a specific string or specific integer. Thus, to operate on any .NET object, the Python runtime needs two components : an instance of an IPyType interface that describes the Python semantics (such as defining string or integer semantics) and the .NET object itself (that is, a reference to the specific string or integer being operated on). For this reason, the Python for .NET runtime defines a PyObject structure (that is, a C# value type), which consists of references to an IPyType interface and a .NET object. Almost all runtime functions work with PyObject s. The Python for .NET runtime also exposes an API for use by the compiler, which works primarily with PyObject structures. It provides a function for creating a new PyObject at runtime, given nothing except an anonymous .NET object reference. The compiler will frequently generate calls to create these PyObject structures (often storing the result in a variable) and pass these PyObject structures back into the runtime environment as needed. The Python LibraryThe role of the Python for .NET library is to implement the standard Python library ”the modules Python guarantees will be available to a program at runtime. Python programs reference library modules with the import statement. One of the biggest challenges with a new implementation is this library. In general, there are two distinct categories of library modules in the existing CPython implementation:
As the CPython API is defined in terms of the CPython implementation (that is, the extension module interface is specific to an implementation rather than part of the language specification), it is not practical to port existing C/C++ extension modules to the .NET implementation while having the CLR consider these modules verifiable . For this reason, there is a two-stage approach to implementing the Python library for .NET: Reimplement all standard Python extension modules. These modules can be reimplemented either by creating an extension module in C# or by implementing these modules in Python and thereby taking advantage of the .NET Framework facilities. Compile existing Python extension modules under the .NET compiler. Assuming that all extension modules available for CPython have been re-implemented for .NET, and that the compiler is capable, all existing Python modules should compile under the new implementation. At the time of this writing, the library for the Python for .NET implementation is quite sparse, and only enough modules required to run basic tests have been implemented. It is hoped that this library will grow as use of the compiler expands. |