From 4edc5283860d965f33d5d2520bafa94e5cd3d833 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Mon, 16 Sep 2024 15:40:28 +0200 Subject: [PATCH 1/5] Add compile jack comand to cli --- cli/src/index.ts | 104 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 97 insertions(+), 7 deletions(-) diff --git a/cli/src/index.ts b/cli/src/index.ts index 2092800ad..868d860e0 100644 --- a/cli/src/index.ts +++ b/cli/src/index.ts @@ -1,18 +1,22 @@ #!/usr/bin/env node -import { dirname, parse, resolve } from "path"; -import yargs from "yargs"; +import path, { dirname, parse, resolve } from "path"; +import yargs, { boolean } from "yargs"; import { hideBin } from "yargs/helpers"; import { main } from "./grading.js"; import { testRunner } from "./testrunner.js"; +import { NodeFileSystemAdapter } from "@davidsouther/jiffies/lib/esm/fs_node.js"; +import { FileSystem } from "@davidsouther/jiffies/lib/esm/fs.js"; +import * as fsCore from "fs"; +import { compile } from "@nand2tetris/simulator/jack/compiler.js"; yargs(hideBin(process.argv)) .usage("$0 ") .command( - "grade [directory]", - "Grade all NAND2Tetris projects in a directory tree.", + "grade [srcectory]", + "Grade all NAND2Tetris projects in a srcectory tree.", (yargs) => yargs - .positional("directory", { + .positional("srcectory", { type: "string", default: process.cwd(), describe: "Path to a folder to grade for nand2tetris projects.", @@ -24,8 +28,8 @@ yargs(hideBin(process.argv)) "When set, look for the java IDE jars in this path and compare both runs.", }), async (argv) => { - console.log("grade", argv.directory, "nand2tetris grader!"); - const exitCodePromise = main(argv.directory, argv.java_ide); + console.log("grade", argv.srcectory, "nand2tetris grader!"); + const exitCodePromise = main(argv.srcectory, argv.java_ide); const exitCode = await exitCodePromise; if (exitCode) { process.exit(exitCode); @@ -74,6 +78,92 @@ yargs(hideBin(process.argv)) } }, ) + .command( + "compile [dst]", + "Compile .jack files inside a folder", + (yargs) => + yargs + .positional("src", { + type: "string", + describe: "Path to input folder with jack files", + }) + .option("dst", { + type: "string", + describe: "Path to destination folder", + default: "" + }) + .coerce(['src', 'dst'], function (arg) { + return path.resolve(arg) + "/"; + }) + .check((argv, options) => { + const src = argv.src + const dst = argv.dst + if (src === undefined) { + throw Error("Please provide input folder path"); + } + + if (dst && !fsCore.lstatSync(dst).isDirectory()) { + throw Error(src + " is not a folder"); + } + if (!fsCore.lstatSync(src).isDirectory()) { + throw Error(src + " is not a folder"); + } + + return true + }). + showHelpOnFail(false, 'Specify --help for available options'), + async (argv) => { + enum Colors { + Red = "\x1b[31m", + Green = "\x1b[32m", + Reset = "\u001b[0m" + } + const JACK_EXT = '.jack'; + const src = argv.src + const dst = argv.dst ?? src + if (src === undefined) { + throw Error("Please provde input folder path"); + } + + if (dst === undefined) { + throw Error("Please provde input folder path"); + } + const fs = new FileSystem(new NodeFileSystemAdapter()); + + + const files = await fs.readdir(src); + const jackFiles = files.filter(file => file.endsWith(JACK_EXT)); + if (jackFiles.length === 0) { + throw Error("No jack files inside a folder"); + } + const nameToContent = {} as Record; + for (const file of jackFiles) { + const filepath = path.join(src, file) + const content = await fs.readFile(filepath); + nameToContent[file.replace(JACK_EXT, "")] = content; + } + let error = false; + for (const [name, compiled] of Object.entries(compile(nameToContent))) { + if (typeof compiled === "string") { + const outputFilename = name + '.vm' + const outpath = path.join(dst, outputFilename); + await fs.writeFile(outpath, compiled); + + } else { + if (!error) { + console.error("Compilation failed\n"); + } + console.error(Colors.Red +compiled.message.replace(/Line\s([\d]+):/g, name + ".jack:$1"+Colors.Reset)); + error = true; + } + } + if (error) { + process.exit(1); + } else { + console.log(Colors.Green + "Compiled files"); + } + }, + ) .help() .demandCommand(1) .parse(); From 837e9f774fd3ca02154908bb9520ffe2a43d7424 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Mon, 16 Sep 2024 15:41:21 +0200 Subject: [PATCH 2/5] WIP --- cli/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/src/index.ts b/cli/src/index.ts index 868d860e0..437dd8140 100644 --- a/cli/src/index.ts +++ b/cli/src/index.ts @@ -153,7 +153,7 @@ yargs(hideBin(process.argv)) if (!error) { console.error("Compilation failed\n"); } - console.error(Colors.Red +compiled.message.replace(/Line\s([\d]+):/g, name + ".jack:$1"+Colors.Reset)); + console.error(Colors.Red + compiled.message.replace(/Line\s([\d]+):/g, name + ".jack:$1" + Colors.Reset)); error = true; } } From c10afcef75e2be92b95ee4435b94f4d2e2704534 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Mon, 16 Sep 2024 15:49:46 +0200 Subject: [PATCH 3/5] WIP --- cli/src/index.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cli/src/index.ts b/cli/src/index.ts index 437dd8140..59bd76668 100644 --- a/cli/src/index.ts +++ b/cli/src/index.ts @@ -12,11 +12,11 @@ import { compile } from "@nand2tetris/simulator/jack/compiler.js"; yargs(hideBin(process.argv)) .usage("$0 ") .command( - "grade [srcectory]", - "Grade all NAND2Tetris projects in a srcectory tree.", + "grade [directory]", + "Grade all NAND2Tetris projects in a directory tree.", (yargs) => yargs - .positional("srcectory", { + .positional("directory", { type: "string", default: process.cwd(), describe: "Path to a folder to grade for nand2tetris projects.", @@ -28,8 +28,8 @@ yargs(hideBin(process.argv)) "When set, look for the java IDE jars in this path and compare both runs.", }), async (argv) => { - console.log("grade", argv.srcectory, "nand2tetris grader!"); - const exitCodePromise = main(argv.srcectory, argv.java_ide); + console.log("grade", argv.directory, "nand2tetris grader!"); + const exitCodePromise = main(argv.directory, argv.java_ide); const exitCode = await exitCodePromise; if (exitCode) { process.exit(exitCode); From 6436d4095dd6f28ca121d3ea2a64cda71e1ddfea Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Mon, 16 Sep 2024 15:53:46 +0200 Subject: [PATCH 4/5] WIP --- cli/src/index.ts | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/cli/src/index.ts b/cli/src/index.ts index 59bd76668..01433fc95 100644 --- a/cli/src/index.ts +++ b/cli/src/index.ts @@ -1,6 +1,6 @@ #!/usr/bin/env node import path, { dirname, parse, resolve } from "path"; -import yargs, { boolean } from "yargs"; +import yargs from "yargs"; import { hideBin } from "yargs/helpers"; import { main } from "./grading.js"; import { testRunner } from "./testrunner.js"; @@ -90,14 +90,14 @@ yargs(hideBin(process.argv)) .option("dst", { type: "string", describe: "Path to destination folder", - default: "" + default: "", }) - .coerce(['src', 'dst'], function (arg) { + .coerce(["src", "dst"], function (arg) { return path.resolve(arg) + "/"; }) .check((argv, options) => { - const src = argv.src - const dst = argv.dst + const src = argv.src; + const dst = argv.dst; if (src === undefined) { throw Error("Please provide input folder path"); } @@ -109,18 +109,18 @@ yargs(hideBin(process.argv)) throw Error(src + " is not a folder"); } - return true - }). - showHelpOnFail(false, 'Specify --help for available options'), + return true; + }) + .showHelpOnFail(false, "Specify --help for available options"), async (argv) => { enum Colors { Red = "\x1b[31m", Green = "\x1b[32m", - Reset = "\u001b[0m" + Reset = "\u001b[0m", } - const JACK_EXT = '.jack'; - const src = argv.src - const dst = argv.dst ?? src + const JACK_EXT = ".jack"; + const src = argv.src; + const dst = argv.dst ?? src; if (src === undefined) { throw Error("Please provde input folder path"); } @@ -130,30 +130,34 @@ yargs(hideBin(process.argv)) } const fs = new FileSystem(new NodeFileSystemAdapter()); - const files = await fs.readdir(src); - const jackFiles = files.filter(file => file.endsWith(JACK_EXT)); + const jackFiles = files.filter((file) => file.endsWith(JACK_EXT)); if (jackFiles.length === 0) { throw Error("No jack files inside a folder"); } const nameToContent = {} as Record; for (const file of jackFiles) { - const filepath = path.join(src, file) + const filepath = path.join(src, file); const content = await fs.readFile(filepath); nameToContent[file.replace(JACK_EXT, "")] = content; } let error = false; for (const [name, compiled] of Object.entries(compile(nameToContent))) { if (typeof compiled === "string") { - const outputFilename = name + '.vm' + const outputFilename = name + ".vm"; const outpath = path.join(dst, outputFilename); await fs.writeFile(outpath, compiled); - } else { if (!error) { console.error("Compilation failed\n"); } - console.error(Colors.Red + compiled.message.replace(/Line\s([\d]+):/g, name + ".jack:$1" + Colors.Reset)); + console.error( + Colors.Red + + compiled.message.replace( + /Line\s([\d]+):/g, + name + ".jack:$1" + Colors.Reset, + ), + ); error = true; } } From 6e87b66c2820a55317b0ae1f0c96bad722b02cb5 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Mon, 16 Sep 2024 17:00:54 +0200 Subject: [PATCH 5/5] WIP --- cli/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/src/index.ts b/cli/src/index.ts index 01433fc95..a541b2b27 100644 --- a/cli/src/index.ts +++ b/cli/src/index.ts @@ -164,7 +164,7 @@ yargs(hideBin(process.argv)) if (error) { process.exit(1); } else { - console.log(Colors.Green + "Compiled files"); + console.log(Colors.Green + "Compiled files" + Colors.Reset); } }, )