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

function _repr_list(lis,     tv, t, v, pr, car, cdr, r) {
    r = "" lis
    for(; !_is_null(lis); lis=cdr) {
        car = _car(lis)
        cdr = _cdr(lis)
        r = r " -> " cdr
    }
    return r
}
        
function _repr(cell,      tv, t, v) {
    if(_is_literal(cell)) {
        if(cell ~ /^#/) return substr(cell,3)+0
        else if(cell == "t") return "true"
        else if(cell == "f") return "false"
        else if(cell == "nil") return "()"
        else return "[repr unimplemented for literal " cell "]"
    } else {
        t = _TYPE[cell]
        if(t == "(") return _repr_cons(cell)
        else if(t == "s") return _repr_string(cell)
        else if(t == "'") return _repr_symbol(cell)
    }
}

function _repr_string(n) {
    return "\"" _STRING[n] "\""
}

function _repr_cons(n,     pr, car, cdr, r, tv, t, v) {
    if(_is_null(n)) { # the empty list
        return "()"
    } else {
        car = _car(n)
        cdr = _cdr(n)
        r = "(" _repr(car)
        if(_is_null(cdr)) { # a list with length 1
            return r ")"
        } else if(_TYPE[cdr] == "(") { # a list
            while(!_is_null(cdr)) {
                n = cdr
                car = _car(n)
                cdr = _cdr(n)
                r = r " " _repr(car)
            }
            r = r ")"
            return r
        } else { # a pair
            return r " . " _repr(cdr) ")"
        }
    }
}

function _repr_symbol(n) {
    return _SYM_NUMBERS[n]
}

function _print(x) {
    if(_OUTPUT_REDIR_NAME) {
        if(_OUTPUT_REDIR_KIND == ">") {
            print _repr(x) > _OUTPUT_REDIR_NAME
            _OUTPUT_REDIR_KIND = ">>"
        } else if(_OUTPUT_REDIR_KIND == ">>") {
            print _repr(x) >> _OUTPUT_REDIR_NAME
        } else if(_OUTPUT_REDIR_KIND == "|") {
            print _repr(x) | _OUTPUT_REDIR_NAME
        }
    } else {
        print _repr(x)
    }
}