#!/usr/bin/env node

const show_parsed = false;  /* Set true to see parsed expressions in output */

const readline = require('node:readline/promises');
const lexp = require( '../common/lexp' );

console.log( "lexp", lexp.version, "CLI (Reactor tool edition)" );

function emap( key, value ) {
    if ( Number.isNaN( value ) ) {
        return "--NaN--";
    } else if ( value === Infinity || value === -Infinity ) {
        return `--${value.toString()}--`;
    }
    return value;
}

function help() {
    console.log("Use CTRL-C, quit, or exit to terminate. Use '=' by itself to show defined variables.");
    console.log("For expression documentation, see https://github.com/toggledbits/lexpjs");
}

const ctx = lexp.get_context();

async function processLines() {
    const rl = readline.createInterface({ input: process.stdin, output: process.stdout, prompt: "lexpjs> " });
    help();
    process.stdout.write( "lexpjs> " );
    for await (const line of rl) {
        const c = line.trim();
        if ( "quit" === c || "exit" === c ) {
            process.exit( 0 );
            return;
        } else if ( "help" === c || "?" === c ) {
            help();
        } else if ( "=" === c ) {
            for ( const [k,v] of Object.entries( ctx.__lvar || {} ) ) {
                console.log(k, typeof v, v);
            }
            for ( const [k,v] of Object.entries( ctx.__func || {} ) ) {
                console.log(`${k}()`, "user-defined function");
            }
        } else {
            try {
                const cx = lexp.compile( c );
                if ( show_parsed ) {
                    console.log(JSON.stringify(cx, emap, 4));
                    console.log("Variable references:", lexp.get_vrefs( cx ));
                }
                const res = lexp.run( cx, ctx );
                console.log("Result:", typeof res, res);
            } catch ( err ) {
                console.error( err );
            }
        }

        process.stdout.write( "lexpjs> " );
    }
}

processLines();
