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 Program Data and Data Structure Definition
12 ------------------------------------------
13
14 Given that micropython has already deduced object and parameter details,
15 such information must be communicated in the systems programming language
16 so that the compiler does not have to deduce it again.
17
18 Explicit constant declaration shall be done at the start of the main
19 module:
20
21 __constants__(...)
22
23 Explicit structure declaration is still performed using class statements,
24 but base classes are omitted and attributes are declared explicitly as
25 follows:
26
27 class C:
28 __instattrs__(member...)
29 __classattrs__(member...)
30
31 Other object table information, such as inherited class attributes and
32 class compatibility (to support isinstance) are also declared explicitly:
33
34 __inherited__(superclass, member...)
35 __descendants__(class...)
36
37 Other than function definitions, no other code statements shall appear in
38 class definitions; such statements will appear after classes have been
39 defined.
40
41 For classes in the module namespace or within other classes, the __main__
42 function collects together all "loose" (module-level) statements; class
43 attribute assignments will occur in the __main__ function, and where a name
44 is associated with a function definition and another object, the function will
45 also be explicitly assigned in the __main__ function using its full name.
46
47 For classes in function namespaces, the containing function could contain the
48 "loose" statements at the point at which the class appears. However, such
49 classes are not currently supported in micropython.
50
51 Any class or function defined once in a namespace need not be assigned to that
52 namespace in the __main__ function, but where multiple definitions exist and
53 program logic determines which definition prevails, such definitions must be
54 assigned in the __main__ function.
55
56 For example:
57
58 class C:
59 def method(self, ...):
60 ...
61 if something:
62 method = something
63
64 This is represented as follows:
65
66 class C:
67 ...
68 def method(self, ...):
69 ...
70
71 def __main__():
72 __globalnames__(...)
73 ...
74 method = module.C.method
75 if something:
76 __storeattr__(module.C, something)
77
78 Imports
79 -------
80
81 Imports act as invocations of module code and name assignments within a
82 particular scope and are defined as follows:
83
84 # import package
85 package.__main__()
86 package = __static__(package)
87
88 # import package.module
89 package.__main__()
90 package.module.__main__()
91 package = __static__(package)
92
93 # from package.module import cls
94 package.__main__()
95 package.module.__main__()
96 cls = __loadattribute__(package.module, cls) # see below
97
98 Since import statements can appear in code that may be executed more than
99 once, __main__ functions should test and set a flag indicating whether the
100 function has already been called.
101
102 Python would arguably be more sensible as a language if imports were
103 processed separately, but this would then rule out logic controlling the
104 use of modules.
105
106 Name and Attribute Declarations
107 -------------------------------
108
109 Assignments and name usage involve locals and globals but usage is declared
110 explicitly:
111
112 __localnames__(...)
113
114 At the function level, locals are genuine local name definitions whereas
115 globals refer to module globals:
116
117 __globalnames__(...)
118
119 At the module level, locals are effectively equivalent to module globals but
120 are declared as follows:
121
122 __moduleattrs__(...)
123
124 Each module's __main__ function will declare any referenced module globals as
125 globals. Note that the __main__ function is not a genuine attribute of any
126 module but an internal construct used to initialise modules appropriately.
127
128 Such declarations must appear first in a program unit (module, function).
129 For example:
130
131 def f(a, b):
132 __localnames__(a, b, x, y)
133 __globalnames__(f, g)
134
135 __storelocal__(x, 1)
136 __storelocal__(y, x)
137 __storelocal__(a, b)
138 __storeattr__(module, g, f)
139
140 Names and Attributes
141 --------------------
142
143 Bare names refer to locals or globals according to the __localnames__ and
144 __globalnames__ declarations, or to constants such as None, True, False and
145 NotImplemented. Storage of local or global names is done using explicit
146 functions as follows:
147
148 __storelocal__(name, value)
149 __storeattr__(module, name, value) # see below
150
151 No operator usage: all operators are converted to invocations, including
152 all attribute access except static references to modules or particular class
153 or function definitions using the following notation:
154
155 __static__(package)
156 __static__(package.module)
157 __static__(package.module.cls)
158 __static__(package.module.cls.function)
159
160 A shorthand dot notation could be employed:
161
162 package.module
163 package.module.cls
164 package.module.cls.function
165
166 Where multiple definitions of static objects occur, the dot notation cannot be
167 used, and the full name of such definitions must be quoted. For example:
168
169 __static__("package.module.cls#1.function")
170
171 In general, attribute access must use an explicit function indicating the
172 kind of access operation being performed. For example:
173
174 __loadattr__(obj, attrname) # preserve context
175 __loadattrcontext__(obj, attrname) # replace context with obj
176 __loadattrcontextcond__(obj, attrname) # run-time context decision
177 __loadattrindex__(obj, attrname) # preserve context
178 __loadattrindexcontext__(obj, attrname) # replace context with obj
179 __loadattrindexcontextcond__(obj, attrname) # run-time context decision
180
181 __storeattr__(obj, attrname, value) # preserve context
182 __storeattrcontext__(obj, attrname, value) # replace context
183 __storeattrindex__(obj, attrname, value)
184
185 Temporary variables could employ similar functions:
186
187 __loadtemp__(0)
188 __storetemp__(0, value)
189
190 Operators and Invocations
191 -------------------------
192
193 Conventional operators use the operator functions.
194
195 Special operators could also use the operator functions (where available)
196 but might as well be supported directly:
197
198 __is__(a, b)
199
200 Logical operators involving short-circuit evaluation could be represented
201 as function calls, but the evaluation semantics would be preserved:
202
203 __and__(...) # returns the first non-true value or the final value
204 __not__(obj) # returns the inverse of the boolean interpretation of obj
205 __or__(...) # returns the first true value or the final value
206
207 Comparisons could be rephrased in a verbose fashion:
208
209 a < b < c becomes lt(a, b) and lt(b, c)
210 or __and__(lt(a, b), lt(b, c))
211
212 Advanced Control-Flow
213 ---------------------
214
215 Any statements requiring control-flow definition in terms of blocks must
216 be handled in the language as the notions of labels and blocks are not
217 introduced earlier apart from the special case of jumping to another
218 callable (described below).
219
220 Special functions for low-level operations:
221
222 __check__(obj, type)
223 __jump__(callable)
224
225 Function/subroutine definition with entry points for checked and unchecked
226 parameters.
227
228 def fn_checked(self, ...):
229 __check__(self, Type) # raises a TypeError if not isinstance(self, Type)
230 __jump__(fn_unchecked) # preserves the frame and return address
231
232 def fn_unchecked(self, ...):
233 ...
234
235 The __jump__ function might also be used for inlining appropriate functions.
236
237 Exceptions must also be handled in the language.
238
239 Object Type Detection
240 ---------------------
241
242 Occasionally, the type of an object (instance of a particular class, class,
243 and so on) needs to be determined at run-time:
244
245 __isclass__(obj)