#ifndef wren_vm_h
#define wren_vm_h
#include "wren_common.h"
#include "wren_compiler.h"
#include "wren_value.h"
#include "wren_utils.h"
#define WREN_MAX_TEMP_ROOTS 5
typedef enum
{
#define OPCODE(name, _) CODE_##name,
#include "wren_opcodes.h"
#undef OPCODE
} Code;
struct WrenHandle
{
Value value;
WrenHandle* prev;
WrenHandle* next;
};
struct WrenVM
{
ObjClass* boolClass;
ObjClass* classClass;
ObjClass* fiberClass;
ObjClass* fnClass;
ObjClass* listClass;
ObjClass* mapClass;
ObjClass* nullClass;
ObjClass* numClass;
ObjClass* objectClass;
ObjClass* rangeClass;
ObjClass* stringClass;
ObjFiber* fiber;
ObjMap* modules;
size_t bytesAllocated;
size_t nextGC;
Obj* first;
Obj** gray;
int grayCount;
int grayCapacity;
Obj* tempRoots[WREN_MAX_TEMP_ROOTS];
int numTempRoots;
WrenHandle* handles;
Value* apiStack;
WrenConfiguration config;
Compiler* compiler;
SymbolTable methodNames;
};
void* wrenReallocate(WrenVM* vm, void* memory, size_t oldSize, size_t newSize);
void wrenFinalizeForeign(WrenVM* vm, ObjForeign* foreign);
WrenHandle* wrenMakeHandle(WrenVM* vm, Value value);
WrenInterpretResult wrenInterpretInModule(WrenVM* vm, const char* module,
const char* source);
Value wrenImportModule(WrenVM* vm, Value name);
Value wrenGetModuleVariable(WrenVM* vm, Value moduleName, Value variableName);
Value wrenFindVariable(WrenVM* vm, ObjModule* module, const char* name);
int wrenDeclareVariable(WrenVM* vm, ObjModule* module, const char* name,
size_t length, int line);
int wrenDefineVariable(WrenVM* vm, ObjModule* module, const char* name,
size_t length, Value value);
void wrenPushRoot(WrenVM* vm, Obj* obj);
void wrenPopRoot(WrenVM* vm);
static inline ObjClass* wrenGetClassInline(WrenVM* vm, Value value)
{
if (IS_NUM(value)) return vm->numClass;
if (IS_OBJ(value)) return AS_OBJ(value)->classObj;
#if WREN_NAN_TAGGING
switch (GET_TAG(value))
{
case TAG_FALSE: return vm->boolClass; break;
case TAG_NAN: return vm->numClass; break;
case TAG_NULL: return vm->nullClass; break;
case TAG_TRUE: return vm->boolClass; break;
case TAG_UNDEFINED: UNREACHABLE();
}
#else
switch (value.type)
{
case VAL_FALSE: return vm->boolClass;
case VAL_NULL: return vm->nullClass;
case VAL_NUM: return vm->numClass;
case VAL_TRUE: return vm->boolClass;
case VAL_OBJ: return AS_OBJ(value)->classObj;
case VAL_UNDEFINED: UNREACHABLE();
}
#endif
UNREACHABLE();
return NULL;
}
#endif