Sky 0.0.5: A not-quite-REPL

This is part of a series of posts about writing a simple interpreter for a small Lisp-like language. Please see here for an overview of the series.

Last time we added the ability to read Sky data from a C stream. This time we’re doing something with a smaller scope: adding some tests for reading and printing, plus a note-quite-REPL (specifically, without the “eval” part).

You can see the code as of this post here, and a comparison against last time here.

The tests

For the tests, we start with a directory containing some valid examples of Sky data. Specifically, we have:

  • A string containing every ASCII character
  • A list containing every ASCII character
  • The most-positive Sky integer (on 64-bit machines)
  • The least-positive Sky integer (on 64-bit machines)

Then we have a script that checks whether read and print are consistent. For each of the test files, it uses the sky binary to read the file and then print the data to a new file, and then uses diff to check that the file we printed is byte-for-byte identical to the file we read. If it’s not, it exits with an error code.

The final piece of the puzzle is in the makefile, which has a new check rule:

check:
    @tst/run.sh || (echo "Tests failed" && exit 1)

The end result is that we can run make all check, which will build Sky and then test that reading and printing are working as we expect.

We could go a lot further with testing, but I’m keeping it minimal for now. Testing will be easier once we can test Sky in Sky itself.

The not-quite-REPL

The function to implement a REPL-minus-eval is very simple now that we have both the read and print parts:

static void run_repl(void)
{
    value_t value;
    bool eof = false;

    fputs("Welcome to Sky. Use control-c to exit.\n", stdout);

    for (;;) {
        fprintf(stdout, "> ");
        fflush(stdout);
        value = read_from_stream(stdin, &eof);
        if (eof) break;
        println(stdout, value);
    }

    fputs("\nGoodbye\n", stdout);
}

The result is that we can interactively send expressions to Sky, which will read them and print them back. The important thing is that it’s not just echoing the text; the text is being read, resulting in Sky values, which are then printed.

Here’s a brief example session:

~/code/sky/> ./src/sky
Welcome to Sky. Use control-c to exit.
> 1
1
> one
one
> "foo\nbar"
"foo\nbar"
> (#\a #\b #\c)
(#\a #\b #\c)
> ^C
Goodbye

That’s all for this time.

Next time

Next time I think we’ll try to solve the problem I referenced when discussing printing, which is that there are currently some symbols which can be printed but not read.