examples/reader-macros.js

Summary

Maintainability
A
0 mins
Test Coverage
/**
 * This is an example of how you can extend LIPS parser using reader macros
 *
 * This is part of the LIPS JavaScript interpter
 * Copyright (c) Jakub T. Jankiewicz <https://jcubic.pl/me>
 * Released under MIT license
 */
/* global lips */
(function() {
    const { env, specials, Symbol, Pair, Macro, evaluate, LNumber } = lips;
    // new vector type #(1 2 3) will create new array
    // you can use any expression inside that will evaluate to list that in turn will be
    // converted to array by the macro. Parser will convert #(1 2 3) into (vector (1 2 3))
    // so vector needs to be LIPS macro
    specials['#'] = Symbol('vector');
    env.set('vector', new Macro('vector', function(code, { dynamic_scope, error }) {
        const args = { env: this, error };
        if (dynamic_scope) {
            args.dynamic_scope = this;
        }
        var wrap = new Pair(new Symbol('list'), code.car);
        return this.get('list->array')(evaluate(wrap, args));
    }));

    // new Alist of object syntax you use is like this:
    // {}((foo . 10)) it will also evaluate all pairs expressions like:
    // {}(((concat "foo" "-" "bar") . (+ 2 1))) it will create object {"foo-bar": 3}
    specials['{}'] = Symbol('make-object');
    env.set('make-object', new Macro('make-object', function(code, { dynamic_scope, error }) {
        const args = { env: this, error };
        if (dynamic_scope) {
            args.dynamic_scope = this;
        }
        return code.car.map((pair) => {
            const [car, cdr] = [pair.car, pair.cdr].map(obj => {
                if (obj instanceof Pair) {
                    return evaluate(obj, args);
                }
                return obj;
            }).map(obj => {
                // unwrap LNumbers
                if (obj instanceof LNumber) {
                    return obj.valueOf();
                }
                return obj;
            });
            return new Pair(car, cdr);
        }).to_object();
    }));
    env.set('object->string', function(obj) {
        return JSON.stringify(obj);
    });
})();