Skip to content
This repository was archived by the owner on May 24, 2022. It is now read-only.

Commit 1f10bf6

Browse files
committed
Finish basic Virtual Machine
1 parent 49256eb commit 1f10bf6

File tree

7 files changed

+181
-5
lines changed

7 files changed

+181
-5
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
build/
1+
build/
2+
.vscode

includes/chunk.h

+5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
typedef enum
88
{
99
OP_CONSTANT,
10+
OP_ADD,
11+
OP_SUBTRACT,
12+
OP_MULTIPLY,
13+
OP_DIVIDE,
14+
OP_NEGATE,
1015
OP_RETURN
1116
} OpCode;
1217

includes/common.h

+2
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@
55
#include <stddef.h>
66
#include <stdint.h>
77

8+
#define DEBUG_TRACE_EXECUTION
9+
810
#endif

includes/vm.h

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#ifndef meon_vm_h
2+
#define meon_vm_h
3+
4+
#include "chunk.h"
5+
#include "value.h"
6+
7+
#define STACK_MAX 256
8+
9+
typedef struct
10+
{
11+
Chunk *chunk;
12+
uint8_t *ip;
13+
Value *stack;
14+
int stackSize;
15+
int stackMaxSize;
16+
} VM;
17+
18+
typedef enum
19+
{
20+
INTERPRET_OK,
21+
INTERPRET_COMPILE_ERROR,
22+
INTERPRET_RUNTIME_ERROR
23+
} InterpretResult;
24+
25+
void initVM();
26+
void freeVM();
27+
InterpretResult interpret(Chunk *chunk);
28+
void push(Value value);
29+
Value pop();
30+
31+
#endif

src/debug.c

+13-3
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ static int simpleInstruction(const char *name, int offset)
2929

3030
int disassembleInstruction(Chunk *chunk, int offset)
3131
{
32-
printf("%04d ", offset);
32+
printf("%04X ", offset);
3333
int line = getLine(chunk, offset);
3434
if (offset > 0 && line == getLine(chunk, offset - 1))
3535
{
@@ -43,10 +43,20 @@ int disassembleInstruction(Chunk *chunk, int offset)
4343
uint8_t instruction = chunk->code[offset];
4444
switch (instruction)
4545
{
46-
case OP_RETURN:
47-
return simpleInstruction("ret", offset);
4846
case OP_CONSTANT:
4947
return constantInstruction("const", chunk, offset);
48+
case OP_ADD:
49+
return simpleInstruction("add", offset);
50+
case OP_SUBTRACT:
51+
return simpleInstruction("sub", offset);
52+
case OP_MULTIPLY:
53+
return simpleInstruction("mul", offset);
54+
case OP_DIVIDE:
55+
return simpleInstruction("div", offset);
56+
case OP_NEGATE:
57+
return simpleInstruction("neg", offset);
58+
case OP_RETURN:
59+
return simpleInstruction("ret", offset);
5060
default:
5161
printf("Unknown OpCode %d\n", instruction);
5262
return offset + 1;

src/main.c

+18-1
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,34 @@
11
#include "chunk.h"
22
#include "debug.h"
3+
#include "vm.h"
34

45
int main(int argc, char *argv[])
56
{
7+
initVM();
68
Chunk chunk;
79
initChunk(&chunk);
810

911
int constant = addConstant(&chunk, 1.2);
1012
writeChunk(&chunk, OP_CONSTANT, 123);
1113
writeChunk(&chunk, constant, 123);
14+
15+
constant = addConstant(&chunk, 3.4);
16+
writeChunk(&chunk, OP_CONSTANT, 123);
17+
writeChunk(&chunk, constant, 123);
18+
19+
writeChunk(&chunk, OP_ADD, 123);
20+
21+
constant = addConstant(&chunk, 5.6);
22+
writeChunk(&chunk, OP_CONSTANT, 123);
23+
writeChunk(&chunk, constant, 123);
24+
25+
writeChunk(&chunk, OP_DIVIDE, 123);
26+
writeChunk(&chunk, OP_NEGATE, 123);
1227
writeChunk(&chunk, OP_RETURN, 123);
1328

1429
disassembleChunk(&chunk, "test chunk");
30+
interpret(&chunk);
31+
freeVM();
1532
freeChunk(&chunk);
1633
return 0;
17-
}
34+
}

src/vm.c

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#include <stdio.h>
2+
3+
#include "common.h"
4+
#include "debug.h"
5+
#include "vm.h"
6+
#include "mem.h"
7+
8+
VM vm;
9+
10+
static void resetStack()
11+
{
12+
vm.stackSize = 0;
13+
}
14+
15+
void initVM()
16+
{
17+
vm.stack = NULL;
18+
vm.stackMaxSize = 0;
19+
resetStack();
20+
}
21+
22+
void freeVM() {}
23+
24+
void push(Value value)
25+
{
26+
if (vm.stackMaxSize < vm.stackSize + 1)
27+
{
28+
int old = vm.stackMaxSize;
29+
vm.stackMaxSize = GROW_ARRAY_SIZE(old);
30+
vm.stack = GROW_ARRAY(Value, vm.stack, old, vm.stackMaxSize);
31+
}
32+
vm.stack[vm.stackSize] = value;
33+
vm.stackSize++;
34+
}
35+
36+
Value pop()
37+
{
38+
vm.stackSize--;
39+
return vm.stack[vm.stackSize];
40+
}
41+
42+
static InterpretResult run()
43+
{
44+
#define READ_BYTE() (*vm.ip++)
45+
#define READ_CONSTANT() (vm.chunk->constants.values[READ_BYTE()])
46+
47+
#define BINARY_OP(op) \
48+
do \
49+
{ \
50+
double b = pop(); \
51+
double a = pop(); \
52+
push(a op b); \
53+
} while (false)
54+
55+
for (;;)
56+
{
57+
#ifdef DEBUG_TRACE_EXECUTION
58+
printf(" ");
59+
for (int i = 0; i < vm.stackSize; i++)
60+
{
61+
printf("[ ");
62+
printValue(vm.stack[i]);
63+
printf(" ]");
64+
}
65+
printf("\n");
66+
disassembleInstruction(vm.chunk, (int)(vm.ip - vm.chunk->code));
67+
#endif
68+
69+
uint8_t instruction;
70+
switch (instruction = READ_BYTE())
71+
{
72+
case OP_CONSTANT:
73+
{
74+
Value constant = READ_CONSTANT();
75+
push(constant);
76+
break;
77+
}
78+
case OP_ADD:
79+
BINARY_OP(+);
80+
break;
81+
case OP_SUBTRACT:
82+
BINARY_OP(-);
83+
break;
84+
case OP_MULTIPLY:
85+
BINARY_OP(*);
86+
break;
87+
case OP_DIVIDE:
88+
BINARY_OP(/);
89+
break;
90+
case OP_NEGATE:
91+
push(-pop());
92+
break;
93+
case OP_RETURN:
94+
{
95+
printValue(pop());
96+
printf("\n");
97+
return INTERPRET_OK;
98+
}
99+
}
100+
}
101+
#undef READ_BYTE
102+
#undef READ_CONSTANT
103+
}
104+
105+
InterpretResult interpret(Chunk *chunk)
106+
{
107+
vm.chunk = chunk;
108+
vm.ip = vm.chunk->code;
109+
return run();
110+
}

0 commit comments

Comments
 (0)