git @ Cat's Eye Technologies Pixley / e9c41da
Convert main document to Markdown format. --HG-- rename : doc/pixley.html => doc/Pixley.markdown catseye 13 years ago
2 changed file(s) with 241 addition(s) and 255 deletion(s). Raw diff Collapse all Expand all
0 The Pixley Programming Language
1 ===============================
2
3 Language version 2.0, distribution revision 2011.1209
4
5 Introduction
6 ------------
7
8 *Pixley* is a strict and purely functional subset of R^(5)RS Scheme.
9 All Pixley programs are also therefore Scheme programs.
10
11 Pixley was designed for "bootstrappability". I aimed to encompass a
12 minimal subset of Scheme that was still expressive enough to
13 permit writing a Pixley interpreter without too much pain.
14
15 Semantics
16 ---------
17
18 Pixley implements the following functions and forms from Scheme
19 (listed in alphabetical order):
20
21 * `car`
22 * `cdr`
23 * `cond` / `else`
24 * `cons`
25 * `equal?`
26 * `lambda`
27 * `let*`
28 * `list?`
29 * `quote`
30
31 For the precise meanings of each of these forms, please refer to the
32 Revised^(5) Report on the Algorithmic Language Scheme.
33
34 Pixley only understands the Scheme datatypes of lists, symbols, function
35 values (lambdas), and booleans. Pixley's behaviour regarding any attempt
36 to produce a value of any other type is undefined. Neither is its
37 behaviour defined for s-expressions which result in errors when evaluated
38 as Scheme programs.
39
40 Syntax
41 ------
42
43 Pixley's syntax is a strict subset of Scheme's. The meanings of
44 syntactical constructs which are valid in Scheme but not defined in Pixley
45 (such as numbers, strings, comments, quasiquoting, or hygienic macros) are
46 undefined.
47
48 Of literal values, only those of list type can be directly introduced
49 through syntactical elements. Like Scheme, a literal null list can be
50 denoted by `(quote ())`. (However, `()` by itself is considered to be an
51 illegal, empty application.) Literal symbols may be introduced through
52 the `quote` form, literal function values can be produced through the
53 `lambda` form, and the two boolean values can be produced through the use
54 of trivial tests such as `(equal? (quote ()) (quote ()))` and
55 `(equal? (quote a) (quote b))`.
56
57 Reference Implementation
58 ------------------------
59
60 The reference implementation of Pixley, `pixley.pix`, is written in 122
61 lines of Pixley (or, if you prefer, 122 lines of Scheme; and if you prefer
62 more Scheme-ly metrics, it consists of 405 instances of 53 unique symbols
63 in 668 cons cells.)
64
65 `pixley.pix` does not include a lexical processor: the Pixley program to
66 be interpreted must be made available to the interpreter as a native
67 s-expression. Since Pixley does not implement `define`, this is usually
68 achieved by applying a textual copy of `pixley.pix` (a `lambda` expression)
69 to the s-expression to be interpreted as a Pixley program.
70
71 Because `pixley.pix` is written in Pixley, multiple copies can be applied
72 successively with equivalent semantics. For example, having `pixley.pix`
73 interpret some program `foo.pix` should produce the same observable
74 behaviour (modulo performance) as having `pixley.pix` interpret `pixley.pix`
75 interpreting `foo.pix`, or having `pixley.pix` interpret `pixley.pix`
76 interpret `pixley.pix` interpreting `foo.pix`, etc. etc. ad infinitum.
77 The test suite for the Pixley reference interpreter does just that,
78 running through the set of tests at successively higher "degrees".
79 This is an example of a *computational automorphism* and is a property of
80 any bootstrapped universal computer (or rather, of the Turing-complete
81 language of that computer.)
82
83 The Pixley reference interpreter is highly meta-circular, implementing
84 e.g. Pixley's `car` simply in terms of the underlying Pixley (or Scheme)
85 `car`. The datatypes of Pixley are likewise directly represented by the
86 corresponding datatypes in the underlying language.
87
88 Environments are represented as lists similar to association lists,
89 except containing two-element sublists instead of pairs, because Pixley
90 can't directly represent pairs. Each sublist's first element is a symbol
91 naming the identifier, and the second is the value to which it is bound.
92
93 History
94 -------
95
96 ### Pixley 1.0 ###
97
98 Pixley 1.0 was released on May 1st, 2009, from Cupertino, California.
99
100 In addition to the 10 Scheme symbols listed above, Pixley 1.x also
101 implemented the Scheme functions `cadr` and `null?`. However, it was
102 found that the interpreter was actually shorter if those functions were
103 defined only locally within the interpreter. They were thus removed from
104 the Pixley language in version 2.0. It is easy enough to apply the same
105 technique to any Pixley 1.x program to convert it to Pixley 2.0; simply
106 wrap it in the following:
107
108 (let* ((cadr (lambda (alist)
109 (car (cdr alist))))
110 (null? (lambda (expr)
111 (equal? expr (quote ())))))
112 ...)
113
114 ### Pixley v1.1 ###
115
116 Pixley 1.1 was released on November 5th, 2010, from Evanston, Illinois.
117
118 Funny story! So I was writing writing stuff in C to compile with DICE C
119 under AmigaOS 1.3, right? And I was looking for something to write, and I
120 decided to implement Pixley in C. And that was going pretty well; as I was
121 implementing each command, I was making up ad-hoc test cases for it, and I
122 was thinking "Hey, I should record these somewhere and make a test suite for
123 the Pixley reference distribution!" Of course, I never did record those
124 cases, but in the following weeks I started doing various other things with
125 the Pixley project, and at one point, decided anew that it would be a good
126 idea to bulk up the test cases.
127
128 So I started writing more test cases, right? And I got to testing `list?`.
129 Well, `(list? (lambda (x) x))` should be *false*, right? Sure. Except it
130 wasn't.
131
132 Well, I went to the docs and saw that there was an easy explanation for this.
133 This was for Pixley 1.0, mind you, and they've changed since then, but they
134 told me that:
135
136 > Some places where the underlying and interpreted representations must
137 > differ are in the data types, namely lists and lambda functions.
138
139 > Each interpreted list is represented as a two-element underlying list.
140 > The first element is the atom `__list__` and the second element is the
141 > (interpreted) list itself.
142
143 > Each interpreted lambda function is represented by an underlying list
144 > of four elements: the atom `__lambda__`, a representation of the enclosing
145 > environment, a list of the formal arguments of the function, and the
146 > (interpreted) body of the function.
147
148 In other words, in the reference interpreter, both lists and function values
149 are represented with lists; you tell them apart by looking at the first
150 element, which is `__lambda__` for a function value and `__list__` for a list.
151 And `list?` was probably just looking at the representation list and not
152 checking the first element, right? Sure. Except, no, it was much more.
153
154 It turns out that while function values were in fact represented by lists
155 with `__lambda__` as the first element, lists were just represented by lists.
156 Which means that there was an overlap between the types: a function value was,
157 at the Pixley level, a kind of list, and could be treated just like one, for
158 example with `car` and `cdr`. This is clearly not kosher R^(5)RS, which has
159 a whole *section* titled "Disjointness of types". (Of course, neither "list"
160 nor "function value" is mentioned in that section, but I'd say the spirit of
161 the law is pretty clear there or whatever.)
162
163 So this meant I had to fix the Pixley interpreter! But first, I had to make a
164 decision: how to represent lists? Well, there were two general paths here:
165 more meta-circular, or less. I could make the implementation conform to the
166 documentation, making it less meta-circular, but then I'd have to be changing
167 everything that built (or touched) a list to build (or check for) a list with
168 `__list__` at its head. Doable, but kind of distasteful. Alternatively, I
169 could make it more meta-circular: keep lists represented as lists, and
170 go one further by representing function values as function values. This is a
171 little unilluminating, as it no longer lays bare how function values work;
172 but this is made up for by the fact that most of the mechanics have to
173 continue to exist in the implementation (just in different places) and there
174 is a modest savings of space (because we can fall back on the implementing
175 language's semantics for cases like trying to execute a non-function.)
176 So that's what I did.
177
178 Now, this technically changed the semantics of the language, because gosh
179 you *could* have been relying on the fact that `(car (lambda (x) x))`
180 evaluates to `__lambda__`, in your Pixley programs, and we can't have that,
181 can we? So the language version was bumped up to 1.1.
182
183 #### Goodies ####
184
185 The Pixley 1.1 distribution also included the following supplementary
186 material:
187
188 * An enlarged test suite (previously mentioned).
189 * A REPL (read-eval-print loop, or "interactive mode" interpreter), written
190 in Scheme.
191 * A statistics generator, written in Scheme, which counts the cons cells,
192 symbol instances, and unique symbols present in a given s-expression.
193 This was to measure the complexity of the Pixley interpreter.
194 * A Mini-Scheme driver. During my adventures in getting programs to run
195 under AmigaOS 1.3, I compiled Mini-Scheme thereunder, and got Pixley to
196 run under it by including the Pixley interpreter in Mini-Scheme's
197 `init.scm` file and invoking it therein. From this I conclude that,
198 although I have not confirmed this is in a solid way by looking at the
199 spec or anything, Pixley is also a strict subset of R^(4)RS Scheme.
200
201 ### Pixley 2.0 ###
202
203 As previously mentioned, Pixley 2.0 removes the `cadr` and `null?`
204 functions from the language.
205
206 #### Goodies ####
207
208 The Pixley 2.0 distribution also includes the following supplementary
209 material:
210
211 * Bourne Shell scripts to run Pixley programs which are stored in individual
212 files. `pixley.sh` runs either a self-contained Pixley program from a
213 single file, or evaluates a Pixley file to a function value and applies it
214 to an S-expression stored in a second file. `scheme.sh` does the same
215 thing, but with Scheme, as a sanity-check. By default these scripts use
216 `plt-r5rs` for the Scheme interpreter, but that can be changed with an
217 environment variable.
218 * A P-Normalizer written in Pixley, probably the first non-trivial Pixley
219 program to be written, aside from the Pixley interpreter itself. P-Normal
220 Pixley is a simplified version of Pixley where `let*` can only bind one
221 identifer to one value and `cond` can only make one test, like Scheme's
222 `if`. This form is described more fully in the [Falderal literate test
223 suite for the P-Normalizer](../eg/p-normal.falderal).
224 * Test suites, written in Falderal, for both Pixley and the P-Normalizer.
225 The original test suite written in Scheme, which runs successively deeper
226 nested copies of the Pixley interpreter, is still included in the
227 distribution.
228 * A few other standalone Pixley examples, including `reverse.pix`,
229 which reverses the given list.
230
231 Conclusion
232 ----------
233
234 The last main division of a discourse, usually containing a summing up of
235 the points and a statement of opinion or decisions reached.
236
237 Keep Smiling! (I could never stand those "Home Sweet Home" folks.)
238 Chris Pressey
239 December 9th, 2011
240 Evanston, Illinois
+0
-255
doc/pixley.html less more
0 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/2002/REC-xhtml1-20020801/DTD/xhtml1-strict.dtd">
1 <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
2 <head>
3 <title>The Pixley Programming Language</title>
4 <!-- begin html doc dynamic markup -->
5 <script type="text/javascript" src="/contrib/jquery-1.6.4.min.js"></script>
6 <script type="text/javascript" src="/scripts/documentation.js"></script>
7 <!-- end html doc dynamic markup -->
8 </head>
9 <body>
10
11 <h1>The Pixley Programming Language</h1>
12
13 <p>Language version 2.0, distribution revision 2011.1209</p>
14
15 <h2>Introduction</h2>
16
17 <p><dfn>Pixley</dfn> is a strict and purely functional subset of R<sup>5</sup>RS Scheme.
18 All Pixley programs are also therefore Scheme programs.</p>
19
20 <p>Pixley was designed for "bootstrappability". I aimed to encompass a
21 minimal subset of Scheme that was still expressive enough to
22 permit writing a Pixley interpreter without too much pain.</p>
23
24 <h2>Semantics</h2>
25
26 <p>Pixley implements the following functions and forms from Scheme
27 (listed in alphabetical order):</p>
28
29 <ul>
30 <li><code>car</code></li>
31 <li><code>cdr</code></li>
32 <li><code>cond</code> / <code>else</code></li>
33 <li><code>cons</code></li>
34 <li><code>equal?</code></li>
35 <li><code>lambda</code></li>
36 <li><code>let*</code></li>
37 <li><code>list?</code></li>
38 <li><code>quote</code></li>
39 </ul>
40
41 <p>For the precise meanings of each of these forms,
42 please refer to the Revised<sup>5</sup> Report on the Algorithmic Language Scheme.</p>
43
44 <p>Pixley only understands the Scheme datatypes of lists, symbols, function values (lambdas),
45 and booleans. Pixley's behaviour regarding any attempt to produce a value of any other type is undefined.
46 Neither is its behaviour defined for s-expressions which result in errors
47 when evaluated as Scheme programs.</p>
48
49 <h2>Syntax</h2>
50
51 <p>Pixley's syntax is a strict subset of Scheme's. The meanings of
52 syntactical constructs which are valid in Scheme but not defined in Pixley (such as
53 numbers, strings, comments, quasiquoting, or hygienic macros) are undefined.</p>
54
55 <p>Of literal values, only those of list type can be directly introduced through syntactical
56 elements. Like Scheme, a literal null list can be denoted by <code>(quote ())</code>.
57 (However, <code>()</code> by itself is considered to be an illegal, empty application.)
58 Literal symbols may be introduced through the <code>quote</code> form,
59 literal function values can be produced through the <code>lambda</code>
60 form, and the two boolean values can be produced through the use of trivial
61 tests such as <code>(equal? (quote ()) (quote ()))</code>
62 and <code>(equal? (quote a) (quote b))</code>.</p>
63
64 <h2>Reference Implementation</h2>
65
66 <p>The reference implementation of Pixley, <code>pixley.pix</code>,
67 is written in 122 lines of Pixley (or, if you prefer, 122 lines of Scheme;
68 and if you prefer more Scheme-ly metrics, it consists of 405 instances of
69 53 unique symbols in 668 cons cells.)</p>
70
71 <p><code>pixley.pix</code> does not include a lexical processor:
72 the Pixley program to be interpreted
73 must be made available to the interpreter as a native s-expression.
74 Since Pixley does not implement <code>define</code>, this is
75 usually achieved by applying a textual copy of <code>pixley.pix</code>
76 (a <code>lambda</code> expression)
77 to the s-expression to be interpreted as a Pixley program.</p>
78
79 <p>Because <code>pixley.pix</code> is written in Pixley, multiple
80 copies can be applied successively with equivalent semantics.
81 For example, having <code>pixley.pix</code> interpret some
82 program <code>foo.pix</code> should produce the same
83 observable behaviour (modulo performance) as having
84 <code>pixley.pix</code> interpret <code>pixley.pix</code> interpreting
85 <code>foo.pix</code>, or having
86 <code>pixley.pix</code> interpret <code>pixley.pix</code>
87 interpret <code>pixley.pix</code> interpreting
88 <code>foo.pix</code>, etc. etc. ad infinitum.
89 The Scheme test suite for the Pixley reference interpreter does just that,
90 running through the set of tests at successively higher "degrees".
91 This is an example of a <dfn>computational automorphism</dfn>
92 and is a property of any bootstrapped universal computer (or rather,
93 of the Turing-complete language of that computer.)</p>
94
95 <p>The Pixley reference interpreter is highly meta-circular,
96 implementing e.g. Pixley's <code>car</code> simply in terms of the
97 underlying Pixley (or Scheme) <code>car</code>. The datatypes of
98 Pixley are likewise directly represented by the corresponding datatypes
99 in the underlying language.
100 Environments are represented as lists similar to association lists,
101 except containing two-element sublists instead of pairs, because Pixley
102 can't directly represent pairs. Each sublist's first element is a symbol
103 naming the identifier, and the second is the value to which it is bound.</p>
104
105 <h2>History</h2>
106
107 <h3>Pixley 1.0</h3>
108
109 <p>Pixley 1.0 was released on May 1<sup>st</sup>, 2009, from Cupertino,
110 California.</p>
111
112 <p>In addition to the 10 Scheme symbols listed above, Pixley 1.0 (and 1.1) also implemented
113 the Scheme functions <code>cadr</code> and <code>null?</code>. However, it was
114 found that the interpreter was actually shorter if those functions were defined
115 only locally within the interpreter. They were thus removed from the Pixley
116 language in version 2.0. It is easy enough to apply the same technique to any
117 Pixley 1.0 (or 1.1) program to convert it to Pixley 2.0; simply wrap it in the following:</p>
118
119 <pre>
120 (let* ((cadr (lambda (alist)
121 (car (cdr alist))))
122 (null? (lambda (expr)
123 (equal? expr (quote ())))))
124 ...)
125 </pre>
126
127 <h3>Pixley v1.1</h3>
128
129 <p>Pixley 1.1 was released on November 5<sup>th</sup>, 2010, from Evanston,
130 Illinois.</p>
131
132 <p>Funny story! So I was writing writing stuff in C to compile with DICE C for AmigaOS 1.3, right?
133 And I was looking for something to write, and I decided to implement Pixley in C.
134 And that was going pretty well; as I was implementing each command, I was making up
135 ad-hoc test cases for it, and I was thinking "Hey, I should record these somewhere and make a test
136 suite for the Pixley reference distribution!" Of course, I never did record those cases, but
137 in the following weeks I started doing various other things with the Pixley project, and
138 at one point, decided anew that it would be a good idea to bulk up the test cases.</p>
139
140 <p>So I started writing more test cases, right? And I got to testing <code>list?</code>.
141 Well, <code>(list? (lambda (x) x))</code> should be <em>false</em>, right? Sure.
142 Except it wasn't.</p>
143
144 <p>Well, I went to the docs and saw that there was an easy explanation for this. This was
145 for Pixley 1.0, mind you, and they've changed since then, but they told me that:</p>
146
147 <blockquote>
148 <p>Some places where the underlying and interpreted representations must
149 differ are in the data types, namely lists and lambda functions.</p>
150
151 <p>Each interpreted list is represented as a two-element underlying list. The
152 first element is the atom <code>__list__</code> and the second
153 element is the (interpreted) list itself.</p>
154
155 <p>Each interpreted lambda function is represented by an underlying list
156 of four elements: the atom <code>__lambda__</code>,
157 a representation of the enclosing environment, a list of the formal
158 arguments of the function, and the (interpreted) body of the function.</p>
159 </blockquote>
160
161 <p>In other words, in the
162 reference interpreter, both lists and function values are represented with lists; you tell
163 them apart by looking at the first element, which is <code>__lambda__</code> for a
164 function value and <code>__list__</code> for a list. And <code>list?</code> was
165 probably just looking at the representation list and not checking the first element,
166 right? Sure. Except, no, it was much more.</p>
167
168 <p>It turns out that while function values were in fact represented by lists
169 with <code>__lambda__</code> as the first element, lists were just represented by lists.
170 Which means that there was an overlap between the types: a function value was, at the Pixley
171 level, a kind of list, and could be treated just like one, for example with <code>car</code>
172 and <code>cdr</code>. This is clearly not kosher R<sup>5</sup>RS, which has a whole
173 <em>section</em> titled "Disjointness of types". (Of course, neither "list" nor
174 "function value" is mentioned in that section, but I'd say the spirit of the law is pretty
175 clear there or whatever.)</p>
176
177 <p>So this meant I had to fix the Pixley interpreter! But first, I had to make a decision: how to
178 represent lists? Well, there were two general paths here: more meta-circular, or less.
179 I could make the implementation conform to the documentation, making it less meta-circular,
180 but then I'd have to be changing everything that built (or touched) a list to build (or check
181 for) a list with <code>__list__</code> at its head. Doable, but kind of distasteful.
182 Alternatively, I could make it more meta-circular: keep lists represented as lists, and
183 go one further by representing function values as function values. This is a little unilluminating,
184 as it no longer lays bare how function values work; but this is made up for by the fact
185 that most of the mechanics have to continue to exist in the implementation (just in
186 different places) and there is a modest savings of space (because we can fall back on
187 the implementing language's semantics for cases like trying to execute a non-function.)
188 So that's what I did.</p>
189
190 <p>Now, this technically changed the semantics of the language, because gosh you
191 <em>could</em> have been relying on the fact that <code>(car (lambda (x) x))</code>
192 evaluates to <code>__lambda__</code>, in your Pixley programs, and we can't have that,
193 can we? So the language version was bumped up to 1.1.</p>
194
195 <h4>Goodies</h4>
196
197 <p>The Pixley 1.1 distribution also included the following supplementary material.</p>
198
199 <ul>
200 <li>An enlarged test suite (previously mentioned).</li>
201 <li>A REPL (read-eval-print loop, or "interactive mode" interpreter), written in Scheme.</li>
202 <li>A statistics generator, written in Scheme, which counts the cons cells, symbol
203 instances, and unique symbols present in a given s-expression. This was to measure the
204 complexity of the Pixley interpreter.</li>
205 <li>A Mini-Scheme driver. During my adventures in getting programs
206 to run under AmigaOS 1.3, I compiled Mini-Scheme thereunder, and got Pixley to run
207 under it by including the Pixley interpreter in Mini-Scheme's <code>init.scm</code> file and
208 <code>eval</code>'ing it therein. From this I conclude that, although I have not confirmed
209 this is in a solid way by looking at the spec or anything, Pixley is also a strict subset of
210 R<sup>4</sup>RS Scheme.</li>
211 </ul>
212
213 <h3>Pixley 2.0</h3>
214
215 <p>A previously mentioned, Pixley 2.0 removes the <code>cadr</code> and <code>null?</code>
216 functions from the language.</p>
217
218 <h4>Goodies</h4>
219
220 <p>The Pixley 2.0 distribution also includes the following supplementary material.</p>
221
222 <ul>
223 <li>Bourne Shell scripts to run Pixley programs which are stored in individual files.
224 <code>pixley.sh</code> runs either a self-contained Pixley program from a single file,
225 or evaluates a Pixley file to a function value and applies it to an S-expression stored in a
226 second file. <code>scheme.sh</code> does the same thing, but with Scheme, as a
227 sanity-check. By default these scripts use <code>plt-r5rs</code> for the Scheme interpreter,
228 but that can be changed with an environment variable.</li>
229 <li>A P-Normalizer written in Pixley, probably the first non-trivial Pixley program
230 to be written, aside from the Pixley interpreter itself. P-Normal Pixley is a simplified version of
231 Pixley where <code>let*</code> and <code>cond</code> only handle a single instance
232 of what they do (like <code>let</code> and <code>if</code> in Scheme.) This form is
233 described more fully in the <a href="../eg/p-normal.falderal">Falderal literate test
234 suite for the P-Normalizer</a>.</li>
235 <li>Test suites, written in Falderal, for both Pixley and the P-Normalizer. The
236 original test suite written in Scheme, which runs successively deeper nested copies of
237 the Pixley interpreter, is still included in the distribution.</li>
238 <li>A few other standalone Pixley examples, including <code>reverse.pix</code>,
239 which reverses the given list.</li>
240 </ul>
241
242 <h2>Conclusion</h2>
243
244 <p>The last main division of a discourse,
245 usually containing a summing up of the points
246 and a statement of opinion or decisions reached.</p>
247
248 <p>Keep Smiling! (I could never stand those "Home Sweet Home" folks.)
249 <br/>Chris Pressey
250 <br/>December 9<sup>th</sup>, 2011
251 <br/>Evanston, Illinois</p>
252
253 </body>
254 </html>