소스 검색

Initial commit

Shuning Bian 2 달 전
커밋
485018aa15
3개의 변경된 파일182개의 추가작업 그리고 0개의 파일을 삭제
  1. 25 0
      fib_given.asm
  2. 37 0
      fib_sb.asm
  3. 120 0
      vm.py

+ 25 - 0
fib_given.asm

@@ -0,0 +1,25 @@
+# init to 1
+INC A_Bug
+
+INC B_Task
+
+.TODO
+%print reg
+%sleep 1
+
+# moves A into C and adds A to B
+DEC A_Bug .QA
+    INC C_Story
+    INC B_Task
+    DEC Z .TODO
+
+.QA
+%print reg
+%sleep 1
+
+# moves C into A
+DEC C_Story .TODO
+    INC A_Bug
+    DEC Z .QA
+
+

+ 37 - 0
fib_sb.asm

@@ -0,0 +1,37 @@
+# init to 1
+INC A_Bug
+
+INC B_Task
+%print reg
+
+.TODO
+
+# move B into C and adds B to A
+DEC B_Task .QA
+    INC C_Story
+    INC A_Bug
+    DEC Z .TODO
+
+.QA
+# moves A into B
+DEC A_Bug .IN_PROG
+    INC B_Task
+    DEC Z .QA
+
+.IN_PROG
+
+# moves C into A
+DEC C_Story .OUTPUT
+    INC A_Bug
+    DEC Z .IN_PROG
+
+.OUTPUT
+%print reg
+%sleep 1
+
+DEC Z .TODO
+
+
+
+
+

+ 120 - 0
vm.py

@@ -0,0 +1,120 @@
+#!/bin/bash env python3
+"""
+Reads stdin in full then interprets the instructions on each line as follows:
+    - `DEC $R $S`: if register `$R` is > 0, decrement it, otherwise jump to state `$S`
+    - `INC $R`: increments register `$R`
+    - `.$STATE`: labels the current position as `$STATE` allowing transition from `DEC`.
+      Note that the entirety of the line $STATE`, i.e. the name of the state _includes_
+      the leading `.`
+    - `HALT`: halts the machine and exits
+    - `%`: debug instructions, e.g. printing program state
+
+Any string is allowed for register names and state names as long as they don't contain
+a space.
+
+Comments are allowed via `#` where everything pass `#` and `#` itself is stripped out
+prior to execution.
+"""
+
+from dataclasses import dataclass
+from collections import Counter
+import sys
+import time
+
+@dataclass
+class Instruction:
+    OP_DEC = 0
+    OP_INC = 1
+    OP_HALT = 2
+    OP_STATE = 3
+    OP_DEBUG = 99
+
+    op: int
+    pc: int
+    source_line: str = None
+    reg_arg: str = None
+    state_arg: str = None
+
+def main():
+    program: list[Instruction] = []
+    registers = Counter()
+    # maps labels to PC counter values
+    states: dict[str, int] = {}
+
+    source_code = [l.strip() for l in sys.stdin.readlines()]
+
+    pc = 0
+    for line in source_code:
+        line = line.split('#')[0]
+        if len(line) == 0:
+            continue
+
+        tokens = line.split(' ')
+        inst = None
+        if tokens[0] == 'DEC':
+            inst = Instruction(Instruction.OP_DEC, pc, line, reg_arg = tokens[1], state_arg=tokens[2])
+
+        if tokens[0] == 'INC':
+            inst = Instruction(Instruction.OP_INC, pc, line, reg_arg = tokens[1])
+
+        if tokens[0] == 'HALT':
+            inst = Instruction(Instruction.OP_HALT, pc, line)
+
+        if tokens[0][0] == '.':
+            inst = Instruction(Instruction.OP_STATE, pc, line)
+            states[tokens[0]] = pc
+        if tokens[0][0] == '%':
+            inst = Instruction(Instruction.OP_DEBUG, pc, line)
+
+        if inst is None:
+            raise ValueError(f'Unknown instruction: {line}')
+
+        program.append(inst)
+        pc += 1
+
+    print('Parsed program:')
+    for state, pc_val in states.items():
+        print(f'{state=} {pc_val=}')
+
+    for idx, inst in enumerate(program):
+        print(idx + 1, inst)
+
+    print('Executing...')
+    pc = 0
+    halted = False
+    while not halted and pc >= 0:
+        inst = program[pc]
+
+        if inst.op == Instruction.OP_DEC:
+            if registers[inst.reg_arg] == 0:
+                pc = states[inst.state_arg]
+            else:
+                registers[inst.reg_arg] -= 1
+                pc += 1
+
+        if inst.op == Instruction.OP_INC:
+            registers[inst.reg_arg] += 1
+            pc += 1
+
+        if inst.op == Instruction.OP_HALT:
+            halted = True
+            pc -= 1
+
+        if inst.op == Instruction.OP_STATE:
+            pc += 1
+
+        if inst.op == Instruction.OP_DEBUG:
+            pc += 1
+
+            tokens = inst.source_line[1:].split(' ')
+            if tokens[0] == 'print':
+                if tokens[1] == 'reg':
+                    for k in sorted(registers.keys()):
+                        print(f'{k} = {registers[k]}', end=' ')
+                    print()
+            if tokens[0] == 'sleep':
+                t = float(tokens[1])
+                time.sleep(t)
+
+if __name__ == '__main__':
+    main()