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 Given that micropython has already deduced object and parameter details,
12 such information must be communicated in the systems programming language
13 so that the compiler does not have to deduce it again.
14
15 Explicit constant declaration shall be done at the start of the main
16 module:
17
18 __constants__(...)
19
20 Explicit structure declaration is still performed using class statements,
21 but base classes are omitted and attributes are declared explicitly as
22 follows:
23
24 class C:
25 __instattrs__(member...)
26 __classattrs__(member...)
27
28 Other object table information, such as inherited class attributes and
29 class compatibility (to support isinstance) are also declared explicitly:
30
31 __inherited__(superclass, member...)
32 __descendants__(class...)
33
34 Other than function definitions, no other code statements shall appear in
35 class definitions; such statements will appear after classes have been
36 defined in a __main__ function collecting together all "loose"
37 (module-level) statements.
38
39 Imports act as invocations of module code and name assignments within a
40 particular scope and are defined as follows:
41
42 # import package
43 package.__main__()
44 package = __module__(package)
45
46 # import package.module
47 package.__main__()
48 package.module.__main__()
49 package = __module__(package)
50
51 # from package.module import cls
52 package.__main__()
53 package.module.__main__()
54 cls = __loadattribute__(package.module, cls) # see below
55
56 Since import statements can appear in code that may be executed more than
57 once, __main__ functions should test and set a flag indicating whether the
58 function has already been called.
59
60 Python would arguably be more sensible as a language if imports were
61 processed separately, but this would then rule out logic controlling the
62 use of modules.
63
64 Assignments and name usage involves locals and globals but usage is
65 declared explicitly:
66
67 __localnames__(...)
68
69 At the function level, locals are genuine local name definitions whereas
70 globals refer to module globals:
71
72 __globalnames__(...)
73
74 Although at the module level, locals are effectively equivalent to module
75 globals, each module's __main__ function will declare them as globals.
76
77 Such declarations must appear first in a program unit (module, function).
78 For example:
79
80 def f(a, b):
81 __localnames__(a, b, x, y)
82 __globalnames__(f, g)
83
84 x = 1 # local
85 y = x # locals
86 a = b # locals
87 g = f # globals
88
89 No operator usage: all operators are converted to invocations, including
90 all attribute access except static references to modules using the
91 following notation:
92
93 __module__(package)
94 __module__(package.module)
95 package.module # shorthand where dot notation is used
96
97 In general, attribute access must use an explicit function indicating the
98 kind of access operation being performed. For example:
99
100 __loadaddress__(obj, attrname)
101 __loadaddresscontext__(obj, attrname)
102 __loadaddresscontextcond__(obj, attrname)
103 __loadattr__(obj, attrname)
104 __loadattrindex__(obj, attrname)
105 __loadattrindexcontext__(obj, attrname)
106 __loadattrindexcontextcond__(obj, attrname)
107
108 __storeaddress__(obj, attrname, value)
109 __storeaddresscontext__(obj, attrname, value)
110 __storeattr__(obj, attrname, value)
111 __storeattrindex__(obj, attrname, value)
112
113 Conventional operators use the operator functions.
114
115 Special operators could also use the operator functions (where available)
116 but might as well be supported directly:
117
118 __is__(a, b)
119
120 Logical operators involving short-circuit evaluation could be represented
121 as function calls, but the evaluation semantics would be preserved:
122
123 __and__(...) # returns the first non-true value or the final value
124 __not__(obj) # returns the inverse of the boolean interpretation of obj
125 __or__(...) # returns the first true value or the final value
126
127 Comparisons could be rephrased in a verbose fashion:
128
129 a < b < c becomes lt(a, b) and lt(b, c)
130 or __and__(lt(a, b), lt(b, c))
131
132 Any statements requiring control-flow definition in terms of blocks must
133 be handled in the language as the notions of labels and blocks are not
134 introduced earlier apart from the special case of jumping to another
135 callable (described below).
136
137 Special functions for low-level operations:
138
139 __check__(obj, type)
140 __jump__(callable)
141
142 Function/subroutine definition with entry points for checked and unchecked
143 parameters.
144
145 def fn_checked(self, ...):
146 __check__(self, Type) # raises a TypeError if not isinstance(self, Type)
147 __jump__(fn_unchecked) # preserves the frame and return address
148
149 def fn_unchecked(self, ...):
150 ...