aboutsummaryrefslogtreecommitdiffgithub
diff options
context:
space:
mode:
authorAustin Adams <git@austinjadams.com>2019-01-18 16:51:30 -0500
committerAustin Adams <git@austinjadams.com>2019-01-18 16:51:30 -0500
commita8a18e12910e00f956813720c990112a0292000b (patch)
tree88c889cf92c762e9d9730d8d896ae5dedc22f1b8
parent20d5321a99ca84eb968531aeb2ed83e5e56a3435 (diff)
downloadnovice-a8a18e12910e00f956813720c990112a0292000b.tar.gz
novice-a8a18e12910e00f956813720c990112a0292000b.tar.xz
Yank Assembly IR interfaces out of parserland and into isaland
-rw-r--r--novice/assembler/assembler.ts8
-rw-r--r--novice/assembler/codegen/base.ts12
-rw-r--r--novice/assembler/codegen/codegen.ts5
-rw-r--r--novice/assembler/parsers/complx.ts12
-rw-r--r--novice/assembler/parsers/index.ts4
-rw-r--r--novice/assembler/parsers/lc2200.ts12
-rw-r--r--novice/assembler/parsers/parser.test.ts3
-rw-r--r--novice/assembler/parsers/parser.ts59
-rw-r--r--novice/isa/assembly.ts47
-rw-r--r--novice/isa/index.ts18
-rw-r--r--novice/isa/isa.ts6
-rw-r--r--novice/simulator/simulator.ts6
12 files changed, 101 insertions, 91 deletions
diff --git a/novice/assembler/assembler.ts b/novice/assembler/assembler.ts
index ce465cd..0ce1bfa 100644
--- a/novice/assembler/assembler.ts
+++ b/novice/assembler/assembler.ts
@@ -1,8 +1,8 @@
import { Readable, Writable } from 'stream';
-import { Isa } from '../isa';
+import { Assembly, Isa } from '../isa';
import { MachineCodeGenerator, MachineCodeSection } from './codegen';
import { PseudoOpSpec } from './opspec';
-import { ParsedAssembly, Parser } from './parsers';
+import { Parser } from './parsers';
import { Serializer } from './serializers';
interface AssemblerConfig {
@@ -20,11 +20,11 @@ class Assembler {
this.cfg = cfg;
}
- public async parse(fp: Readable): Promise<ParsedAssembly> {
+ public async parse(fp: Readable): Promise<Assembly> {
return await this.cfg.parser.parse(fp);
}
- public codegen(asm: ParsedAssembly): MachineCodeSection[] {
+ public codegen(asm: Assembly): MachineCodeSection[] {
return this.cfg.generator.gen(this.cfg.isa, this.cfg.opSpec, asm);
}
diff --git a/novice/assembler/codegen/base.ts b/novice/assembler/codegen/base.ts
index 1a6625b..74ac800 100644
--- a/novice/assembler/codegen/base.ts
+++ b/novice/assembler/codegen/base.ts
@@ -1,6 +1,6 @@
-import { Instruction as IsaInstruction, Isa } from '../../isa';
+import { Assembly, Instruction, InstructionSpec, Isa, PseudoOp,
+ Section } from '../../isa';
import { AsmContext, OpOperands, OpSpec, PseudoOpSpec } from '../opspec';
-import { Instruction, ParsedAssembly, PseudoOp, Section } from '../parsers';
import { MachineCodeGenerator, MachineCodeSection } from './codegen';
interface ReassembleVictim {
@@ -13,7 +13,7 @@ interface ReassembleVictim {
type SymbTable = {[s: string]: number};
class BaseMachineCodeGenerator implements MachineCodeGenerator {
- public gen(isa: Isa, opSpec: PseudoOpSpec, asm: ParsedAssembly):
+ public gen(isa: Isa, opSpec: PseudoOpSpec, asm: Assembly):
MachineCodeSection[] {
const sections: MachineCodeSection[] = [];
const symbtable: SymbTable = {};
@@ -114,7 +114,7 @@ class BaseMachineCodeGenerator implements MachineCodeGenerator {
return [match.asm(ctx, operands), false];
}
} else {
- let match: IsaInstruction|null = null;
+ let match: InstructionSpec|null = null;
// TODO: Figure out a more efficient way than this. just a
// hashmap right?
@@ -168,7 +168,7 @@ class BaseMachineCodeGenerator implements MachineCodeGenerator {
return operands;
}
- private genInstrBin(instr: Instruction, isaInstr: IsaInstruction,
+ private genInstrBin(instr: Instruction, isaInstr: InstructionSpec,
pc: number, symbtable: SymbTable, isa: Isa): number {
let bin = 0;
let o = 0;
@@ -286,7 +286,7 @@ class BaseMachineCodeGenerator implements MachineCodeGenerator {
pseudoOp.operand.kind === opSpec.operands[0].kind);
}
- private instrMatch(instr: Instruction, isaInstr: IsaInstruction): boolean {
+ private instrMatch(instr: Instruction, isaInstr: InstructionSpec): boolean {
if (instr.op !== isaInstr.op) {
return false;
}
diff --git a/novice/assembler/codegen/codegen.ts b/novice/assembler/codegen/codegen.ts
index 92f711f..9c0cef0 100644
--- a/novice/assembler/codegen/codegen.ts
+++ b/novice/assembler/codegen/codegen.ts
@@ -1,6 +1,5 @@
-import { Isa } from '../../isa';
+import { Assembly, Isa } from '../../isa';
import { PseudoOpSpec } from '../opspec';
-import { ParsedAssembly } from '../parsers';
interface MachineCodeSection {
startAddr: number;
@@ -8,7 +7,7 @@ interface MachineCodeSection {
}
interface MachineCodeGenerator {
- gen(isa: Isa, opSpec: PseudoOpSpec, asm: ParsedAssembly): MachineCodeSection[];
+ gen(isa: Isa, opSpec: PseudoOpSpec, asm: Assembly): MachineCodeSection[];
}
export { MachineCodeSection, MachineCodeGenerator };
diff --git a/novice/assembler/parsers/complx.ts b/novice/assembler/parsers/complx.ts
index 7023772..8322a42 100644
--- a/novice/assembler/parsers/complx.ts
+++ b/novice/assembler/parsers/complx.ts
@@ -1,17 +1,17 @@
// Parser for complx syntax
-import { Isa } from '../../isa';
+import { Assembly, Instruction, IntegerOperand, Isa,
+ LabelOperand, PseudoOp, RegisterOperand, Section,
+ StringOperand } from '../../isa';
import { ParseTable, ParseTree } from '../lr1';
import { Grammar } from './grammar';
import { grammar, NT, T } from './grammars/complx';
-import { AbstractParser, Instruction, IntegerOperand, LabelOperand, Line,
- ParsedAssembly, Parser, PseudoOp, RegisterOperand,
- Section, StringOperand } from './parser';
+import { AbstractParser, Line, Parser } from './parser';
import table from './tables/complx';
interface ParseContext {
currentSection: Section|null;
labels: string[];
- assembly: ParsedAssembly;
+ assembly: Assembly;
}
class ComplxParser extends AbstractParser<ParseContext, NT, T> {
@@ -139,7 +139,7 @@ class ComplxParser extends AbstractParser<ParseContext, NT, T> {
}
}
- protected finish(ctx: ParseContext) {
+ protected finish(ctx: ParseContext): Assembly {
if (ctx.currentSection) {
throw new Error('missing an .end at the end of file');
}
diff --git a/novice/assembler/parsers/index.ts b/novice/assembler/parsers/index.ts
index be317fb..6ec6174 100644
--- a/novice/assembler/parsers/index.ts
+++ b/novice/assembler/parsers/index.ts
@@ -1,11 +1,11 @@
import { Isa } from '../../isa';
import ComplxParser from './complx';
import Lc2200Parser from './lc2200';
-import { Instruction, ParsedAssembly, Parser, PseudoOp, Section } from './parser';
+import { Parser } from './parser';
const parsers: {[s: string]: new(isa: Isa) => Parser} = {
complx: ComplxParser,
lc2200: Lc2200Parser,
};
-export { ParsedAssembly, Section, Parser, parsers, Instruction, PseudoOp };
+export { Parser, parsers };
diff --git a/novice/assembler/parsers/lc2200.ts b/novice/assembler/parsers/lc2200.ts
index b416bda..c72c776 100644
--- a/novice/assembler/parsers/lc2200.ts
+++ b/novice/assembler/parsers/lc2200.ts
@@ -1,11 +1,10 @@
// Parser for LC-2200 syntax
-import { getAliases, Isa } from '../../isa';
+import { Assembly, getAliases, Instruction, IntegerOperand, Isa, LabelOperand,
+ PseudoOp, RegisterOperand, Section } from '../../isa';
import { ParseTable, ParseTree } from '../lr1';
import { Grammar } from './grammar';
import { grammar, NT, T } from './grammars/lc2200';
-import { AbstractParser, Instruction, IntegerOperand, LabelOperand, Line,
- ParsedAssembly, Parser, PseudoOp, RegisterOperand,
- Section } from './parser';
+import { AbstractParser, Line, Parser } from './parser';
import table from './tables/lc2200';
interface ParseContext {
@@ -73,13 +72,14 @@ class Lc2200Parser extends AbstractParser<ParseContext, NT, T> {
}
}
- protected finish(ctx: ParseContext): ParsedAssembly {
+ protected finish(ctx: ParseContext): Assembly {
if (ctx.labelQueue.length > 0) {
// TODO: line numbers
throw new Error(`stray label ${ctx.labelQueue[0]} at end of file`);
}
- const asm: ParsedAssembly = {sections: [{startAddr: 0, instructions: ctx.instrs}], labels: {}};
+ const asm: Assembly = {sections: [{startAddr: 0, instructions: ctx.instrs}],
+ labels: {}};
Object.keys(ctx.labels).forEach(
label => { asm.labels[label] = [0, ctx.labels[label]]; });
return asm;
diff --git a/novice/assembler/parsers/parser.test.ts b/novice/assembler/parsers/parser.test.ts
index a49f52b..ad957bc 100644
--- a/novice/assembler/parsers/parser.test.ts
+++ b/novice/assembler/parsers/parser.test.ts
@@ -1,3 +1,4 @@
+import { Assembly } from '../../isa';
import { AbstractParser, Parser } from './parser';
import { Grammar } from './grammar';
import { ParseTable, ParseTree } from '../lr1';
@@ -31,7 +32,7 @@ describe('abstract parser', () => {
protected initCtx(): Context { return {}; }
protected parseLine(ctx: Context, parseTree: ParseTree<NT, T>, line: Line<T>): void {}
// @ts-ignore
- protected finish(ctx: Context): ParsedAssembly { return null; }
+ protected finish(ctx: Context): Assembly { return null; }
}
beforeEach(() => {
diff --git a/novice/assembler/parsers/parser.ts b/novice/assembler/parsers/parser.ts
index a1c3637..95ba7a6 100644
--- a/novice/assembler/parsers/parser.ts
+++ b/novice/assembler/parsers/parser.ts
@@ -1,57 +1,12 @@
import { Readable } from 'stream';
-import { Isa } from '../../isa';
+import { Assembly, Isa } from '../../isa';
import { Parser as LR1Parser, ParseTable, ParseTree,
TableGenerator } from '../lr1';
import { Line, Scanner, Token } from '../scanner';
import { Grammar } from './grammar';
-interface RegisterOperand {
- kind: 'reg';
- prefix: string;
- num: number;
-}
-
-interface IntegerOperand {
- kind: 'int';
- val: number;
-}
-
-interface LabelOperand {
- kind: 'label';
- label: string;
-}
-
-interface StringOperand {
- kind: 'string';
- contents: string;
-}
-
-interface Instruction {
- kind: 'instr';
- line: number;
- op: string;
- operands: (RegisterOperand|IntegerOperand|LabelOperand)[];
-}
-
-interface PseudoOp {
- kind: 'pseudoop';
- line: number;
- op: string;
- operand: StringOperand|IntegerOperand|LabelOperand|undefined;
-}
-
-interface Section {
- startAddr: number;
- instructions: (Instruction|PseudoOp)[];
-}
-
-interface ParsedAssembly {
- sections: Section[];
- labels: {[s: string]: [number, number]};
-}
-
interface Parser {
- parse(fp: Readable): Promise<ParsedAssembly>;
+ parse(fp: Readable): Promise<Assembly>;
// Pass back an object because higher levels of abstraction don't
// care about what exactly is in here, it's just a blob of JSON
genTable(): object;
@@ -69,7 +24,7 @@ abstract class AbstractParser<Ctx, NT, T> implements Parser {
this.parser = new LR1Parser<NT, T>(this.getTable());
}
- public async parse(fp: Readable): Promise<ParsedAssembly> {
+ public async parse(fp: Readable): Promise<Assembly> {
return this.parseLines(await this.scanner.scan(fp));
}
@@ -80,7 +35,7 @@ abstract class AbstractParser<Ctx, NT, T> implements Parser {
return tablegen.genTable();
}
- protected parseLines(lines: Line<T>[]): ParsedAssembly {
+ protected parseLines(lines: Line<T>[]): Assembly {
const ctx = this.initCtx();
for (const line of lines) {
@@ -96,9 +51,7 @@ abstract class AbstractParser<Ctx, NT, T> implements Parser {
protected abstract initCtx(): Ctx;
protected abstract parseLine(ctx: Ctx, parseTree: ParseTree<NT, T>,
line: Line<T>): void;
- protected abstract finish(ctx: Ctx): ParsedAssembly;
+ protected abstract finish(ctx: Ctx): Assembly;
}
-export { Parser, AbstractParser, ParsedAssembly, Section, Instruction,
- RegisterOperand, IntegerOperand, LabelOperand, PseudoOp,
- StringOperand, Line };
+export { Parser, AbstractParser, Line };
diff --git a/novice/isa/assembly.ts b/novice/isa/assembly.ts
new file mode 100644
index 0000000..925ff72
--- /dev/null
+++ b/novice/isa/assembly.ts
@@ -0,0 +1,47 @@
+interface RegisterOperand {
+ kind: 'reg';
+ prefix: string;
+ num: number;
+}
+
+interface IntegerOperand {
+ kind: 'int';
+ val: number;
+}
+
+interface LabelOperand {
+ kind: 'label';
+ label: string;
+}
+
+interface StringOperand {
+ kind: 'string';
+ contents: string;
+}
+
+interface Instruction {
+ kind: 'instr';
+ line: number;
+ op: string;
+ operands: (RegisterOperand|IntegerOperand|LabelOperand)[];
+}
+
+interface PseudoOp {
+ kind: 'pseudoop';
+ line: number;
+ op: string;
+ operand: StringOperand|IntegerOperand|LabelOperand|undefined;
+}
+
+interface Section {
+ startAddr: number;
+ instructions: (Instruction|PseudoOp)[];
+}
+
+interface Assembly {
+ sections: Section[];
+ labels: {[s: string]: [number, number]};
+}
+
+export { Assembly, Section, Instruction, RegisterOperand, IntegerOperand,
+ LabelOperand, PseudoOp, StringOperand };
diff --git a/novice/isa/index.ts b/novice/isa/index.ts
index a59380f..5113f9e 100644
--- a/novice/isa/index.ts
+++ b/novice/isa/index.ts
@@ -1,6 +1,9 @@
+import { Assembly, Instruction, IntegerOperand, LabelOperand, PseudoOp,
+ RegisterOperand, Section, StringOperand } from './assembly';
import { DummyIsa } from './dummy';
import { IO, StreamIO } from './io';
-import { Fields, getAliases, Instruction, Isa, Reg, regPrefixes } from './isa';
+import { Fields, getAliases, InstructionSpec, Isa, Reg,
+ regPrefixes } from './isa';
import { Lc2200Isa } from './lc2200';
import { Lc3Isa } from './lc3';
import { MachineState, MachineStateUpdate, RegIdentifier } from './state';
@@ -19,6 +22,13 @@ function getIsa(isaName: string): Isa {
return isas[isaName];
}
-export { Isa, Instruction, isas, Lc3Isa, MachineState, MachineStateUpdate,
- RegIdentifier, Fields, Reg, getIsa, IO, StreamIO, regPrefixes,
- getAliases };
+export { getIsa, isas,
+ // assembly
+ Assembly, Section, Instruction, RegisterOperand, IntegerOperand,
+ LabelOperand, PseudoOp, StringOperand,
+ // io
+ IO, StreamIO,
+ // isa
+ Isa, InstructionSpec, Fields, Reg, regPrefixes, getAliases,
+ // state
+ RegIdentifier, MachineState, MachineStateUpdate };
diff --git a/novice/isa/isa.ts b/novice/isa/isa.ts
index f15caf0..7cad869 100644
--- a/novice/isa/isa.ts
+++ b/novice/isa/isa.ts
@@ -60,7 +60,7 @@ interface Fields {
imms: {[s: string]: number};
}
-interface Instruction {
+interface InstructionSpec {
op: string;
fields: Field[];
sim: (state: MachineState, io: IO, ir: Fields) => MachineStateUpdate[];
@@ -70,7 +70,7 @@ interface Isa {
pc: Pc;
mem: Mem;
regs: Reg[];
- instructions: Instruction[];
+ instructions: InstructionSpec[];
}
function regPrefixes(isa: Isa): string[] {
@@ -93,4 +93,4 @@ function getAliases(isa: Isa, prefix: string): {[s: string]: number} {
throw new Error(`no such register prefix ${prefix}`);
}
-export { Isa, Fields, Instruction, Reg, regPrefixes, getAliases };
+export { Isa, Fields, InstructionSpec, Reg, regPrefixes, getAliases };
diff --git a/novice/simulator/simulator.ts b/novice/simulator/simulator.ts
index 4614c81..de3fd08 100644
--- a/novice/simulator/simulator.ts
+++ b/novice/simulator/simulator.ts
@@ -1,4 +1,4 @@
-import { Fields, Instruction, IO, Isa, Reg, RegIdentifier } from '../isa';
+import { Fields, InstructionSpec, IO, Isa, Reg, RegIdentifier } from '../isa';
class Simulator {
public pc: number;
@@ -113,7 +113,7 @@ class Simulator {
throw new Error(`unknown register identifier ${id}`);
}
- private decode(ir: number): [Instruction, Fields] {
+ private decode(ir: number): [InstructionSpec, Fields] {
// TODO: ridiculously inefficient. idea for improvement: binary
// tree of depth like 8 to cut down on iteration time
const matches = [];
@@ -150,7 +150,7 @@ class Simulator {
return [instruction, this.genFields(ir, instruction)];
}
- private genFields(ir: number, instr: Instruction): Fields {
+ private genFields(ir: number, instr: InstructionSpec): Fields {
const fields: Fields = {regs: {}, imms: {}};
for (const field of instr.fields) {