micropython

Annotated docs/rationale.txt

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