Skip to content

Commit

Permalink
feat(pointfree-lang): update CLI wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
postspectacular committed Dec 14, 2023
1 parent b1ed768 commit f261f42
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 88 deletions.
2 changes: 1 addition & 1 deletion packages/pointfree-lang/bin/pointfree
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ while [ -h "$SOURCE" ]; do
done
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"

/usr/bin/env node "$DIR/../cli.js" "$@"
/usr/bin/env node "$DIR/../cli.js" "$DIR" "$@"
1 change: 1 addition & 0 deletions packages/pointfree-lang/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"@thi.ng/args": "^2.2.46",
"@thi.ng/bench": "^3.4.14",
"@thi.ng/errors": "^2.4.6",
"@thi.ng/file-io": "^1.0.5",
"@thi.ng/logger": "^2.0.2",
"@thi.ng/pointfree": "^3.1.55"
},
Expand Down
186 changes: 99 additions & 87 deletions packages/pointfree-lang/src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,102 +1,114 @@
// thing:no-export
import type { FnU, IObjectOf } from "@thi.ng/api";
import { flag, parse, string, usage, type Args } from "@thi.ng/args";
import { cliApp, flag, string, type Command } from "@thi.ng/args";
import { timedResult } from "@thi.ng/bench";
import { ConsoleLogger, NULL_LOGGER } from "@thi.ng/logger";
import { readJSON, readText, writeFile } from "@thi.ng/file-io";
import { LogLevel } from "@thi.ng/logger";
import { ensureStack, type StackContext } from "@thi.ng/pointfree";
import { readFileSync, readdirSync, writeFileSync } from "fs";
import { readFileSync, readdirSync } from "fs";
import { resolve } from "path";
import { ffi, run, runU } from "./runtime.js";

interface CLIOpts {
debug: boolean;
exec?: string;
}

const showUsage = () => {
process.stderr.write(
usage(argOpts, { prefix: "Usage: pointfree [opts] [file]" })
);
process.exit(1);
};
const PKG = readJSON(resolve(process.argv[2], "../package.json"));

const argOpts: Args<CLIOpts> = {
debug: flag({ alias: "d", desc: "print debug info", group: "main" }),
exec: string({ alias: "e", desc: "execute given string" }),
const CMD: Command<CLIOpts, CLIOpts> = {
desc: "",
opts: {},
fn: async ({ logger, opts, inputs }) => {
let src = opts.exec;
if (!src) {
if (!inputs.length) {
process.stderr.write(`require --exec option or a source file`);
process.exit(1);
}
try {
src = readFileSync(inputs[0]).toString();
inputs.shift();
} catch (e) {
process.stderr.write(
`error reading source file ${(<Error>e).message}`
);
process.exit(1);
}
}
const includeCache = new Set();
const rootEnv = { args: inputs };
const builtins: IObjectOf<FnU<StackContext>> = {
include: (ctx) => {
const stack = ctx[0];
ensureStack(stack, 1);
const path = stack.pop();
if (!includeCache.has(path)) {
// cycle breaker
// TODO use dgraph
includeCache.add(path);
run(readText(path, logger), {
...ctx[2],
__vars: null,
});
} else {
logger.debug(`\t${path} already included, skipping...`);
}
return ctx;
},
"read-file": (ctx) => {
const stack = ctx[0];
ensureStack(stack, 1);
const path = stack.pop();
stack.push(readText(path, logger));
return ctx;
},
"write-file": (ctx) => {
const stack = ctx[0];
ensureStack(stack, 2);
const path = stack.pop();
writeFile(path, stack.pop(), undefined, logger);
return ctx;
},
"read-dir": (ctx) => {
const stack = ctx[0];
ensureStack(stack, 1);
const path = stack.pop();
logger.debug(`reading directory: ${path}`);
stack.push(readdirSync(path));
return ctx;
},
};
const env = ffi(rootEnv, builtins);
const [res, time] = timedResult(() => runU(src!, env));
logger.debug(`executed in ${time}ms`);
process.exit(typeof res === "number" ? res : 0);
},
};

const result = parse(argOpts, process.argv);
if (!result) process.exit(1);

const { result: opts, rest } = result!;
if (!(opts.exec || rest.length)) showUsage();

let src: string;
cliApp({
name: "pointfree",
start: 3,
opts: {
debug: flag({ alias: "d", desc: "print debug info", group: "main" }),
exec: string({ alias: "e", default: "", desc: "execute given string" }),
},
commands: { CMD },
single: true,
usage: {
prefix: `
█ █ █ │
██ █ │
█ █ █ █ █ █ █ █ │ ${PKG.name} v${PKG.version}
█ █ █ █ █ █ █ █ █ │ Forth-style DSL & CLI
█ │
█ █ │
if (!opts.exec) {
try {
src = readFileSync(rest[0]).toString();
rest.shift();
} catch (e) {
process.stderr.write(`error reading source file ${(<Error>e).message}`);
process.exit(1);
}
} else {
src = opts.exec;
}

try {
const logger = opts.debug ? new ConsoleLogger("pointfree") : NULL_LOGGER;
const includeCache = new Set();
const rootEnv = { args: rest };
const builtins: IObjectOf<FnU<StackContext>> = {
include: (ctx) => {
const stack = ctx[0];
ensureStack(stack, 1);
const path = stack.pop();
if (!includeCache.has(path)) {
// cycle breaker
// TODO use dgraph
includeCache.add(path);
logger.debug(`including: ${path}`);
run(readFileSync(path).toString(), {
...ctx[2],
__vars: null,
});
} else {
logger.debug(`\t${path} already included, skipping...`);
}
return ctx;
},
"read-file": (ctx) => {
const stack = ctx[0];
ensureStack(stack, 1);
const path = stack.pop();
logger.debug(`reading file: ${path}`);
stack.push(readFileSync(path).toString());
return ctx;
},
"write-file": (ctx) => {
const stack = ctx[0];
ensureStack(stack, 2);
const path = stack.pop();
logger.debug(`writing file: ${path}`);
writeFileSync(path, stack.pop());
return ctx;
},
"read-dir": (ctx) => {
const stack = ctx[0];
ensureStack(stack, 1);
const path = stack.pop();
logger.debug(`reading directory: ${path}`);
stack.push(readdirSync(path));
return ctx;
},
};
const env = ffi(rootEnv, builtins);
const [res, time] = timedResult(() => runU(src, env));
logger.debug(`executed in ${time}ms`);
process.exit(typeof res === "number" ? res : 0);
} catch (e) {
console.log(e);
}
process.exit(1);
Usage: pointfree [opts] [file]\n\n`,
paramWidth: 24,
},
ctx: async (ctx) => {
if (ctx.opts.debug) ctx.logger.level = LogLevel.DEBUG;
return ctx;
},
});
1 change: 1 addition & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5287,6 +5287,7 @@ __metadata:
"@thi.ng/args": ^2.2.46
"@thi.ng/bench": ^3.4.14
"@thi.ng/errors": ^2.4.6
"@thi.ng/file-io": ^1.0.5
"@thi.ng/logger": ^2.0.2
"@thi.ng/pointfree": ^3.1.55
esbuild: ^0.19.8
Expand Down

0 comments on commit f261f42

Please sign in to comment.