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 }