-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathassembler.ts
100 lines (86 loc) · 2.65 KB
/
assembler.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import Parser from './parser'
import Code from './code'
import Writer from './writer'
import SymbolTable from './symbol-table'
import { IParser } from './interface'
import Utils from './utils'
import Logger from './logger'
import constants from './constants'
export default class HackAssembler {
parser: Parser
code: Code
writer: Writer
symbol: SymbolTable
logger: Logger
constructor() {
const filepaths = process.argv.slice(2)
if (filepaths.length <= 0) {
throw new Error('need to requrie some asm path')
}
// 今は決めで1ファイルのみに対応するようにする
this.logger = new Logger(HackAssembler)
this.parser = new Parser(filepaths[0])
this.writer = new Writer(filepaths[0])
this.code = new Code()
this.symbol = new SymbolTable()
}
async setup() {
this.logger.setup('Start setup()')
// this.symbol.printCurrent()
await this.parser.readFile()
}
before() {
this.logger.before('Start before()')
const readLine: Function = this.parser.getReader()
this.symbol.createTableOnlyFunction(readLine)
}
after() {
this.logger.after(`Check output file: ${this.writer.filepath}`)
}
async exec() {
this.logger.exec('Start exec()')
this.before()
await this.writer.remove()
const readLine: Function = this.parser.getReader()
// 本当はここに書きたくない
let variableAddr = 16
while (true) {
const parsed: IParser = readLine()
if (!parsed) {
break
}
switch (parsed.command) {
case constants.COMMAND.A.type:
let addr = ''
const symbol = parsed.symbol
const move = isNaN(Number(symbol))
// @iとか@numとか
// @423423とかは無視する
this.logger.exec(`[switch] ${JSON.stringify(parsed)}`)
if (move) {
// 登録されていない場合は変数を登録する
if (!this.symbol.containes(symbol)) {
// 変数をSymbolTableに登録する
addr = this.symbol.addEntry(symbol, variableAddr)
variableAddr += 1
} else {
// 登録されている場合はSymbolTableからアドレスを取得する
addr = this.symbol.getAddress(symbol)
}
} else {
addr = Utils.getPaddedBinary(symbol)
}
await this.writer.write(addr)
break
case constants.COMMAND.C.type:
const encoded = this.code.compile(parsed)
await this.writer.write(encoded)
break
default:
break
}
}
this.symbol.printCurrent()
this.parser.clear()
}
}