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 __storeaddress__(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 __storeaddress__(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 __storeaddress__(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 __loadaddress__(obj, attrname)
175 __loadaddresscontext__(obj, attrname)
176 __loadaddresscontextcond__(obj, attrname)
177 __loadattr__(obj, attrname)
178 __loadattrindex__(obj, attrname)
179 __loadattrindexcontext__(obj, attrname)
180 __loadattrindexcontextcond__(obj, attrname)
181
182 __storeaddress__(obj, attrname, value)
183 __storeaddresscontext__(obj, attrname, value)
184 __storeattr__(obj, attrname, value)
185 __storeattrindex__(obj, attrname, value)
186
187 Temporary variables could employ similar functions:
188
189 __loadtemp__(0)
190 __storetemp__(0, value)
191
192 Operators and Invocations
193 -------------------------
194
195 Conventional operators use the operator functions.
196
197 Special operators could also use the operator functions (where available)
198 but might as well be supported directly:
199
200 __is__(a, b)
201
202 Logical operators involving short-circuit evaluation could be represented
203 as function calls, but the evaluation semantics would be preserved:
204
205 __and__(...) # returns the first non-true value or the final value
206 __not__(obj) # returns the inverse of the boolean interpretation of obj
207 __or__(...) # returns the first true value or the final value
208
209 Comparisons could be rephrased in a verbose fashion:
210
211 a < b < c becomes lt(a, b) and lt(b, c)
212 or __and__(lt(a, b), lt(b, c))
213
214 Advanced Control-Flow
215 ---------------------
216
217 Any statements requiring control-flow definition in terms of blocks must
218 be handled in the language as the notions of labels and blocks are not
219 introduced earlier apart from the special case of jumping to another
220 callable (described below).
221
222 Special functions for low-level operations:
223
224 __check__(obj, type)
225 __jump__(callable)
226
227 Function/subroutine definition with entry points for checked and unchecked
228 parameters.
229
230 def fn_checked(self, ...):
231 __check__(self, Type) # raises a TypeError if not isinstance(self, Type)
232 __jump__(fn_unchecked) # preserves the frame and return address
233
234 def fn_unchecked(self, ...):
235 ...
236
237 Exceptions must also be handled in the language.