micropython

docs/syspython.txt

679:48f3af55bd30
2013-07-08 Paul Boddie Added some support for specific kinds of invocations identified through analysis. 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 Names and Attributes
   182 --------------------
   183 
   184 Bare names refer to locals or globals according to the localnames and
   185 globalnames declarations, or to constants such as None, True, False and
   186 NotImplemented. Storage of local or global names is done using explicit
   187 functions as follows:
   188 
   189     storelocal(name, value)
   190     storeattr(module, name, value) # see below
   191 
   192 No operator usage: all operators are converted to invocations, including
   193 all attribute access except static references to modules or particular class
   194 or function definitions using the following notation:
   195 
   196     static(package)
   197     static(package.module)
   198     static(package.module.cls)
   199     static(package.module.cls.function)
   200 
   201 A shorthand dot notation could be employed:
   202 
   203     package.module
   204     package.module.cls
   205     package.module.cls.function
   206 
   207 Where multiple definitions of static objects occur, the dot notation cannot be
   208 used, and the full name of such definitions must be quoted. For example:
   209 
   210     static("package.module.cls#1.function")
   211 
   212 In general, attribute access must use an explicit function indicating the
   213 kind of access operation being performed. For example:
   214 
   215     # Instance-related operations:
   216 
   217     loadattr(obj, attrname)                             # preserve retrieved context
   218 
   219     # Static attribute operations:
   220 
   221     loadaddress(parent, attrname)                       # preserve retrieved context
   222     loadaddresscontext(parent, attrname, obj)           # replace context with obj
   223     loadaddresscontextcond(parent, attrname, obj)       # run-time context decision
   224 
   225     # Unoptimised operations:
   226 
   227     loadattrindex(obj, attrname)                        # preserve retrieved context
   228     loadattrindexcontextcond(obj, attrname)             # run-time context decision
   229 
   230     # Instance-related operations:
   231 
   232     storeattr(obj, attrname, value)                     # preserve context for value
   233 
   234     # Static attribute operations:
   235 
   236     storeaddress(parent, attrname, value)               # preserve context for value
   237     storeaddresscontext(parent, attrname, value, obj)   # replace context with obj
   238 
   239     # Unoptimised operations:
   240 
   241     storeattrindex(obj, attrname, value)                # preserve context for value
   242 
   243 Recall that for loadattrindex family functions, the location of the attribute
   244 is obtained from the object table and the nature of the attribute is
   245 determined from the stored context value.
   246 
   247 Temporary variables could employ similar functions:
   248 
   249     loadtemp(0)
   250     storetemp(0, value)
   251 
   252 Operators and Invocations
   253 -------------------------
   254 
   255 Conventional operators use the operator functions.
   256 
   257 Special operators could also use the operator functions (where available)
   258 but might as well be supported directly:
   259 
   260     __is__(a, b)
   261     __is_not__(a, b)
   262 
   263 Logical operators involving short-circuit evaluation could be represented
   264 as function calls, but the evaluation semantics would be preserved:
   265 
   266     __and__(...)  # returns the first non-true value or the final value
   267     __not__(obj)  # returns the inverse of the boolean interpretation of obj
   268     __or__(...)   # returns the first true value or the final value
   269 
   270 Comparisons could be rephrased in a verbose fashion:
   271 
   272     a < b < c becomes lt(a, b) and lt(b, c)
   273                    or __and__(lt(a, b), lt(b, c))
   274 
   275 Advanced Control-Flow
   276 ---------------------
   277 
   278 Any statements requiring control-flow definition in terms of blocks must
   279 be handled in the language as the notions of labels and blocks are not
   280 introduced earlier apart from the special case of jumping to another
   281 callable (described below).
   282 
   283 Special functions for low-level operations:
   284 
   285     check(obj, type)
   286     jump(callable)
   287 
   288 Function/subroutine definition with entry points for checked and unchecked
   289 parameters.
   290 
   291     def fn_checked(self, ...):
   292         check(self, Type)    # raises a TypeError if not isinstance(self, Type)
   293         jump(fn_unchecked)   # preserves the frame and return address
   294 
   295     def fn_unchecked(self, ...):
   296         ...
   297 
   298 The jump function might also be used for inlining appropriate functions.
   299 
   300 Exceptions must also be handled in the language.
   301 
   302 Object Type Detection
   303 ---------------------
   304 
   305 Occasionally, the type of an object (instance of a particular class, class,
   306 and so on) needs to be determined at run-time:
   307 
   308     isclass(obj)