-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcompiler.py
70 lines (55 loc) · 1.91 KB
/
compiler.py
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
from typing import Tuple, List
import calculate
import mem_access
import branching
import function
pointers_base = ((256, 'SP'), (300, 'LCL'), (400, 'ARG'), (3000, 'THIS'), (3010, 'THAT'))
call_sys_init, _ = function.write_call('Sys.init', '0', {'function': 'Boot.0', 'call_count': 0})
bootstrap_dir = tuple(
(f"@{address}" "\n"
"D=A" "\n"
f"@{pointer}" "\n"
"M=D" "\n") for address, pointer in pointers_base
) + call_sys_init
# Commands that do not depend on or modify the state
stateless = {
'//': lambda: (), # comments do nothing...
'add': calculate.write_add,
'sub': calculate.write_sub,
'and': calculate.write_and,
'or' : calculate.write_or,
'not': calculate.write_not,
'neg': calculate.write_neg,
}
# Commands that depend on and/or modify the state
stateful = {
'push': mem_access.write_push,
'pop' : mem_access.write_pop,
'eq' : calculate.write_eq,
'gt' : calculate.write_gt,
'lt' : calculate.write_lt,
'function': function.write_function,
'call' : function.write_call,
'return' : function.write_return,
'label' : branching.write_label,
'goto' : branching.write_goto,
'if-goto' : branching.write_if,
}
def parse(vm_line: str) -> Tuple[str, List[str]]:
'''Tokenize and parse the source vm line'''
tokens = vm_line.split("//")[0].split() # ignore comments
try:
command, *args = tokens
except ValueError: # blank line
command, args = '//', [] # no difference from a comment
return (command, args)
def compile_line(vm_line: str, state: dict) -> Tuple[Tuple[str, ...], dict]:
# Parse
command, args = parse(vm_line)
# Compile!
if command in stateless:
asm_block = stateless[command]()
return asm_block, state
else:
asm_block, new_state = stateful[command](*args, state)
return asm_block, new_state