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