micropython

docs/rationale.txt

746:59be62d8e75f
2013-11-25 Paul Boddie Fixed loadconstant usage to include both the constant and the new context. syspython-as-target
     1 Micropython: A minimal implementation of Python for constrained devices
     2 
     3   * "Full strength" Python:
     4     * Introspection, interactivity, PEP/reference-compliance
     5     * CPython, Jython, IronPython, PyPy, CLPython, etc.
     6   * "Reduced strength" Python:
     7     * Remove "luxury" semantics
     8     * Shed Skin, RPython, etc.
     9 
    10 Motivations
    11 
    12   * Run Python programs in "small" devices
    13   * Small programs plus few executed instructions
    14     * Avoid expensive library code
    15       (small footprint, lots of executed instructions)
    16 
    17 Python's flexibility comes at a cost
    18 
    19   * Modules, classes, instances are all objects
    20   * Freedom to modify most objects at any time
    21   * Difficult to predict eventual behaviour before execution
    22   * Difficult to generate optimisations when compiling
    23 
    24 Not all things are dynamic/equal in Python
    25 
    26   * Locals, modules and classes are special in some way
    27     * Locals don't tend to change unilaterally
    28     * Parameter lists don't tend to change if fully specified
    29     * Modules usually retain their identity
    30     * Classes differ from objects (despite metaclasses)
    31 
    32 Attribute access
    33 
    34   * Must do a full lookup every time:
    35     * Check instance dictionary
    36     * Check class, superclasses
    37   * Potentially lots of code
    38   * Lots of executed instructions
    39 
    40 Improving attribute access performance
    41 
    42   * Achieve faster access using a different representation
    43   * Must define attributes of objects in advance
    44   * Restriction: modules, classes, instances are "closed"
    45   * Evaluate the limitations: are they too disruptive?
    46 
    47 Consequences of revised attribute access
    48 
    49   * Cannot extend the range of attributes on objects of existing classes
    50   * Further optimisations:
    51     * Restriction: attempt to control modification of attributes
    52     * Result: further optimisation of accesses
    53 
    54 Invocations
    55 
    56   * Target checking
    57   * Number of arguments vs. number of parameters
    58   * Keyword parameter resolution
    59   * Defaults
    60 
    61 Other costly operations
    62 
    63   * Binary operators
    64   * Comparisons
    65 
    66 Examples of rarely used/unnecessary flexibility
    67 
    68   * Can subclass dynamically:
    69 
    70     for cls in A, B:
    71         class C(cls):
    72             pass
    73 
    74   * Yet most people would relate to "class C"
    75   * Not "the class currently known as C"
    76 
    77 Examples of occasionally used flexibility
    78 
    79   * Can evaluate classes and functions in dynamic contexts:
    80 
    81     if platform == 'posix':
    82         class C:
    83             ...
    84     else:
    85         class C:
    86             ...
    87 
    88   * Seen quite often in the standard library with functions
    89   * Dynamism used for configuration purposes
    90 
    91 Distinguish between "good" and "bad" dynamism
    92 
    93   * Dynamic class preparation
    94   * Run-time choice of classes
    95   * Assigning attributes to modules
    96 
    97 Run-time configuration
    98 
    99   * The source of a lot of "bad" dynamism
   100   * Comparable to, but more robust than...
   101     * Class loading tricks in Java
   102     * Dynamic library loading magic in C/C++
   103   * Has a place, but perhaps not in compiled, embedded programs
   104 
   105 Micropython modules
   106 
   107   * Modules contain attributes as with normal Python
   108   * Inside the module:
   109     * Attributes can be accessed and set as globals
   110     * Classes and functions define module attributes
   111   * Outside the module:
   112     * Attributes can be accessed but not set
   113     * This can be relaxed with attribute usage observations
   114   * Definition from within means more predictable content
   115 
   116 Micropython classes
   117 
   118   * Classes contain attributes and expose superclass attributes
   119   * Inside the class:
   120     * Attributes can be accessed and set in the class scope
   121     * Functions define methods
   122   * Outside the class:
   123     * Attributes can be accessed but not set
   124     * This can be relaxed with attribute usage observations
   125   * Definition from within means more predictable content
   126 
   127 Micropython instances
   128 
   129   * Instances contain attributes and expose class attributes
   130   * Instance attributes must not shadow class attributes
   131   * The set of attributes is detected by scanning the __init__ method
   132 
   133 Rationale for restrictions
   134 
   135   * Construct efficient run-time representations
   136   * Predictable content means that access can be optimised
   137   * No shadowing means that only a single lookup is necessary
   138 
   139 References, attributes and values
   140 
   141   * Almost everything can be considered as a kind of attribute:
   142     * Module, class, instance
   143     * Local variable is the exception
   144   * Acquired attributes are "values":
   145     * An object being manipulated
   146     * Its context
   147   * Most kinds of values have no real context:
   148     * Module and class attributes, locals
   149   * The exception:
   150     * Instance attributes
   151 
   152 Wild idea: isn't AttributeError just evidence of a bug in the program?
   153 
   154   * Note down all attributes used by a particular name during its lifetime
   155   * Upon recording name usage, record the location of usage
   156   * Use the set of attributes to constrain the range of types that can be used
   157     without an AttributeError being raised
   158   * Convert all name usage to specific attribute usage (on the range of types
   159     found) for all attribute accesses
   160 
   161 Attributes on locals
   162 
   163   * Control-flow can make attribute tracking awkward:
   164 
   165     obj.x           # obj must have x
   166     if obj.p:       # obj must have x, p
   167                     # (branch)
   168         obj = ...   #   obj reset
   169         obj.attr    #   obj must have attr
   170                     # (end of branch)
   171     else:           # (branch)
   172         obj.name    #   obj must have x, p, name
   173                     # (end of branch)
   174                     # (merge branch ends)
   175                     # obj must have either attr or x, p, name
   176 
   177 Attributes on locals with loops
   178 
   179   * Loops complicate matters still further:
   180 
   181     obj.x           # obj must have x
   182     while obj.p:    # obj must have x, p
   183                     # (branch)
   184         obj.y       #   obj must have x, p, y
   185         obj = ...   #   obj reset
   186         obj.z       #   obj must have z
   187                     # (re-test)
   188                     #   obj must have z, p
   189                     # (end of branch)
   190                     # (null branch - no else)
   191                     # (merge branch ends)
   192                     # obj must have either z, p (from loop) or x, p (from null branch)
   193 
   194 Attributes on attributes
   195 
   196   * Classes and modules should preserve single interpretations of attributes
   197   * Attributes on such attributes should accumulate on the targets
   198   * Tracking attributes on such targets is only useful for unknown targets
   199   * Instances cannot be relied upon to refer to a coherent set of targets