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