Skip to content

Commit 4f6bfc7

Browse files
committed
feat: implement bytecode virtual machine and initial compiler components for ProXPL.
1 parent 42b702e commit 4f6bfc7

5 files changed

Lines changed: 25 additions & 152 deletions

File tree

include/vm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,5 +64,6 @@ struct ObjUpvalue *captureUpvalue(Value *local, VM *vm);
6464
bool invokeFromClass(struct ObjClass *klass, struct ObjString *name, int argCount, VM *vm);
6565
bool invoke(struct ObjString *name, int argCount, VM *vm);
6666
bool callValue(Value callee, int argCount, VM *vm);
67+
void runtimeError(VM* vm, const char* format, ...);
6768

6869
#endif // PROX_VM_H

src/compiler/backend_llvm.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,7 @@ class LLVMEmitter {
452452
break;
453453
}
454454
}
455+
455456

456457
void setupSchedulerHelpers() {
457458
// void prox_rt_resume(i8* hdl)
@@ -465,7 +466,7 @@ class LLVMEmitter {
465466
// Implement prox_rt_resume wrapper
466467
llvm::BasicBlock* Entry = llvm::BasicBlock::Create(*Context, "entry", FResume);
467468
llvm::IRBuilder<> ResBuilder(Entry);
468-
llvm::Function* FCoroResume = llvm::Intrinsic::getDeclaration(ModuleOb.get(), llvm::Intrinsic::coro_resume);
469+
llvm::Function* FCoroResume = llvm::Intrinsic::getOrInsertDeclaration(ModuleOb.get(), llvm::Intrinsic::coro_resume);
469470
// Note: getDeclaration is deprecated but for some LLVM versions getOrInsertDeclaration is for non-intrinsics?
470471
// Actually, for intrinsics, getDeclaration is still standard in many versions.
471472
// But the warning says use getOrInsertDeclaration?

src/compiler/parser/parser.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#include <stdlib.h>
1313
#include <string.h>
1414

15-
1615
// Forward declarations of parsing functions
1716
static Stmt *declaration(Parser *p);
1817
static Stmt *statement(Parser *p);
@@ -53,7 +52,7 @@ static Token advance(Parser *p);
5352
static bool check(Parser *p, PxTokenType type);
5453
static bool match(Parser *p, int count, ...);
5554
static Token consume(Parser *p, PxTokenType type, const char *message);
56-
static void synchronize(Parser *p);
55+
5756

5857
// === Initialization ===
5958

src/runtime/vm.c

Lines changed: 1 addition & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ void freeVM(VM *pvm) {
4444
}
4545

4646
// Runtime Error Helper
47-
static void runtimeError(VM* pvm, const char* format, ...) {
47+
void runtimeError(VM* pvm, const char* format, ...) {
4848
char message[1024];
4949
va_list args;
5050
va_start(args, format);
@@ -108,145 +108,6 @@ static void concatenate(VM* pvm) {
108108
}
109109

110110

111-
void closeUpvalues(VM *vm, Value *last) {
112-
while (vm->openUpvalues != NULL &&
113-
vm->openUpvalues->location >= last) {
114-
ObjUpvalue *upvalue = vm->openUpvalues;
115-
upvalue->closed = *upvalue->location;
116-
upvalue->location = &upvalue->closed;
117-
vm->openUpvalues = upvalue->next;
118-
}
119-
}
120-
121-
ObjUpvalue *captureUpvalue(Value *local, VM *vm) {
122-
ObjUpvalue *prevUpvalue = NULL;
123-
ObjUpvalue *upvalue = vm->openUpvalues;
124-
while (upvalue != NULL && upvalue->location > local) {
125-
prevUpvalue = upvalue;
126-
upvalue = upvalue->next;
127-
}
128-
129-
if (upvalue != NULL && upvalue->location == local) {
130-
return upvalue;
131-
}
132-
133-
ObjUpvalue *createdUpvalue = newUpvalue(local);
134-
createdUpvalue->next = upvalue;
135-
136-
if (prevUpvalue == NULL) {
137-
vm->openUpvalues = createdUpvalue;
138-
} else {
139-
prevUpvalue->next = createdUpvalue;
140-
}
141-
142-
return createdUpvalue;
143-
}
144-
145-
void defineMethod(ObjString *name, VM *vm) {
146-
Value method = peek(vm, 0);
147-
ObjClass *klass = AS_CLASS(peek(vm, 1));
148-
tableSet(&klass->methods, name, method);
149-
pop(vm);
150-
}
151-
152-
bool bindMethod(struct ObjClass *klass, ObjString *name, VM *vm) {
153-
Value method;
154-
if (!tableGet(&klass->methods, name, &method)) {
155-
runtimeError(vm, "Undefined property '%s'.", name->chars);
156-
return false;
157-
}
158-
159-
ObjBoundMethod *bound = newBoundMethod(peek(vm, 0), AS_CLOSURE(method));
160-
pop(vm);
161-
push(vm, OBJ_VAL(bound));
162-
return true;
163-
}
164-
165-
bool call(ObjClosure *closure, int argCount, VM *vm) {
166-
if (argCount != closure->function->arity) {
167-
runtimeError(vm, "Expected %d arguments but got %d.",
168-
closure->function->arity, argCount);
169-
return false;
170-
}
171-
172-
if (vm->frameCount == 64) {
173-
runtimeError(vm, "Stack overflow.");
174-
return false;
175-
}
176-
177-
CallFrame *frame = &vm->frames[vm->frameCount++];
178-
frame->closure = closure;
179-
frame->ip = closure->function->chunk.code;
180-
frame->slots = vm->stackTop - argCount - 1;
181-
return true;
182-
}
183-
184-
bool callValue(Value callee, int argCount, VM *vm) {
185-
if (IS_OBJ(callee)) {
186-
switch (OBJ_TYPE(callee)) {
187-
case OBJ_BOUND_METHOD: {
188-
ObjBoundMethod *bound = AS_BOUND_METHOD(callee);
189-
vm->stackTop[-argCount - 1] = bound->receiver;
190-
return call(bound->method, argCount, vm);
191-
}
192-
case OBJ_CLASS: {
193-
ObjClass *klass = AS_CLASS(callee);
194-
vm->stackTop[-argCount - 1] = OBJ_VAL(newInstance(klass));
195-
Value initializer;
196-
if (tableGet(&klass->methods, copyString("init", 4), &initializer)) {
197-
return call(AS_CLOSURE(initializer), argCount, vm);
198-
} else if (argCount != 0) {
199-
runtimeError(vm, "Expected 0 arguments but got %d.", argCount);
200-
return false;
201-
}
202-
return true;
203-
}
204-
case OBJ_CLOSURE:
205-
return call(AS_CLOSURE(callee), argCount, vm);
206-
case OBJ_NATIVE: {
207-
NativeFn native = AS_NATIVE(callee);
208-
Value result = native(argCount, vm->stackTop - argCount);
209-
vm->stackTop -= argCount + 1;
210-
push(vm, result);
211-
return true;
212-
}
213-
default:
214-
break; // Non-callable object type
215-
}
216-
}
217-
runtimeError(vm, "Can only call functions and classes.");
218-
return false;
219-
}
220-
221-
bool invokeFromClass(struct ObjClass *klass, ObjString *name,
222-
int argCount, VM *vm) {
223-
Value method;
224-
if (!tableGet(&klass->methods, name, &method)) {
225-
runtimeError(vm, "Undefined property '%s'.", name->chars);
226-
return false;
227-
}
228-
return call(AS_CLOSURE(method), argCount, vm);
229-
}
230-
231-
bool invoke(ObjString *name, int argCount, VM *vm) {
232-
Value receiver = peek(vm, argCount);
233-
234-
if (!IS_INSTANCE(receiver)) {
235-
runtimeError(vm, "Only instances have methods.");
236-
return false;
237-
}
238-
239-
struct ObjInstance *instance = AS_INSTANCE(receiver);
240-
241-
Value value;
242-
if (tableGet(&instance->fields, name, &value)) {
243-
vm->stackTop[-argCount - 1] = value;
244-
return callValue(value, argCount, vm);
245-
}
246-
247-
return invokeFromClass(instance->klass, name, argCount, vm);
248-
}
249-
250111
static InterpretResult run(VM *vm) {
251112

252113
CallFrame* frame = &vm->frames[vm->frameCount - 1];

src/runtime/vm_helpers.c

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
1+
#include <stdio.h>
2+
#include <string.h>
3+
#include <stdarg.h>
14

2-
static void closeUpvalues(VM *vm, Value *last) {
5+
#include "../include/common.h"
6+
#include "../include/vm.h"
7+
#include "../include/object.h"
8+
#include "../include/memory.h"
9+
#include "../include/debug.h"
10+
#include "../include/compiler.h"
11+
12+
13+
void closeUpvalues(VM *vm, Value *last) {
314
while (vm->openUpvalues != NULL &&
415
vm->openUpvalues->location >= last) {
516
ObjUpvalue *upvalue = vm->openUpvalues;
@@ -9,7 +20,7 @@ static void closeUpvalues(VM *vm, Value *last) {
920
}
1021
}
1122

12-
static ObjUpvalue *captureUpvalue(Value *local, VM *vm) {
23+
ObjUpvalue *captureUpvalue(Value *local, VM *vm) {
1324
ObjUpvalue *prevUpvalue = NULL;
1425
ObjUpvalue *upvalue = vm->openUpvalues;
1526
while (upvalue != NULL && upvalue->location > local) {
@@ -33,14 +44,14 @@ static ObjUpvalue *captureUpvalue(Value *local, VM *vm) {
3344
return createdUpvalue;
3445
}
3546

36-
static void defineMethod(ObjString *name, VM *vm) {
47+
void defineMethod(ObjString *name, VM *vm) {
3748
Value method = peek(vm, 0);
3849
ObjClass *klass = AS_CLASS(peek(vm, 1));
3950
tableSet(&klass->methods, name, method);
4051
pop(vm);
4152
}
4253

43-
static bool bindMethod(struct ObjClass *klass, ObjString *name, VM *vm) {
54+
bool bindMethod(struct ObjClass *klass, ObjString *name, VM *vm) {
4455
Value method;
4556
if (!tableGet(&klass->methods, name, &method)) {
4657
runtimeError(vm, "Undefined property '%s'.", name->chars);
@@ -53,7 +64,7 @@ static bool bindMethod(struct ObjClass *klass, ObjString *name, VM *vm) {
5364
return true;
5465
}
5566

56-
static bool call(ObjClosure *closure, int argCount, VM *vm) {
67+
bool call(ObjClosure *closure, int argCount, VM *vm) {
5768
if (argCount != closure->function->arity) {
5869
runtimeError(vm, "Expected %d arguments but got %d.",
5970
closure->function->arity, argCount);
@@ -72,7 +83,7 @@ static bool call(ObjClosure *closure, int argCount, VM *vm) {
7283
return true;
7384
}
7485

75-
static bool callValue(Value callee, int argCount, VM *vm) {
86+
bool callValue(Value callee, int argCount, VM *vm) {
7687
if (IS_OBJ(callee)) {
7788
switch (OBJ_TYPE(callee)) {
7889
case OBJ_BOUND_METHOD: {
@@ -109,7 +120,7 @@ static bool callValue(Value callee, int argCount, VM *vm) {
109120
return false;
110121
}
111122

112-
static bool invokeFromClass(struct ObjClass *klass, ObjString *name,
123+
bool invokeFromClass(struct ObjClass *klass, ObjString *name,
113124
int argCount, VM *vm) {
114125
Value method;
115126
if (!tableGet(&klass->methods, name, &method)) {
@@ -119,15 +130,15 @@ static bool invokeFromClass(struct ObjClass *klass, ObjString *name,
119130
return call(AS_CLOSURE(method), argCount, vm);
120131
}
121132

122-
static bool invoke(ObjString *name, int argCount, VM *vm) {
133+
bool invoke(ObjString *name, int argCount, VM *vm) {
123134
Value receiver = peek(vm, argCount);
124135

125136
if (!IS_INSTANCE(receiver)) {
126137
runtimeError(vm, "Only instances have methods.");
127138
return false;
128139
}
129140

130-
ObjInstance *instance = AS_INSTANCE(receiver);
141+
struct ObjInstance *instance = AS_INSTANCE(receiver);
131142

132143
Value value;
133144
if (tableGet(&instance->fields, name, &value)) {

0 commit comments

Comments
 (0)