A Lisp implemented in AWK
# SPDX-License-Identifier: BSD-2-Clause

function _eval3_other_special_forms(form, env, d,      car, a) {
    car = _car(form)
    if(car == _symbol("as-number"))
        return _as_number(_eval3(_cadr(form), env, env, d+1))
    else if(car == _symbol("gc-dot"))
        # two filenames: one for marks and one for sweeps
        return _gc_dot(_cons(env,
                             _cons(_GLOBALS,
                                   _cons(_MACROS,
                                         _cons(_COMPARED_SYMBOLS,
                                               _nil())))),
                       _STRING[_cadr(form)],
                       _STRING[_caddr(form)])
    else if(car == _symbol("gc")) 
        return _gc(_cons(env,
                         _cons(_GLOBALS,
                               _cons(_MACROS,
                                     _cons(_COMPARED_SYMBOLS,
                                           _nil())))))
    else if(car == _symbol("dump"))
        # the first argument is a filename as an awk string
        return _dump_overwrite(_STRING[_eval3(_cadr(form), env, env, d+1)])
    else if(car == _symbol("dump-append"))
        return _dump_append(_STRING[_eval3(_cadr(form), env, env, d+1)])
    else if(car == _symbol("dump-append-changing-main"))
        # the breaking point was here. here, unlike the other dumps,
        # we break out the awkification of the parameters into the awk
        # function implementing the form.
        return _dump_append_changing_main(_eval3(_cadr(form), env, env, d+1),
                                          _eval3(_caddr(form), env, env, d+1))
    else if(car == _symbol("dump-dot"))
        return _dump_dot(_STRING[_eval3(_cadr(form), env, env, d+1)])
    else if(car == _symbol("cell-info"))
        return _cons(_cons(_symbol("cells-ever"), _cons(_number(N), _nil())),
                     _cons(_cons(_symbol("cells-now"), _cons(_number(length(_TYPE)), _nil())),
                           _nil()))
    else if(car == _symbol("repl"))
        # this is likely only to be called once, ever
        return _repl()
    else _builtin_mischaracterization("_eval3_other_special_forms", car)
}

function _as_number(val) {
    if(_TYPE[val] == "s") {
        # copypasted from reader.awk.
        if(_STRING[val] ~ /^(\+|-)?([0-9]+\.)?[0-9]+([eE][+-]?[0-9]+)?$/) {
            return _number(_STRING[val])
        } else {
            logg_err("_as_number", "this does not appear to be a number: " awkescape(_STRING[val]))
            return _nil()
        }
    } else {
        logg_err("_as_number", "as-number value should be a string")
        return _nil()
    }
}