Today’s plan is to work through an Eloquent JavaScript chapter with the accompanying exercises.

There are also some browser-based chapters in the same book, which look like they might have good exercises for building small apps.

Eloquent JavaScript

Day 6 Code

The Egg Programing Language exercise chapter from Eloquent JavaScript involves writing a parser and interpreter for a toy, Lisp-like programming language called Egg.

I used TypeScript, for which the initial work was mainly setting up the custom types / type aliases.

type ParseResult =
    {
        expr: EggExpr,
        rest: string
    }

type EggExpr
    = ValueToken
    | WordToken
    | ApplyExpr


type ValueToken
    = { type: ValueType, value: Value }

type WordToken
    = { type: WordType, name: string }

type ApplyExpr
    = { type: ApplyType, operator: WordToken, args: Array<EggExpr> }


type ApplyType = "apply";
type ValueType = "value";
type WordType = "word";

type Value = number | string

The type literals are maybe unnecessary, but I wanted to try it as it’s not a feature I’ve used in other statically typed languages.

Exercises: Arrays

The implementation of array is straightforward:

topScope.array = (...vals: Array<Value>): Array<Value> => {
    return vals;
}

topScope.length = (arr: Array<Value>): number => {
    return arr.length;
}

topScope.element = (arr: Array<Value>, i: number): Value => {
    const val = arr[i];
    if (val === undefined) {
        throw new RangeError(`${i} is out of range of array ${arr}`);
    }
    return val;
};

Since there is no error or undefined in the Egg language, attempting to index out of range throws an error.

Exercise: Comments

Following the hint, single-line comments starting with # are ignored. In this case, there is a recursive call required after consuming a comment line. Maybe there is a simpler, regex-based way to avoid the additiomal recursive call, but this seems simple enough.

function skipSpace(s: string): string {
    const firstChar = s.search(/\S/);
    if (firstChar == -1) {
        return "";
    } else {
        const s_ = s.slice(firstChar)
        if (s_[0] == '#') {
            return skipSpace(s_.slice(s_.search(/\n/) + 1));
        } else {
            return s_;
        }
    }

Exercise: Fixing Scope and Adding a set operator

set traverses scope upwards in search of a variable name that should exist (as opposed to define, which is intended for new variables.


specialForms.set = (args: Array<EggExpr>, scope: object) => {
    if (args.length != 2 || args[0].type != "word") {
        throw new SyntaxError("Incorrect use of set");
    } else {
        const name = args[0].name;
        const val = evaluate(args[1], scope);

        while (!Object.prototype.hasOwnProperty.call(scope, name)) {
            if (Object.getPrototypeOf(scope) === null) {
                throw new ReferenceError(`Could not find property ${name} to set with ${val}`);
            } else {
                scope = Object.getPrototypeOf(scope);
            }
        }
        scope[name] = val;
    }
};

Note that there’s no test framework, so I’m just compiling and testing with a series of console.log statements (and the print operator defined in Egg):

tsc egg.ts && node egg.js

Wrapping Up

Today was another short day, given long weekend activities. The Eloquent JavaScript is on the simpler side (certainly compared to Atencio), but it’s very clear and the exercises are helpful for my current level of JS. TypeScript didn’t get in the way today, and was quite helpful in forcing some upfront thought as to the exact types being manipulated. It’s hard to imagine coding without a live, reloading type checker…

In the remaining four days, I’m planning to work on the Eloquent Javascript browser-based and Node exercises, and maybe build something very simple like a todo list (by hand? with React or Vue?).

Todo / To Read

  • More chapters of Atencio
  • Eloquent JavaScript has exercises at the end of chapters, which might be worth exploring
  • Figure out how to use outDir(?) to compile .js files to separate subdirectory
  • Compiling with both TypeScript with Babel
  • Kyle Simpson, You Don’t Know JS
  • Composing Software, by Eric Elliott (https:// leanpub.com/composingsoftware)