2019-09-21

(Home)

I first announced Worst on 1st April 2019, to much confusion, and I’ve been working quietly on it since.

Now, I’ve decided to write about what I’ve been working on and show it to people on the Internet, just to demonstrate that this really is an actual, earnest attempt at a programming language.

Here’s what I’ve been doing.

A new interpreter

Most notably, I completely rewrote the interpreter, moving from around 8,000 lines of Rust to 900 lines of Typed Racket.

I wanted to start again with all the knowledge I’d gained by messing around within the Rust version. It had grown messy and convoluted as I tried to refine what needed to be in the language, grafting new ideas on to the vestigal remains of previous experiments without doing nearly enough pruning.

I’ve started again a few times already, but this attempt is the most complete — and considering how little time it needed to get to this point, I’m confident this means it is simple enough to stay as simple as it is for quite some time.

The new interpreter is a single file; its 900 lines includes the code itself, blank space, Vim folds, tests, a license, and full documentation in the form of an in-line walkthrough of the implementation. Please read it if you would like to know how Worst works. It’s not exactly a light read, but it should help you to understand what I’m trying to achieve (and how to write your own interpreter).

Syntax forms

I made a few bits of syntax to show off what you can do from within Worst. To use them, just import them like any other library.

import syntax/function

function hello(name) {
    "Hello, " print name print "!\n" print
}
hello("World")

; Multiple arguments.
; Using () and {} instead of [] is just a style choice.
function plus(a b) { a b add }

; Invocation accepts arbitrary expressions.
hello(plus(6 7) ->string)
import syntax/assign

; Take stuff off the stack and name it
1 2 3 => [one two three]
; Also works the other way around
[seven] := 7

; and-five(x) -> x, (x + 5)
function and-five(n) { n 5 n add }
; Works with function syntax
and-five(4) => [four nine]
[six eleven] := and-five(6)

Plus some less interesting things like cond, objects, definition attributes, and lexical bindings.

The short-term goal of adding these small pieces of syntax is to make it easier to write programs without needing to think about the state of the data stack. Eventually, you’ll be able to pick from a library of syntax forms and combine them into an interpreter for a completely different language.

Documentation system

The interpreter includes a help and documentation system.

Type help for help. It will show you some help. If you type help help it will help you with help.

Try help tags to list the different help tags available; for instance, help numeric will show all topics tagged numeric.

You can document code like this:

import syntax/attributes
import doc
define cool [
    @[documentation [
        title "Be cool"
        description "Use this function to be really cool."
        usage "how cool"
        example "600 cool"
        tags [very cool]
    ]]
    1337 add
]

Then, when issuing help cool, you will see some help. Cool.

You can also check documentation coverage like this:

import doc/check
check-docs

It will list all undocumented definitions, and whatever is missing from partially-documented definitions.

The available help is currently nowhere near complete, but it’s a start.

That’s it, really

Thanks for reading. I’ll add a tag to the repository and call this a release.

There’s some extra stuff in there too, including a module system, terminal formatting with ANSI escape codes, list quasiquotation, and mutable dictionaries, which are starting to look like the beginnings of a standard library.

I’ll try to make more updates like this in the future, even if just to give myself something to work towards once in a while. In no particular order, here’s what I want to work on next:

  • A nice way of redefining the reader for new character syntax instead of completely relying on Racket’s read

  • A combined property-based testing and contract system

  • Optimisation and compilation

  • Some kind of library for making games

  • IDE-like features for the REPL to make it nicer to use