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 in a __main__ function collecting together all "loose"
40 (module-level) statements.
41
42 Imports
43 -------
44
45 Imports act as invocations of module code and name assignments within a
46 particular scope and are defined as follows:
47
48 # import package
49 package.__main__()
50 package = __module__(package)
51
52 # import package.module
53 package.__main__()
54 package.module.__main__()
55 package = __module__(package)
56
57 # from package.module import cls
58 package.__main__()
59 package.module.__main__()
60 cls = __loadattribute__(package.module, cls) # see below
61
62 Since import statements can appear in code that may be executed more than
63 once, __main__ functions should test and set a flag indicating whether the
64 function has already been called.
65
66 Python would arguably be more sensible as a language if imports were
67 processed separately, but this would then rule out logic controlling the
68 use of modules.
69
70 Name and Attribute Declarations
71 -------------------------------
72
73 Assignments and name usage involve locals and globals but usage is declared
74 explicitly:
75
76 __localnames__(...)
77
78 At the function level, locals are genuine local name definitions whereas
79 globals refer to module globals:
80
81 __globalnames__(...)
82
83 At the module level, locals are effectively equivalent to module globals but
84 are declared as follows:
85
86 __moduleattrs__(...)
87
88 Each module's __main__ function will declare any referenced module globals as
89 globals. Note that the __main__ function is not a genuine attribute of any
90 module but an internal construct used to initialise modules appropriately.
91
92 Such declarations must appear first in a program unit (module, function).
93 For example:
94
95 def f(a, b):
96 __localnames__(a, b, x, y)
97 __globalnames__(f, g)
98
99 x = 1 # local
100 y = x # locals
101 a = b # locals
102 g = f # globals
103
104 Names and Attributes
105 --------------------
106
107 No operator usage: all operators are converted to invocations, including
108 all attribute access except static references to modules using the
109 following notation:
110
111 __module__(package)
112 __module__(package.module)
113 package.module # shorthand where dot notation is used
114
115 In general, attribute access must use an explicit function indicating the
116 kind of access operation being performed. For example:
117
118 __loadaddress__(obj, attrname)
119 __loadaddresscontext__(obj, attrname)
120 __loadaddresscontextcond__(obj, attrname)
121 __loadattr__(obj, attrname)
122 __loadattrindex__(obj, attrname)
123 __loadattrindexcontext__(obj, attrname)
124 __loadattrindexcontextcond__(obj, attrname)
125
126 __storeaddress__(obj, attrname, value)
127 __storeaddresscontext__(obj, attrname, value)
128 __storeattr__(obj, attrname, value)
129 __storeattrindex__(obj, attrname, value)
130
131 Operators and Invocations
132 -------------------------
133
134 Conventional operators use the operator functions.
135
136 Special operators could also use the operator functions (where available)
137 but might as well be supported directly:
138
139 __is__(a, b)
140
141 Logical operators involving short-circuit evaluation could be represented
142 as function calls, but the evaluation semantics would be preserved:
143
144 __and__(...) # returns the first non-true value or the final value
145 __not__(obj) # returns the inverse of the boolean interpretation of obj
146 __or__(...) # returns the first true value or the final value
147
148 Comparisons could be rephrased in a verbose fashion:
149
150 a < b < c becomes lt(a, b) and lt(b, c)
151 or __and__(lt(a, b), lt(b, c))
152
153 Advanced Control-Flow
154 ---------------------
155
156 Any statements requiring control-flow definition in terms of blocks must
157 be handled in the language as the notions of labels and blocks are not
158 introduced earlier apart from the special case of jumping to another
159 callable (described below).
160
161 Special functions for low-level operations:
162
163 __check__(obj, type)
164 __jump__(callable)
165
166 Function/subroutine definition with entry points for checked and unchecked
167 parameters.
168
169 def fn_checked(self, ...):
170 __check__(self, Type) # raises a TypeError if not isinstance(self, Type)
171 __jump__(fn_unchecked) # preserves the frame and return address
172
173 def fn_unchecked(self, ...):
174 ...
175
176 Exceptions must also be handled in the language.