forked from perl11/potion
-
Notifications
You must be signed in to change notification settings - Fork 0
/
README
301 lines (208 loc) · 7.7 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
.ooo
'OOOo
~ p ooOOOo tion ~
.OOO
oO %% a little
Oo fast language.
'O
`
(o)
___/ /
/` \
/v^ ` ,
(...v/v^/
\../::/
\/::/
~ potion ~
Potion is an object- and mixin-oriented (traits)
language.
Its exciting points are:
* Just-in-time compilation to x86 and x86-64
machine code function pointers. This means
she's a speedy one. Who integrates very
well with C extensions.
The JIT is turned on by default and is
considered the primary mode of operation.
* Intermediate bytecode format and VM. Load
and dump code. Decent speed and cross-
architecture. Heavily based on Lua's VM.
* A lightweight generational GC, based on
Basile Starynkevitch's work on Qish.
<http://starynkevitch.net/Basile/qishintro.html>
* Bootstrapped "id" object model, based on
Ian Piumarta's soda languages. This means
everything in the language, including
object allocation and interpreter state
are part of the object model.
(See COPYING for citations.)
* Interpreter is thread-safe and reentrant.
I hope this will facilitate coroutines,
parallel interpreters and sandboxing.
* Small. Under 10kloc. Right now we're like
6,000 or something. Install sloccount
and run: make sloc.
* Reified AST and bytecode structures. This
is very important to me. By giving access
to the parser and compiler, it allows people
to target other platforms, write code analysis
tools and even fully bootstrapped VMs. I'm
not as concerned about the Potion VM being
fully bootstrapped, especially as it is tied
into the JIT so closely.
* Memory-efficient classes. Stored like C
structs. (Although the method lookup table
can be used like a hash for storing arbitrary
data.)
* The JIT is also used to speed up some other
bottlenecks. For example, instance variable
and method lookup tables are compiled into
machine code.
However, some warnings:
* Strings are immutable (like Lua) and byte
arrays are used for I/O buffers.
* No floating point support yet.
* No error handling. I'm wary of just tossing
in exceptions and feeling rather uninspired
on the matter. Let's hear from you.
~ a whiff of potion ~
5 times: "Odelay!" print.
Or,
add = (x, y): x + y.
add(2, 4) string print
Or,
hello =
"(x): ('hello ', x) print." eval
hello ('world')
~ building and installing ~
$ make
Look inside the file called INSTALL for options.
~ how it transpired ~
This isn't supposed to happen!
I started playing with Lua's internals and reading
stuff by Ian Piumarta and Nicolas Cannasse. And I,
well... I don't know how this happened!
Turns out making a language is a lovely old time,
you should try it. If you keep it small, fit the
VM and the parser and the stdlib all into 10k
lines, then it's no sweat.
To be fair, I'd been tinkering with the parser
for years, though.
~ the potion pledge ~
EVERYTHING IS AN OBJECT.
However, OBJECTS AREN'T EVERYTHING.
(And, incidentally, everything is a function.)
~ items to understand ~
1. A traditional object is a tuple of data
and methods: (D, M).
D is kept in the object itself.
M is kept in classes.
2. In Potion, objects are just D.
3. Every object has an M.
4. But M can be altered, swapped,
added to, removed from, whatever.
5. Objects do not have classes.
The M is a mixin, a collection
of methods.
Example: all strings have a "length"
method. This method comes with Potion.
It's in the String mixin.
6. You can swap out mixins for the span
of a single source file.
Example: you could give all strings a
"backwards" method. But just for the
code inside your test.pn script.
7. You can re-mix for the span of a
single closure.
To sum up:
EVERYTHING IS AN OBJECT.
EVEN MIXINS ARE OBJECTS.
AND, OF COURSE, CLOSURES ARE OBJECTS.
However, OBJECTS AREN'T EVERYTHING.
THEY ARE USELESS WITHOUT MIXINS.
~ unique ideas (to be implemented) ~
Potion does have a few unique features
underway.
* It is two languages in one.
The language itself is objects and closures.
Number add = (x): self + x.
But it also includes a data language.
app = [window (width=200, height=400)
[button "OK", button "Cancel"]]
The code and data languages can be interleaved
over and over again. In a way, I'm trying to find
a middle ground between s-expressions and stuff like
E4X. I like that s-expressions are a very light data
syntax, but I like that E4X clearly looks like data.
When s-expressions appear in Lisp code, they look
like code. I think it is nice to distinguish the two.
* Deeply nested blocks can be closed quickly.
I don't like significant whitespace, personally.
But I don't like end end end end.
say = (phrase):
10 times (i):
20 times (j):
phrase print
_say
The closing "_ say" ends the block saved to "say" var.
Normally, blocks are closed with a period. In this case
we'd need three periods, which looks strange.
say = ():
10 times:
20 times:
"Odelay!" print
...
If you prefer, you can give it some space. Or you can
use a variable name introduced by the block,
say = (phrase):
10 times (i):
20 times (j):
phrase print
_ phrase
say = (phrase):
10 times (i):
20 times (j):
phrase print
_ i
.
Maybe it all looks strange. I don't know. I'm just trying
things out, okay?
* Elimination of line noise.
I avoid @, #, $, %, {}.
Stick with ., |, (), [], =, !, ?. Easier on the eyes.
These are common punctuations in English.
* I try to defer to English when it comes to punctuation rules.
Period means "end". (In other langs it means "method call".)
Comma breaks up statements.
Space between messages gives a noun-verb feeling.
window open (width=400, height=500)
* Named block args.
(1, 2, 3) map (item=x, index=i): i display, x + 1.
~ feverish and fond thankyous ~
I am gravely indebted to Basile Starynkevitch, who fielded my
questions about his garbage collector. I favor French hackers
to an extreme (Xavier Leroy, Nicolas Cannasse, Guy Decoux,
Mathieu Bochard to name only a portion of those I admire) and
am very glad to represent their influence in Potion's garbage
collector.
Matz, for answering my questions about conservative GC and
for encouraging me so much. Potion's stack scanning code and
some of the object model come from Ruby.
Steve Dekorte for the Io language, libgarbagecollector and
libcoroutine -- I referred frequently to all of them in
sorting out what I wanted.
Of course, Mauricio Fernandez for his inspiring programming
journal housed at http://eigenclass.org/R2/ and for works
derived throughout the course of it -- extprot most of all.
Many of my thoughts about language internals (object repr,
GC, etc.) are informed by him.
Ian Piumarta for peg/leg. I use a re-entrant custom version
of it, but the original library is sheer minimalist parsing
amazement.
Final appreciations to Jonathan Wright and William Morgan
who pitched in, back in the wee hours of Potion's history.
Tanks.
~ license ~
See COPYING for legal information. It's an MIT license,
which lets you do anything you want with this. I'm hoping
that makes it very nice for folks who want to embed a little
Potion in their app!