diff --git a/.changeset/short-kids-decide.md b/.changeset/short-kids-decide.md new file mode 100644 index 0000000..c24cfce --- /dev/null +++ b/.changeset/short-kids-decide.md @@ -0,0 +1,5 @@ +--- +"@asmelabs/pushkin": minor +--- + +Add CLI to run .push files via pushkin command diff --git a/examples/hello.push b/examples/hello.push deleted file mode 100644 index 926638d..0000000 --- a/examples/hello.push +++ /dev/null @@ -1,3 +0,0 @@ -// your first Pushkin program -// logs "Hello, World!" to the console -print("Hello, World!"); \ No newline at end of file diff --git a/package.json b/package.json index 088063a..a4e9625 100644 --- a/package.json +++ b/package.json @@ -57,5 +57,8 @@ "biome check --write ." ] }, - "type": "module" + "type": "module", + "bin": { + "pushkin": "dist/cli.js" + } } diff --git a/src/cli.ts b/src/cli.ts new file mode 100644 index 0000000..9bf92f4 --- /dev/null +++ b/src/cli.ts @@ -0,0 +1,43 @@ +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; +import { Interpreter } from "./interpreter"; +import { Lexer } from "./lexer"; +import { Parser } from "./parser"; + +function main(): void { + const args = process.argv.slice(2); + + if (args.length === 0) { + console.error("Usage: pushkin "); + process.exit(1); + } + + const filePath = resolve(args[0] as string); + + if (!filePath.endsWith(".push")) { + console.error("Error: File must have a .push extension"); + process.exit(1); + } + + let source: string; + + try { + source = readFileSync(filePath, "utf-8"); + } catch { + console.error(`Error: Could not read file '${filePath}'`); + process.exit(1); + } + + try { + const tokens = new Lexer(source).tokenize(); + const ast = new Parser(tokens).parse(); + new Interpreter().run(ast); + } catch (error) { + if (error instanceof Error) { + console.error(`Error: ${error.message}`); + } + process.exit(1); + } +} + +main(); diff --git a/tsup.config.ts b/tsup.config.ts index e86ac85..0ed5984 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -1,9 +1,20 @@ import { defineConfig } from "tsup"; -export default defineConfig({ - entry: ["src/index.ts"], - format: ["esm", "cjs"], - dts: true, - clean: true, - target: "esnext", -}); +export default defineConfig([ + { + entry: ["src/index.ts"], + format: ["esm", "cjs"], + dts: true, + clean: true, + target: "esnext", + }, + { + entry: ["src/cli.ts"], + format: ["esm", "cjs"], + clean: false, + target: "esnext", + banner: { + js: "#!/usr/bin/env node", + }, + }, +]);