micropython

docs/rationale.txt

442:13aae946513b
2011-07-05 Paul Boddie Introduced Instance() in place of None as a result and for the value of the active expression where no definitive object can be deduced. Made all Instance values compare equal to each other in order to avoid duplication in sets. Improved Constant comparisons. Fixed assignment counting where many values are provided in a single assignment. Added inspection support for conditional expressions (since they are used in the standard library).
     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   * Definition from within means more predictable content
   114 
   115 Micropython classes
   116 
   117   * Classes contain attributes and expose superclass attributes
   118   * Inside the class:
   119     * Attributes can be accessed and set in the class scope
   120     * Functions define methods
   121   * Outside the class:
   122     * Attributes can be accessed but not set
   123   * Definition from within means more predictable content
   124 
   125 Micropython instances
   126 
   127   * Instances contain attributes and expose class attributes
   128   * Instance attributes must not shadow class attributes
   129   * The set of attributes is detected by scanning the __init__ method
   130 
   131 Rationale for restrictions
   132 
   133   * Construct efficient run-time representations
   134   * Predictable content means that access can be optimised
   135   * No shadowing means that only a single lookup is necessary
   136 
   137 References, attributes and values
   138 
   139   * Almost everything can be considered as a kind of attribute:
   140     * Module, class, instance
   141     * Local variable is the exception
   142   * Acquired attributes are "values":
   143     * An object being manipulated
   144     * Its context
   145   * Most kinds of values have no real context:
   146     * Module and class attributes, locals
   147   * The exception:
   148     * Instance attributes
   149 
   150 Wild idea: isn't AttributeError just evidence of a bug in the program?
   151 
   152   * Note down all attributes used by a particular name during its lifetime
   153   * Upon recording name usage, record the location of usage
   154   * Use the set of attributes to constrain the range of types that can be used
   155     without an AttributeError being raised
   156   * Convert all name usage to specific attribute usage (on the range of types
   157     found) for all attribute accesses
   158 
   159 Attributes on locals
   160 
   161   * Control-flow can make attribute tracking awkward:
   162 
   163     obj.x           # obj must have x
   164     if obj.p:       # obj must have x, p
   165                     # (branch)
   166         obj = ...   #   obj reset
   167         obj.attr    #   obj must have attr
   168                     # (end of branch)
   169     else:           # (branch)
   170         obj.name    #   obj must have x, p, name
   171                     # (end of branch)
   172                     # (merge branch ends)
   173                     # obj must have either attr or x, p, name
   174 
   175 Attributes on locals with loops
   176 
   177   * Loops complicate matters still further:
   178 
   179     obj.x           # obj must have x
   180     while obj.p:    # obj must have x, p
   181                     # (branch)
   182         obj.y       #   obj must have x, p, y
   183         obj = ...   #   obj reset
   184         obj.z       #   obj must have z
   185                     # (re-test)
   186                     #   obj must have z, p
   187                     # (end of branch)
   188                     # (null branch - no else)
   189                     # (merge branch ends)
   190                     # obj must have either z, p (from loop) or x, p (from null branch)
   191 
   192 Attributes on attributes
   193 
   194   * Classes and modules should preserve single interpretations of attributes
   195   * Attributes on such attributes should accumulate on the targets
   196   * Tracking attributes on such targets is only useful for unknown targets
   197   * Instances cannot be relied upon to refer to a coherent set of targets