git @ Cat's Eye Technologies Xoomonk / 6fefd6b
Initial import of Xoomonk spec. Cat's Eye Technologies 12 years ago
1 changed file(s) with 453 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 -> encoding: UTF-8
1
2 The Xoomonk Programming Language
3 ================================
4
5 Language version 0.1 Pretty Much Complete But Maybe Not Totally Finalized
6
7 Abstract
8 --------
9
10 _Xoomonk_ is a programming language in which _malingering updatable stores_
11 are first-class objects. Malingering updatable stores unify several language
12 constructs, including procedure activations, named parameters, and object-like
13 data structures.
14
15 Description
16 -----------
17
18 Overall, Xoomonk looks like a "typical" imperative language. The result
19 of evaluating an expression can be assigned to a variable, and the contents
20 of a variable can be used in a further expression.
21
22 | a := 1
23 | b := a
24 | print b
25 = 1
26
27 However, blocks of these imperative statements can appear as terms in
28 expressions; such blocks evaluate to entire updatable stores.
29
30 | a := {
31 | c := 5
32 | d := c
33 | }
34 | print a
35 = [c=5,d=5]
36
37 Once created, a store can be updated and accessed.
38
39 | a := {
40 | c := 5
41 | d := c
42 | }
43 | print a
44 | a.d := 7
45 | print a
46 | print a.c
47 = [c=5,d=5]
48 = [c=5,d=7]
49 = 5
50
51 A store can also be assigned to a variable after creation. Stores are
52 accessed by reference, so this creates two aliases to the same store.
53
54 | a := {
55 | c := 5
56 | d := c
57 | }
58 | b := a
59 | b.c := 17
60 | print a
61 | print b
62 = [c=17,d=5]
63 = [c=17,d=5]
64
65 To create an independent copy of the store, the postfix `*` operator is
66 used.
67
68 | a := {
69 | c := 5
70 | d := c
71 | }
72 | b := a*
73 | b.c := 17
74 | print a
75 | print b
76 = [c=5,d=5]
77 = [c=17,d=5]
78
79 Empty blocks are permissible.
80
81 | a := {}
82 | print a
83 = []
84
85 Once a store has been created, only those variables defined in the store
86 can be updated and accessed -- new variables cannot be added.
87
88 | a := { b := 6 }
89 | print a.c
90 ? Attempt to access an undefined variable
91
92 | a := { b := 6 }
93 | a.c := 12
94 ? Attempt to assign an undefined variable
95
96 Stores and integers are the only two data types in Xoomonk. However, there
97 are some special forms of the print statement, demonstrated here, which
98 allow for textual output.
99
100 | a := 65
101 | print char a
102 | print string "Hello, world!"
103 | print string "The value of a is ";
104 | print a;
105 | print "!"
106 = A
107 = Hello, world!
108 = The value of a is 65!
109
110 Xoomonk enforces strict block scope. Variables can be shadowed in an
111 inner block.
112
113 | a := 14
114 | b := {
115 | a := 12
116 | print a
117 | }
118 | print a
119 = 12
120 = 14
121
122 The special identifier `^` refers to the lexically enclosing store, that is,
123 the store which was in effect when the this store was defined.
124
125 | a := 14
126 | b := {
127 | a := 12
128 | print ^.a
129 | }
130 | print b.a
131 = 14
132 = 12
133
134 As long as a variable is assigned somewhere in a block, it can be accessed
135 before it is first assigned. In this case, it will hold the integer value 0.
136 It need not stay an integer, for typing is dynamic.
137
138 | b := {
139 | print a
140 | a := 12
141 | print a
142 | a := { c := 13 }
143 | print a
144 | }
145 | print b
146 = 0
147 = 12
148 = [c=13]
149 = [a=[c=13]]
150
151 We now present today's main feature.
152
153 It's important to understand that a block need not define all the
154 variables used in it. Such blocks do not immediately evaluate to a store.
155 Instead, they evaluate to an object called an _unsaturated store_.
156
157 Or, to put it another way:
158
159 If, in a block, you refer to a variable which has not yet been given
160 a value in that updatable store, the computations within the block are not
161 performed until that variable is given a value. Such a store is called an
162 _unsaturated store_.
163
164 | a := {
165 | d := c
166 | }
167 | print a
168 = [c=?,d=*]
169
170 An unsaturated store behaves similarly to a saturated store in certain
171 respects. In particular, unsaturated stores can be updated. If doing
172 so means that all of the undefined variables in the store are now defined,
173 the block associated with that store is evaluated, and the store becomes
174 saturated. In this sense, an unsaturated store is like a promise, and
175 this bears some resemblance to lazy evaluation (thus the term _malingering_).
176
177 | a := {
178 | print string "executing block"
179 | d := c
180 | }
181 | print a
182 | a.c := 7
183 | print a
184 = [c=?,d=*]
185 = executing block
186 = [c=7,d=7]
187
188 Once a store has become saturated, the block associated with it is not
189 executed again.
190
191 | a := {
192 | d := c
193 | }
194 | a.c := 7
195 | print a
196 | a.c := 4
197 | print a
198 = [c=7,d=7]
199 = [c=4,d=7]
200
201 The main program is a block. If it is unsaturated, no execution occurs
202 at all.
203
204 | print "hello"
205 | a := 14
206 | b := c
207 =
208
209 Variables cannot generally be accessed from an unsaturated store.
210
211 | a := {
212 | d := c
213 | }
214 | x := a.c
215 ? Attempt to access an unassigned variable
216
217 | a := {
218 | d := c
219 | }
220 | x := a.d
221 ? Attempt to access an unresolved variable
222
223 This is true, even if the variable is assigned a constant expression
224 inside the block.
225
226 | a := {
227 | b := 7
228 | d := c
229 | }
230 | x := a.b
231 ? Attempt to access an unresolved variable
232
233 If, however, the unsaturated store contains some variables that have
234 been updated since the store was created, those variable may be accessed.
235
236 | a := {
237 | print "executing block"
238 | p := q
239 | d := c
240 | }
241 | a.q = 7
242 | print a.q
243 = 7
244
245 Nor is it possible to assign a variable in an unsaturated store which is
246 defined somewhere in the block.
247
248 | a := {
249 | b := 7
250 | d := c
251 | }
252 | a.b := 4
253 ? Attempt to assign an unresolved variable
254
255 A variable is considered unresolved even if it is assigned within the block,
256 if that assignment takes place during or after its first use in an expresion.
257
258 | a := {
259 | b := b
260 | }
261 | a.b := 5
262 | print a
263 = [b=5]
264
265 | a := {
266 | print string "executing block"
267 | l := b
268 | b := 3
269 | l := 3
270 | }
271 | print string "saturating store"
272 | a.b := 5
273 | print a
274 = saturating store
275 = executing block
276 = [b=3,l=3]
277
278 We now describe how this language is (we reasonably assume) Turing-complete.
279
280 Operations are accomplished with certain built-in unsaturated stores. For
281 example, there is a store called `add`, which can be used for addition. These
282 built-in stores are globally available; they do not exist in any particular
283 store themselves. One uses the `$` prefix operator to access this global
284 namespace.
285
286 | print $add
287 | $add.x := 3
288 | $add.y := 5
289 | print $add.result
290 | print $add
291 = [x=?,y=?,result=*]
292 = 8
293 = [x=3,y=5,result=8]
294
295 Because using a built-in operation store in this way saturates it, it cannot
296 be used again. Typically you want to make a copy of the store first, and use
297 that, leaving the built-in store unmodified.
298
299 | o1 := $add*
300 | o1.x := 4
301 | o1.y := 7
302 | o2 := $add*
303 | o2.x := o1.result
304 | o2.y := 9
305 | print o2.result
306 = 20
307
308 Since Xoomonk is not a strictly minimalist language, there is a selection
309 of built-in stores which provide useful operations: `$add`, `$sub`, `$mul`,
310 `$div`, `$gt`, and `$not`.
311
312 Decision-making is also accomplished with a built-in store, `if`. This store
313 contains variables caled `cond`, `then`, and `else`. `cond` should
314 be an integer, and `then` and `else` should be unsaturated stores where `x` is
315 unassigned. When the first three are assigned values, if `cond` is nonzero,
316 it is assigned to `x` in the `then` store; otherwise, if it is zero, it is
317 assigned to `x` in the `else` store.
318
319 | o1 := $if*
320 | o1.then := {
321 | y := x
322 | print "condition is true"
323 | }
324 | o1.else := {
325 | y := x
326 | print "condition is false"
327 | }
328 | o1.cond := 0
329 = condition is false
330
331 | o1 := $if*
332 | o1.then := {
333 | y := x
334 | print "condition is true"
335 | }
336 | o1.else := {
337 | y := x
338 | print "condition is false"
339 | }
340 | o1.cond := 1
341 = condition is true
342
343 Repetition is also accomplished with a built-in store, `loop`. This store
344 contains an unassigned variable called `do`. When it is assigned a value,
345 assumed to be an unsaturated store, a copy of it is made. The variable
346 `x` inside that copy is assigned the value 0. This is supposed to saturate
347 the store. The variable `continue` is then accessed from the store. If
348 it is nonzero, the process repeats, with another copy of the `do` store
349 getting 0 assigned to its `x`, and so forth.
350
351 | l := $loop*
352 | counter := 5
353 | l.do := {
354 | y := x
355 | print ^.counter
356 | o := $sub*
357 | o.x := ^.counter
358 | o.y := 1
359 | ^.counter := o.result
360 | continue := o.result
361 | }
362 | print string "done!"
363 = 5
364 = 4
365 = 5
366 = 2
367 = 1
368 = done!
369
370 Because the `loop` construct will always execute the `do` store at least once
371 (even assuming its only unassigned variable is `x`), it acts like a so-called
372 `repeat` loop. It can be used in conjunction with `if` to simulate a
373 so-called `while` loop. With this loop, the built-in operations provided,
374 and variables which may contain unbounded integer values, Xoomonk should
375 be uncontroversially Turing-complete.
376
377 Finally, there is no provision for defining functions or procedures, because
378 malingering stores can act as these constructs.
379
380 | perimeter := {
381 | o1 := $mul*
382 | o1.x := x
383 | o1.y := 2
384 | o2 := $mul*
385 | o2.x := y
386 | o2.y := 2
387 | o3 := $add*
388 | o3.x := o1.result
389 | o3.y := o2.result
390 | result := o3.result
391 | }
392 | p1 := perimeter*
393 | p1.x := 13
394 | p1.y := 6
395 | print p1.result
396 | p2 := perimeter*
397 | p2.x := 4
398 | p2.y := 1
399 | print p2.result
400 = 38
401 = 10
402
403 Grammar
404 -------
405
406 Xoomonk ::= { Stmt }.
407 Stmt ::= Assign | Print.
408 Assign ::= Ref ":=" Expr.
409 Print ::= "print" ("string" <string> | "char" Expr | Expr) [";"].
410 Expr ::= (Block | Ref | Const) ["*"].
411 Block ::= "{" { Stmt } "}".
412 Ref ::= Name {"." Name}.
413 Name ::= "^" | "$" <alphanumeric> | <alphanumeric>.
414 Const ::= <integer-literal>.
415
416 Discussion
417 ----------
418
419 There is some similarity with Wouter van Oortmerssen's language Bla, in that
420 function environments are very close cousins of updatable stores. But
421 Xoomonk, quite unlike Bla, is an imperative language; once created, a store
422 may be updated at any point. And, of course, this property is exploited in
423 the introduction of malingering stores.
424
425 Xoomonk originally had an infix operator `&`, which takes two stores as its
426 arguments, at least one of which must be saturated, and evaluates to a third
427 store which is the result of merging the two argument stores. This result store
428 may be saturated even if only one of the argument stores was saturated, if
429 the saturated store gave all the values that the unsaturated store needed.
430 This operator was dropped because it is mostly syntactic sugar for assigning
431 each of the desired variables from one store to the other. However, it does
432 admittedly provide a very natural syntax, which orthogonally includes "named
433 arguments", when using unsaturated stores as procedures:
434
435 perimeter = {
436 # see example above
437 }
438 g := perimeter* & { x := 13 y := 6 }
439 print g.result
440
441 Xoomonk, as a project, is also an experiment in _test-driven language
442 design_. As you can see, I've described the language with a series of
443 examples, written in (something close to) Falderal format, each of which
444 could be used as a test case. This should make implementing an interpreter
445 or compiler for the language much easier, when I get around to that.
446
447 Happy malingering!
448
449 -Chris Pressey
450 Cat's Eye Technologies
451 August 7, 2011
452 Evanston, IL