1 module viva.dvm.vm.vm; 2 3 import viva.dvm.vm.instruction; 4 import viva.dvm.vm.opcode; 5 6 /++ 7 + 8 +/ 9 struct VM 10 { 11 private int[] stack; 12 private int ip = 0; 13 private int sp = -1; 14 15 /// 16 public Instruction[] instructions; 17 18 /++ 19 + 20 +/ 21 this(Instruction[] instructions) 22 { 23 this.instructions = instructions; 24 25 this.stack = new int[countStackInstructions() -1]; 26 } 27 28 private int countStackInstructions() 29 { 30 int count = 0; 31 32 foreach (instruction; instructions) 33 { 34 if ( 35 instruction.opcode == Opcode.ICONST 36 || instruction.opcode == Opcode.IADD 37 || instruction.opcode == Opcode.ISUB 38 || instruction.opcode == Opcode.IMUL 39 || instruction.opcode == Opcode.IDIV 40 || instruction.opcode == Opcode.INEG 41 ) 42 count++; 43 44 else if (instruction.operands.length != 0) 45 count++; 46 } 47 48 return count; 49 } 50 51 private int pop() 52 { 53 int val = stack[sp]; 54 stack[sp] = 0; 55 sp--; 56 return val; 57 } 58 59 private void push(int val) 60 { 61 sp++; 62 stack[sp] = val; 63 return; 64 } 65 66 /++ 67 + 68 +/ 69 public void execute() 70 { 71 foreach (instruction; instructions) 72 { 73 ip++; 74 75 final switch (instruction.opcode) 76 { 77 case Opcode.HALT: return; 78 79 case Opcode.PRINT: 80 { 81 import viva.io.console : println; 82 83 int i = stack[sp]; 84 println(i); 85 86 continue; 87 } 88 89 case Opcode.DUP: 90 { 91 int i = stack[sp]; 92 push(i); 93 94 continue; 95 } 96 97 case Opcode.SWAP: 98 { 99 int i = pop(); 100 int j = pop(); 101 push(i); 102 push(j); 103 104 continue; 105 } 106 107 case Opcode.ICONST: 108 { 109 int i = instruction.operands[0]; 110 push(i); 111 112 continue; 113 } 114 115 case Opcode.IADD: 116 { 117 int i = pop(); 118 int j = pop(); 119 push(i + j); 120 121 continue; 122 } 123 124 case Opcode.ISUB: 125 { 126 int i = pop(); 127 int j = pop(); 128 push(j - i); 129 130 continue; 131 } 132 133 case Opcode.IMUL: 134 { 135 int i = pop(); 136 int j = pop(); 137 push(j * i); 138 139 continue; 140 } 141 142 case Opcode.IDIV: 143 { 144 int i = pop(); 145 int j = pop(); 146 push(j / i); 147 148 continue; 149 } 150 151 case Opcode.INEG: 152 { 153 int i = pop(); 154 push(-i); 155 156 continue; 157 } 158 } 159 } 160 } 161 }