Learn Worst
Here’s a medium-length tutorial. It should give you a feel for how Worst works; by the end, you should be able to read and understand simple programs.
When you start the interpreter, you’ll be greeted by a message followed by the prompt.
$ rlwrap lworsti
Welcome to the Worst interactive environment. Type help for assistance.
worst () >
The parts of the prompt, from left to right:
worst
- Just so you don’t forget.()
- The current state of the stack.>
- A prompt marker of no significance.
Worst is a stack-based language. The stack is, simply, a pile of values. It starts out empty and new things go on the right. Any piece of data you want to deal with will go on the stack at some point, and many functions will take things off the stack as input and leave things on it as output.
For example, you could enter two numbers to put them on the stack,
and use add
to replace them with their sum:
worst () > 1
worst (1) > 2
worst (1 2) > add
worst (3) >
You can do more than one thing per line:
worst (3) > 4 5 6
worst (3 4 5 6) > add add
worst (3 15) > add 7 add
worst (25) >
Use drop
to discard the value at the top of the stack:
worst (25) > drop
worst () >
Try something else, like swap
or print
:
worst () > "test\n" 8
worst ("test\n" 8) > swap
worst (8 "test\n") > print
test
worst (8) > drop
worst () >
Most Worst is just words like these.
Try help
if you get stuck. It’s a work in progress though.
Syntax
Here’s most of the syntax you will find in a Worst program.
; single-line comments
123 45.6 ; numbers
#t #f ; boolean true and false
symbols ; uh, symbols
"strings" ; ... strings
"strings\nwith \"escape\" sequences"
(lists {which can be [delimited] using () and {} and []}
and (can [be [nested] (however) you {like}]) {
and can contain "any other data as well"
})
That’s it.
All programs are lists, which can contain other lists,
symbols, and things that are neither lists nor symbols.
Whitespace and indentation are not significant, except to separate
consecutive data (i.e. hello123
and hello 123
are different things).
Definitions
Time for a recap:
- Put things on the stack by typing them in
- Except plain words. They’re called ‘symbols’ and are treated specially
- Special treatment includes doing stuff other than putting them on the stack
- Symbols encountered so far include
add
,drop
, andswap
- Surely there must be some way of adding your own symbols
There sure is! Now is a good time to define
a function:
worst () > define nine [4 5 add]
worst () > nine
worst (9) >
This is new. Usually, things are done one at a time, so you might think it would go like this:
define
clearly does something. There’s nothing on the stack though, so its options are limited.nine
isn’t defined, so should the interpreter crash or something?- Okay, it didn’t crash,
but shouldn’t the list
(1 2 add)
end up on the stack at least?
In fact, define
is able to read the symbol nine
and a list,
and combine them into a function definition.
How it does this will have to wait for the next section,
but first, let’s get a little more funky:
worst () > define add-ten [10 add]
worst () > 11 add-ten
worst (21) >
This time, the definition doesn’t exactly work on its own -
add
takes two things off the stack, but clearly, 10
is only one thing.
The other thing must be on the stack before add-ten
is called,
so that add
has enough things to work with.
If you consider add
as a function that takes two arguments,
then add-ten
implicitly takes one argument.
If you try add-ten
without anything on the stack, i.e. without any arguments,
then the interpreter will crash because add
doesn’t know what to do with
only one number.
The next section
So, how does define
do the thing where it reads the next thing without
evaluating it?
Consider, first, quote
:
worst () > quote add
worst (add) >
Here, instead of add
doing any addition,
quote
puts it on the stack.
Useful, sort of.
Let’s combine it with uplevel
for something slightly more interesting:
worst () > define cool-quote [quote quote uplevel]
worst () > cool-quote hello
worst (hello) >
Now, uplevel
does something completely new.
It temporarily jumps back up to whatever called it in order to
evaluate the symbol on top of the stack,
stashing the current function call away for later.
In this case, it uses quote
to read hello
and put it on the stack.
In the case of define
, it uses uplevel
three times:
twice to read the name and body of the definition,
and the third time to add the definition in the right place.
A slightly better example
That was several words strewn together,
so have a look at this next bit to show how useful
this quote
/uplevel
combo can be:
worst () > define + [quote quote uplevel add]
worst () > 12 + 13
worst (25) >
Now we’re getting somewhere! Regular-looking addition!
Here’s how 12 + 13
works, step by step:
- Put
12
on the stack as normal. - Evaluate
+
. - Inside
+
,quote
takes the next thing (the secondquote
) and puts it on the stack. uplevel
steps out of+
and evaluates the symbolquote
(because it’s on the stack).quote
then takes13
as the next thing after+
, and puts it on the stack.- Back inside
+
,add
takes12
and13
from the stack and adds them together. add
puts25
on the stack. The end. <applause dies down eventually>
As you may expect, quote quote uplevel
is fairly common,
so it has its own shorthand: upquote
.
Uh, that’s it for now
Thanks for reading so far. There’s no advanced tutorial yet, mostly because there’s barely any “advanced” Worst at all, and there’s no reference manual or other documentation yet either. If you like, you can read the source code for the interpreter, linked on the downloads page.