micropython

docs/syspython.txt

746:59be62d8e75f
2013-11-25 Paul Boddie Fixed loadconstant usage to include both the constant and the new context. syspython-as-target
     1 A Systems Programming Language Target for Micropython
     2 =====================================================
     3 
     4 Python-compatible syntax for processing using the compiler module.
     5 
     6 The principal focus is on specific machine code generation and not
     7 analysis. Thus, only block generation, address reference generation,
     8 temporary storage administration and other code generation tasks are to be
     9 left to the systems programming language compiler.
    10 
    11 Special Functions
    12 -----------------
    13 
    14 In syspython, the function invocation notation is reserved to specify
    15 primitive operations such as attribute access and actual function invocations,
    16 with the latter being expressed as follows:
    17 
    18     fn(y)           # original Python
    19     apply(fn, y)    # syspython
    20 
    21 Thus, in syspython, whenever the invocation notation is used, the target of
    22 the invocation is always a special function and not a general Python function
    23 or method. Note that the apply function resembles the Python function of the
    24 same name but is not actually that particular function.
    25 
    26 A family of special functions for invocations exists, addressing optimisation
    27 situations identified by program analysis.
    28 
    29 Low-Level Code
    30 --------------
    31 
    32 Most Python-level program code should be wrapped in special function
    33 invocations, and as a result other syntax features might be used to express
    34 low-level concepts. Low-level operations may also be expressed using other
    35 special functions. For example:
    36 
    37     storelocal(element, loadobjtable(loadattr(obj, classcode), attrcode))
    38 
    39 Here, element holds the raw data provided by the table access involving a base
    40 defined by the classcode of an object and an offset defined by the supplied
    41 attrcode.
    42 
    43 Note that all low-level functions deal only with addresses and offsets, not
    44 symbols. In the above example, loadattr combines the address of obj with the
    45 symbol classcode whose actual value must be substituted by the compiler.
    46 However, the loadobjtable function requires a genuine offset value for the
    47 classcode (which is why loadattr is being used to obtain it), and a genuine
    48 offset for the attrcode (which is provided directly).
    49 
    50 Program Data and Data Structure Definition
    51 ------------------------------------------
    52 
    53 Given that micropython has already deduced object and parameter details,
    54 such information must be communicated in the systems programming language
    55 so that the compiler does not have to deduce it again.
    56 
    57 Explicit constant declaration shall be done at the start of the main
    58 module:
    59 
    60     constants(...)
    61 
    62 Each module may feature keyword arguments, and a list of such names is
    63 provided as follows:
    64 
    65     keywords(...)
    66 
    67 Explicit structure declaration is still performed using class statements,
    68 but base classes are omitted and attributes are declared explicitly as
    69 follows:
    70 
    71     class C:
    72         instattrs(member...)
    73         classattrs(member...)
    74 
    75 Other object table information, such as inherited class attributes and
    76 class compatibility (to support isinstance) are also declared explicitly:
    77 
    78         inherited(superclass, member...)
    79         descendants(class...)
    80 
    81 Other than function definitions, no other code statements shall appear in
    82 class definitions; such statements will appear after classes have been
    83 defined.
    84 
    85 For classes in the module namespace or within other classes, the __main__
    86 function collects together all "loose" (module-level) statements; class
    87 attribute assignments will occur in the __main__ function, and where a name
    88 is associated with a function definition and another object, the function will
    89 also be explicitly assigned in the __main__ function using its full name.
    90 
    91 For classes in function namespaces, the containing function could contain the
    92 "loose" statements at the point at which the class appears. However, such
    93 classes are not currently supported in micropython.
    94 
    95 Any class or function defined once in a namespace need not be assigned to that
    96 namespace in the __main__ function, but where multiple definitions exist and
    97 program logic determines which definition prevails, such definitions must be
    98 assigned in the __main__ function.
    99 
   100 For example:
   101 
   102     class C:
   103         def method(self, ...):
   104             ...
   105         if something:
   106             method = something
   107 
   108 This is represented as follows:
   109 
   110     class C:
   111         ...
   112         def method(self, ...):
   113             ...
   114 
   115     def __main__():
   116         globalnames(...)
   117         ...
   118         if something:
   119             storeattr(module.C, method, something)
   120 
   121 Imports
   122 -------
   123 
   124 Imports act as invocations of module code and name assignments within a
   125 particular scope and are defined as follows:
   126 
   127     # import package
   128     package.__main__()
   129     storelocal(package, static(package))
   130 
   131     # import package.module
   132     package.__main__()
   133     package.module.__main__()
   134     storelocal(package, static(package))
   135 
   136     # from package.module import cls
   137     package.__main__()
   138     package.module.__main__()
   139     storelocal(cls, loadattribute(package.module, cls)) # see below
   140 
   141 Since import statements can appear in code that may be executed more than
   142 once, __main__ functions should test and set a flag indicating whether the
   143 function has already been called.
   144 
   145 Python would arguably be more sensible as a language if imports were
   146 processed separately, but this would then rule out logic controlling the
   147 use of modules.
   148 
   149 Name and Attribute Declarations
   150 -------------------------------
   151 
   152 Assignments and name usage involve locals and globals but usage is declared
   153 explicitly:
   154 
   155     localnames(...)
   156 
   157 At the function level, locals are genuine local name definitions whereas
   158 globals refer to module globals:
   159 
   160     globalnames(...)
   161 
   162 At the module level, locals are effectively equivalent to module globals and
   163 are declared as such.
   164 
   165 Each module's __main__ function will declare any referenced module globals as
   166 globals. Note that the __main__ function is not a genuine attribute of any
   167 module but an internal construct used to initialise modules appropriately.
   168 
   169 Such declarations must appear first in a program unit (module, function).
   170 For example:
   171 
   172     def f(a, b):
   173         localnames(a, b, x, y)
   174         globalnames(f, g)
   175 
   176         storelocal(x, 1)
   177         storelocal(y, x)
   178         storelocal(a, b)
   179         storeattr(module, g, f)
   180 
   181 Assignments
   182 -----------
   183 
   184 Since assignments can rebind names used in the value expression, the evaluated
   185 expression must be captured and referenced when setting the targets. This is
   186 done using the special $expr variable, and so the swap assignment...
   187 
   188     a, b = b, a
   189 
   190 ...would be written (more or less) as...
   191 
   192     $expr = (b, a)
   193     storelocal(a, apply(operator.getitem, $expr, 0))
   194     storelocal(b, apply(operator.getitem, $expr, 1))
   195 
   196 Names and Attributes
   197 --------------------
   198 
   199 Bare names refer to locals or globals according to the localnames and
   200 globalnames declarations, or to constants such as None, True, False and
   201 NotImplemented. Storage of local or global names is done using explicit
   202 functions as follows:
   203 
   204     storelocal(name, value)
   205     storeattr(module, name, value) # see below
   206 
   207 No operator usage: all operators are converted to invocations, including
   208 all attribute access except static references to modules or particular class
   209 or function definitions using the following notation:
   210 
   211     static(package)
   212     static(package.module)
   213     static(package.module.cls)
   214     static(package.module.cls.function)
   215 
   216 A shorthand dot notation could be employed:
   217 
   218     package.module
   219     package.module.cls
   220     package.module.cls.function
   221 
   222 Where multiple definitions of static objects occur, the dot notation cannot be
   223 used, and the full name of such definitions must be quoted. For example:
   224 
   225     static("package.module.cls#1.function")
   226 
   227 In general, attribute access must use an explicit function indicating the
   228 kind of access operation being performed. For example:
   229 
   230     # Instance-related operations:
   231 
   232     loadattr(obj, attrname)                             # preserve retrieved context
   233 
   234     # Constant attribute operations:
   235 
   236     static(value)                                       # see above
   237     loadconstant(value, obj)                            # replace context with obj
   238 
   239     # Static attribute operations:
   240 
   241     loadaddress(parent, attrname)                       # preserve retrieved context
   242     loadaddresscontext(parent, attrname, obj)           # replace context with obj
   243     loadaddresscontextcond(parent, attrname, obj)       # run-time context decision
   244 
   245     # Unoptimised operations:
   246 
   247     loadattrindex(obj, attrname)                        # preserve retrieved context
   248     loadattrindexcontextcond(obj, attrname)             # run-time context decision
   249 
   250     # Instance-related operations:
   251 
   252     storeattr(obj, attrname, value)                     # preserve context for value
   253 
   254     # Static attribute operations:
   255 
   256     storeaddress(parent, attrname, value)               # preserve context for value
   257     storeaddresscontext(parent, attrname, value, obj)   # replace context with obj
   258 
   259     # Unoptimised operations:
   260 
   261     storeattrindex(obj, attrname, value)                # preserve context for value
   262 
   263 Recall that for loadattrindex family functions, the location of the attribute
   264 is obtained from the object table and the nature of the attribute is
   265 determined from the stored context value.
   266 
   267 Temporary variables could employ similar functions:
   268 
   269     loadtemp(0)
   270     storetemp(0, value)
   271 
   272 Operators and Invocations
   273 -------------------------
   274 
   275 Conventional operators use the operator functions.
   276 
   277 Special operators could also use the operator functions (where available)
   278 but might as well be supported directly:
   279 
   280     __is__(a, b)
   281     __is_not__(a, b)
   282 
   283 Logical operators involving short-circuit evaluation could be represented
   284 as function calls, but the evaluation semantics would be preserved:
   285 
   286     __and__(...)  # returns the first non-true value or the final value
   287     __not__(obj)  # returns the inverse of the boolean interpretation of obj
   288     __or__(...)   # returns the first true value or the final value
   289 
   290 Comparisons could be rephrased in a verbose fashion:
   291 
   292     a < b < c becomes lt(a, b) and lt(b, c)
   293                    or __and__(lt(a, b), lt(b, c))
   294 
   295 Advanced Control-Flow
   296 ---------------------
   297 
   298 Any statements requiring control-flow definition in terms of blocks must
   299 be handled in the language as the notions of labels and blocks are not
   300 introduced earlier apart from the special case of jumping to another
   301 callable (described below).
   302 
   303 Special functions for low-level operations:
   304 
   305     check(obj, type)
   306     jump(callable)
   307 
   308 Function/subroutine definition with entry points for checked and unchecked
   309 parameters.
   310 
   311     def fn_checked(self, ...):
   312         check(self, Type)    # raises a TypeError if not isinstance(self, Type)
   313         jump(fn_unchecked)   # preserves the frame and return address
   314 
   315     def fn_unchecked(self, ...):
   316         ...
   317 
   318 The jump function might also be used for inlining appropriate functions.
   319 
   320 Exceptions must also be handled in the language.
   321 
   322 Object Type Detection
   323 ---------------------
   324 
   325 Occasionally, the type of an object (instance of a particular class, class,
   326 and so on) needs to be determined at run-time:
   327 
   328     isclass(obj)