Skip to content

Commit

Permalink
VMTest passes projects 7 and 8 files
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidSouther committed Nov 12, 2023
1 parent a613dab commit 83593b9
Show file tree
Hide file tree
Showing 13 changed files with 296 additions and 119 deletions.
5 changes: 3 additions & 2 deletions simulator/src/languages/grammars/tst.ohm
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ Tst <: Base {
| TstLoadROMOperation

TstLoadROMOperation = ROM32K Load FileName
TstFileOperation = FileOperation FileName
TstFileOperation = FileOperation FileName?
TstOutputListOperation = "output-list" OutputFormat+
OutputFormat = Name Index? percent FormatStyle wholeDec dot wholeDec dot wholeDec
TstSetOperation = Set Name Index? Number
Index = OpenSquare wholeDec? CloseSquare
Condition = Value CompareOp Value
TstEvalOperation = Eval | Tick | Tock | TickTock
TstEvalOperation = Eval | Tick | Tock | TickTock | VmStep
TstOutputOperation = Output
TstEchoOperation = Echo String
TstClearEchoOperation = ClearEcho
Expand All @@ -36,6 +36,7 @@ Tst <: Base {
Tick = "tick"
Tock = "tock"
TickTock = "ticktock"
VmStep = "vmstep"
Echo = "echo"
Repeat = "repeat"
ClearEcho = "clear-echo"
Expand Down
5 changes: 3 additions & 2 deletions simulator/src/languages/grammars/tst.ohm.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ Tst <: Base {
| TstLoadROMOperation
TstLoadROMOperation = ROM32K Load FileName
TstFileOperation = FileOperation FileName
TstFileOperation = FileOperation FileName?
TstOutputListOperation = "output-list" OutputFormat+
OutputFormat = Name Index? percent FormatStyle wholeDec dot wholeDec dot wholeDec
TstSetOperation = Set Name Index? Number
Index = OpenSquare wholeDec? CloseSquare
Condition = Value CompareOp Value
TstEvalOperation = Eval | Tick | Tock | TickTock
TstEvalOperation = Eval | Tick | Tock | TickTock | VmStep
TstOutputOperation = Output
TstEchoOperation = Echo String
TstClearEchoOperation = ClearEcho
Expand All @@ -37,6 +37,7 @@ Tst <: Base {
Tick = "tick"
Tock = "tock"
TickTock = "ticktock"
VmStep = "vmstep"
Echo = "echo"
Repeat = "repeat"
ClearEcho = "clear-echo"
Expand Down
26 changes: 26 additions & 0 deletions simulator/src/languages/tst.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import {
FileSystem,
ObjectFileSystemAdapter,
} from "@davidsouther/jiffies/lib/esm/fs.js";
import { resetFiles } from "@nand2tetris/projects/index.js";
import { grammar, TST } from "./tst.js";

const NOT_TST = `
Expand Down Expand Up @@ -469,3 +474,24 @@ describe("tst language", () => {
});
});
});

it("loads all project tst files", async () => {
const fs = new FileSystem(new ObjectFileSystemAdapter());
await resetFiles(fs);
async function check() {
for (const stat of await fs.scandir(".")) {
if (stat.isDirectory()) {
fs.pushd(stat.name);
await check();
fs.popd();
} else {
if (stat.name.endsWith("vm_tst")) {
const tst = await fs.readFile(stat.name);
const match = grammar.match(tst);
expect(match).toHaveSucceeded();
}
}
}
}
await check();
});
6 changes: 3 additions & 3 deletions simulator/src/languages/tst.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export interface TstSetOperation {
}

export interface TstEvalOperation {
op: "eval" | "tick" | "tock";
op: "eval" | "tick" | "tock" | "ticktock" | "vmstep";
}

export interface TstOutputOperation {
Expand Down Expand Up @@ -49,7 +49,7 @@ export interface TstLoadROMOperation {

export interface TstFileOperation {
op: "load" | "output-file" | "compare-to";
file: string;
file?: string;
}

export type TstOperation =
Expand Down Expand Up @@ -183,7 +183,7 @@ tstSemantics.addAttribute<TstOperation>("operation", {
TstFileOperation(op, file) {
return {
op: op.sourceString as TstFileOperation["op"],
file: file.sourceString,
file: file?.sourceString,
};
},
});
Expand Down
7 changes: 7 additions & 0 deletions simulator/src/test/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
TestClearEchoInstruction,
TestCompoundInstruction,
TestEchoInstruction,
TestLoadInstruction,
TestLoadROMInstruction,
TestOutputInstruction,
TestOutputListInstruction,
Expand All @@ -24,6 +25,8 @@ import {
TestWhileInstruction,
} from "./instruction.js";
import { Test } from "./tst.js";
import { TestVMStepInstruction } from "./vmtst.js";
import { TestTickTockInstruction } from "./cputst.js";

function isTstLineStatment(line: TstStatement): line is TstLineStatement {
return (line as TstLineStatement).ops !== undefined;
Expand All @@ -50,8 +53,12 @@ function makeInstruction(inst: TstOperation) {
return new TestTickInstruction();
case "tock":
return new TestTockInstruction();
case "ticktock":
return new TestTickTockInstruction();
case "eval":
return new TestEvalInstruction();
case "vmstep":
return new TestVMStepInstruction();
case "output":
return new TestOutputInstruction();
case "set":
Expand Down
12 changes: 12 additions & 0 deletions simulator/src/test/instruction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,18 @@ export class TestLoadROMInstruction implements TestInstruction {
}
}

export class TestLoadInstruction implements TestInstruction {
constructor(readonly file?: string) {}

async do(test: Test) {
await test.load(this.file);
}

*steps() {
yield this;
}
}

export class TestBreakpointInstruction implements TestInstruction {
constructor(readonly variable: string, readonly value: number) {}

Expand Down
3 changes: 1 addition & 2 deletions simulator/src/test/tst.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export abstract class Test<IS extends TestInstruction = TestInstruction> {
return undefined;
}

async load(_filename: string): Promise<void> {
async load(_filename?: string): Promise<void> {
return undefined;
}
async compareTo(_filename: string): Promise<void> {
Expand All @@ -45,7 +45,6 @@ export abstract class Test<IS extends TestInstruction = TestInstruction> {
}
})(this);
this._step = this._steps.next();
this._step; //?
this._log = "";
return this;
}
Expand Down
37 changes: 37 additions & 0 deletions simulator/src/test/vmtst.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { VM_PROJECTS, resetFiles } from "@nand2tetris/projects/index.js";
import {
FileSystem,
ObjectFileSystemAdapter,
} from "@davidsouther/jiffies/lib/esm/fs.js";
import { TST } from "../languages/tst.js";
import { unwrap } from "@davidsouther/jiffies/lib/esm/result.js";
import { VMTest } from "./vmtst.js";

async function prepare(project: "07" | "08", name: string): Promise<VMTest> {
const fs = new FileSystem(new ObjectFileSystemAdapter({}));
await resetFiles(fs);
fs.cd(`/projects/${project}/${name}`);
const vm_tst = await fs.readFile(name + ".vm_tst");
const tst = unwrap(TST.parse(vm_tst));
const test = VMTest.from(tst).using(fs);
await test.load();
return test;
}

describe("VM Test Runner", () => {
test.each(VM_PROJECTS["07"])("07 VM Test Runner %s", async (name) => {
const test = await prepare("07", name);

for (let i = 0; i < 100; i++) {
await test.step();
}
});

test.each(VM_PROJECTS["08"])("08 VM Test Runner %s", async (name) => {
const test = await prepare("08", name);

for (let i = 0; i < 100; i++) {
test.step();
}
});
});
68 changes: 65 additions & 3 deletions simulator/src/test/vmtst.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
import { FileSystem } from "@davidsouther/jiffies/lib/esm/fs.js";
import { unwrap } from "@davidsouther/jiffies/lib/esm/result.js";
import { RAM } from "../cpu/memory.js";
import { Vm } from "../vm/vm.js";
import { Tst } from "../languages/tst.js";
import { VM } from "../languages/vm.js";
import { Segment, Vm } from "../vm/vm.js";
import { fill } from "./builder.js";
import { TestInstruction } from "./instruction.js";
import { Test } from "./tst.js";

export class VMTest extends Test<VMTestInstruction> {
vm: Vm = new Vm();

static from(tst: Tst): VMTest {
const test = new VMTest();
return fill(test, tst);
}

using(fs: FileSystem): this {
this.fs = fs;
return this;
}

with(vm: Vm) {
this.vm = vm;
return this;
Expand All @@ -24,7 +39,16 @@ export class VMTest extends Test<VMTestInstruction> {
) {
return true;
}
return false;
return [
"argument",
"local",
"static",
"constant",
"this",
"that",
"pointer",
"temp",
].includes(variable.toLowerCase());
}

getVar(variable: string | number, index?: number): number {
Expand All @@ -40,7 +64,7 @@ export class VMTest extends Test<VMTestInstruction> {
) {
return this.vm.RAM.get(index);
}
return 0;
return this.vm.memory.getSegment(variable as Segment, index ?? 0);
}

setVar(variable: string, value: number, index?: number): void {
Expand All @@ -56,11 +80,49 @@ export class VMTest extends Test<VMTestInstruction> {
) {
this.vm.RAM.set(index, value);
}
if (index) {
this.vm.memory.setSegment(variable as Segment, index, value);
} else {
switch (variable.toLowerCase()) {
case "sp":
this.vm.memory.SP = value;
break;
case "arg":
case "argument":
this.vm.memory.ARG = value;
break;
case "lcl":
case "local":
this.vm.memory.LCL = value;
break;
case "this":
this.vm.memory.THIS = value;
break;
case "that":
this.vm.memory.THAT = value;
break;
}
}
}

vmstep(): void {
this.vm.step();
}

override async load(filename?: string) {
if (filename) {
const file = await this.fs.readFile(filename);
const { instructions } = unwrap(VM.parse(file));
unwrap(this.vm.load(instructions));
} else {
for (const file of await this.fs.scandir(".")) {
if (file.isFile() && file.name.endsWith(".vm")) {
await this.load(file.name);
}
}
}
unwrap(this.vm.bootstrap());
}
}

export interface VMTestInstruction extends TestInstruction {
Expand Down
Loading

0 comments on commit 83593b9

Please sign in to comment.