virtual_machine.sf 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #!/usr/bin/ruby
  2. #
  3. ## Inspired by Tom Hudson: https://www.youtube.com/watch?v=GjGRhIl0xWs
  4. #
  5. enum (
  6. PUSH,
  7. ADD,
  8. PRINT,
  9. HALT,
  10. JMPLT,
  11. );
  12. struct Op {
  13. String name,
  14. Number nargs,
  15. }
  16. var ops = Hash.new(
  17. PUSH, Op("push", 1),
  18. ADD, Op("add", 0),
  19. PRINT, Op("print", 0),
  20. HALT, Op("halt", 0),
  21. JMPLT, Op("jmplt", 2),
  22. );
  23. class VM {
  24. has code = []
  25. has pc = 0
  26. has stack = []
  27. has sp = -1
  28. method trace {
  29. var op = ops{code[pc]};
  30. var args = code.slice(pc+1, op.nargs);
  31. printf("%04d:%-10s%20s%40s\n", pc, op.name, args, stack);
  32. }
  33. method run(c=[]) {
  34. code = c;
  35. loop {
  36. # Trace
  37. self.trace();
  38. # Fetch
  39. var op = code[pc++];
  40. # Decode
  41. given(op) {
  42. when (PUSH) {
  43. var val = code[pc++];
  44. stack[++sp] = val;
  45. }
  46. when (ADD) {
  47. var a = stack[sp--];
  48. var b = stack[sp--];
  49. stack[++sp] = a+b;
  50. }
  51. when (PRINT) {
  52. var val = stack[sp--];
  53. say val;
  54. }
  55. when (JMPLT) {
  56. var lt = code[pc++];
  57. var addr = code[pc++];
  58. if (stack[sp] < lt) {
  59. pc = addr;
  60. }
  61. }
  62. when (HALT) {
  63. return();
  64. }
  65. }
  66. }
  67. }
  68. }
  69. var code = [
  70. PUSH, 2,
  71. PUSH, 3,
  72. ADD,
  73. JMPLT, 10, 2,
  74. PRINT,
  75. HALT,
  76. ];
  77. var v = VM();
  78. v.run(code);