1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- #!/usr/bin/ruby
- #
- ## Inspired by Tom Hudson: https://www.youtube.com/watch?v=GjGRhIl0xWs
- #
- enum (
- PUSH,
- ADD,
- PRINT,
- HALT,
- JMPLT,
- );
- struct Op {
- String name,
- Number nargs,
- }
- var ops = Hash.new(
- PUSH, Op("push", 1),
- ADD, Op("add", 0),
- PRINT, Op("print", 0),
- HALT, Op("halt", 0),
- JMPLT, Op("jmplt", 2),
- );
- class VM {
- has code = []
- has pc = 0
- has stack = []
- has sp = -1
- method trace {
- var op = ops{code[pc]};
- var args = code.slice(pc+1, op.nargs);
- printf("%04d:%-10s%20s%40s\n", pc, op.name, args, stack);
- }
- method run(c=[]) {
- code = c;
- loop {
- # Trace
- self.trace();
- # Fetch
- var op = code[pc++];
- # Decode
- given(op) {
- when (PUSH) {
- var val = code[pc++];
- stack[++sp] = val;
- }
- when (ADD) {
- var a = stack[sp--];
- var b = stack[sp--];
- stack[++sp] = a+b;
- }
- when (PRINT) {
- var val = stack[sp--];
- say val;
- }
- when (JMPLT) {
- var lt = code[pc++];
- var addr = code[pc++];
- if (stack[sp] < lt) {
- pc = addr;
- }
- }
- when (HALT) {
- return();
- }
- }
- }
- }
- }
- var code = [
- PUSH, 2,
- PUSH, 3,
- ADD,
- JMPLT, 10, 2,
- PRINT,
- HALT,
- ];
- var v = VM();
- v.run(code);
|