mirror of
https://github.com/wren-lang/wren.git
synced 2026-01-11 06:08:41 +01:00
162 lines
3.1 KiB
C
162 lines
3.1 KiB
C
#ifndef wren_vm_h
|
|
#define wren_vm_h
|
|
|
|
// TODO(bob): Make these externally controllable.
|
|
#define STACK_SIZE 1024
|
|
#define MAX_CALL_FRAMES 256
|
|
#define MAX_SYMBOLS 256
|
|
|
|
typedef enum {
|
|
OBJ_NUM,
|
|
OBJ_BLOCK,
|
|
OBJ_CLASS,
|
|
OBJ_INSTANCE
|
|
} ObjType;
|
|
|
|
typedef enum
|
|
{
|
|
// The object has been marked during the mark phase of GC.
|
|
FLAG_MARKED = 0x01,
|
|
} ObjFlags;
|
|
|
|
typedef struct
|
|
{
|
|
ObjType type;
|
|
ObjFlags flags;
|
|
} Obj;
|
|
|
|
typedef Obj* Value;
|
|
|
|
typedef struct
|
|
{
|
|
Obj obj;
|
|
double value;
|
|
} ObjNum;
|
|
|
|
typedef struct
|
|
{
|
|
Obj obj;
|
|
unsigned char* bytecode;
|
|
Value* constants;
|
|
int numConstants;
|
|
int numLocals;
|
|
} ObjBlock;
|
|
|
|
typedef Value (*Primitive)(Value receiver);
|
|
|
|
typedef enum
|
|
{
|
|
METHOD_NONE,
|
|
METHOD_CALL,
|
|
METHOD_PRIMITIVE,
|
|
METHOD_BLOCK
|
|
} MethodType;
|
|
|
|
typedef struct
|
|
{
|
|
MethodType type;
|
|
union
|
|
{
|
|
Primitive primitive;
|
|
ObjBlock* block;
|
|
};
|
|
} Method;
|
|
|
|
typedef struct sObjClass
|
|
{
|
|
Obj obj;
|
|
struct sObjClass* metaclass;
|
|
// TODO(bob): Hack. Probably don't want to use this much space.
|
|
Method methods[MAX_SYMBOLS];
|
|
} ObjClass;
|
|
|
|
typedef struct
|
|
{
|
|
Obj obj;
|
|
ObjClass* classObj;
|
|
// TODO(bob): Fields.
|
|
} ObjInstance;
|
|
|
|
typedef enum
|
|
{
|
|
CODE_CONSTANT,
|
|
// Load the constant at index [arg].
|
|
|
|
CODE_CLASS,
|
|
// Define a new empty class and push it.
|
|
|
|
CODE_METHOD,
|
|
// Add a method for symbol [arg1] with body stored in constant [arg2] to the
|
|
// class on the top of stack. Does not modify the stack.
|
|
|
|
CODE_DUP,
|
|
// Push a copy of the top of stack.
|
|
|
|
CODE_POP,
|
|
// Pop and discard the top of stack.
|
|
|
|
CODE_LOAD_LOCAL,
|
|
// Pushes the value in local slot [arg].
|
|
|
|
CODE_STORE_LOCAL,
|
|
// Stores the top of stack in local slot [arg]. Does not pop it.
|
|
|
|
CODE_CALL,
|
|
// Invoke the method with symbol [arg].
|
|
|
|
CODE_END
|
|
// The current block is done and should be exited.
|
|
|
|
} Code;
|
|
|
|
typedef struct
|
|
{
|
|
// TODO(bob): Make this dynamically sized.
|
|
char* names[MAX_SYMBOLS];
|
|
int count;
|
|
} SymbolTable;
|
|
|
|
typedef struct
|
|
{
|
|
SymbolTable symbols;
|
|
|
|
ObjClass* blockClass;
|
|
ObjClass* classClass;
|
|
ObjClass* numClass;
|
|
} VM;
|
|
|
|
VM* newVM();
|
|
void freeVM(VM* vm);
|
|
|
|
ObjClass* makeClass();
|
|
ObjBlock* makeBlock();
|
|
ObjNum* makeNum(double number);
|
|
ObjInstance* makeInstance(ObjClass* classObj);
|
|
|
|
// Initializes the symbol table.
|
|
void initSymbolTable(SymbolTable* symbols);
|
|
|
|
// Frees all dynamically allocated memory used by the symbol table, but not the
|
|
// SymbolTable itself.
|
|
void clearSymbolTable(SymbolTable* symbols);
|
|
|
|
// Adds name to the symbol table. Returns the index of it in the table. Returns
|
|
// -1 if the symbol is already present.
|
|
int addSymbol(SymbolTable* symbols, const char* name, size_t length);
|
|
|
|
// Adds name to the symbol table. Returns the index of it in the table. Will
|
|
// use an existing symbol if already present.
|
|
int ensureSymbol(SymbolTable* symbols, const char* name, size_t length);
|
|
|
|
// Looks up name in the symbol table. Returns its index if found or -1 if not.
|
|
int findSymbol(SymbolTable* symbols, const char* name, size_t length);
|
|
|
|
// Given an index in the symbol table, returns its name.
|
|
const char* getSymbolName(SymbolTable* symbols, int symbol);
|
|
|
|
Value interpret(VM* vm, ObjBlock* block);
|
|
|
|
void printValue(Value value);
|
|
|
|
#endif
|