1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/docs/syspython.txt Sat Jan 12 18:38:34 2013 +0100
1.3 @@ -0,0 +1,150 @@
1.4 +A Systems Programming Language Target for Micropython
1.5 +=====================================================
1.6 +
1.7 +Python-compatible syntax for processing using the compiler module.
1.8 +
1.9 +The principal focus is on specific machine code generation and not
1.10 +analysis. Thus, only block generation, address reference generation,
1.11 +temporary storage administration and other code generation tasks are to be
1.12 +left to the systems programming language compiler.
1.13 +
1.14 +Given that micropython has already deduced object and parameter details,
1.15 +such information must be communicated in the systems programming language
1.16 +so that the compiler does not have to deduce it again.
1.17 +
1.18 +Explicit constant declaration shall be done at the start of the main
1.19 +module:
1.20 +
1.21 + __constants__(...)
1.22 +
1.23 +Explicit structure declaration is still performed using class statements,
1.24 +but base classes are omitted and attributes are declared explicitly as
1.25 +follows:
1.26 +
1.27 + class C:
1.28 + __instattrs__(member...)
1.29 + __classattrs__(member...)
1.30 +
1.31 +Other object table information, such as inherited class attributes and
1.32 +class compatibility (to support isinstance) are also declared explicitly:
1.33 +
1.34 + __inherited__(superclass, member...)
1.35 + __descendants__(class...)
1.36 +
1.37 +Other than function definitions, no other code statements shall appear in
1.38 +class definitions; such statements will appear after classes have been
1.39 +defined in a __main__ function collecting together all "loose"
1.40 +(module-level) statements.
1.41 +
1.42 +Imports act as invocations of module code and name assignments within a
1.43 +particular scope and are defined as follows:
1.44 +
1.45 + # import package
1.46 + package.__main__()
1.47 + package = __module__(package)
1.48 +
1.49 + # import package.module
1.50 + package.__main__()
1.51 + package.module.__main__()
1.52 + package = __module__(package)
1.53 +
1.54 + # from package.module import cls
1.55 + package.__main__()
1.56 + package.module.__main__()
1.57 + cls = __loadattribute__(package.module, cls) # see below
1.58 +
1.59 +Since import statements can appear in code that may be executed more than
1.60 +once, __main__ functions should test and set a flag indicating whether the
1.61 +function has already been called.
1.62 +
1.63 +Python would arguably be more sensible as a language if imports were
1.64 +processed separately, but this would then rule out logic controlling the
1.65 +use of modules.
1.66 +
1.67 +Assignments and name usage involves locals and globals but usage is
1.68 +declared explicitly:
1.69 +
1.70 + __localnames__(...)
1.71 +
1.72 +At the function level, locals are genuine local name definitions whereas
1.73 +globals refer to module globals:
1.74 +
1.75 + __globalnames__(...)
1.76 +
1.77 +Although at the module level, locals are effectively equivalent to module
1.78 +globals, each module's __main__ function will declare them as globals.
1.79 +
1.80 +Such declarations must appear first in a program unit (module, function).
1.81 +For example:
1.82 +
1.83 + def f(a, b):
1.84 + __localnames__(a, b, x, y)
1.85 + __globalnames__(f, g)
1.86 +
1.87 + x = 1 # local
1.88 + y = x # locals
1.89 + a = b # locals
1.90 + g = f # globals
1.91 +
1.92 +No operator usage: all operators are converted to invocations, including
1.93 +all attribute access except static references to modules using the
1.94 +following notation:
1.95 +
1.96 + __module__(package)
1.97 + __module__(package.module)
1.98 + package.module # shorthand where dot notation is used
1.99 +
1.100 +In general, attribute access must use an explicit function indicating the
1.101 +kind of access operation being performed. For example:
1.102 +
1.103 + __loadaddress__(obj, attrname)
1.104 + __loadaddresscontext__(obj, attrname)
1.105 + __loadaddresscontextcond__(obj, attrname)
1.106 + __loadattr__(obj, attrname)
1.107 + __loadattrindex__(obj, attrname)
1.108 + __loadattrindexcontext__(obj, attrname)
1.109 + __loadattrindexcontextcond__(obj, attrname)
1.110 +
1.111 + __storeaddress__(obj, attrname, value)
1.112 + __storeaddresscontext__(obj, attrname, value)
1.113 + __storeattr__(obj, attrname, value)
1.114 + __storeattrindex__(obj, attrname, value)
1.115 +
1.116 +Conventional operators use the operator functions.
1.117 +
1.118 +Special operators could also use the operator functions (where available)
1.119 +but might as well be supported directly:
1.120 +
1.121 + __is__(a, b)
1.122 +
1.123 +Logical operators involving short-circuit evaluation could be represented
1.124 +as function calls, but the evaluation semantics would be preserved:
1.125 +
1.126 + __and__(...) # returns the first non-true value or the final value
1.127 + __not__(obj) # returns the inverse of the boolean interpretation of obj
1.128 + __or__(...) # returns the first true value or the final value
1.129 +
1.130 +Comparisons could be rephrased in a verbose fashion:
1.131 +
1.132 + a < b < c becomes lt(a, b) and lt(b, c)
1.133 + or __and__(lt(a, b), lt(b, c))
1.134 +
1.135 +Any statements requiring control-flow definition in terms of blocks must
1.136 +be handled in the language as the notions of labels and blocks are not
1.137 +introduced earlier apart from the special case of jumping to another
1.138 +callable (described below).
1.139 +
1.140 +Special functions for low-level operations:
1.141 +
1.142 + __check__(obj, type)
1.143 + __jump__(callable)
1.144 +
1.145 +Function/subroutine definition with entry points for checked and unchecked
1.146 +parameters.
1.147 +
1.148 + def fn_checked(self, ...):
1.149 + __check__(self, Type) # raises a TypeError if not isinstance(self, Type)
1.150 + __jump__(fn_unchecked) # preserves the frame and return address
1.151 +
1.152 + def fn_unchecked(self, ...):
1.153 + ...