forked from Mirror/wren
wren/vm: Uniformize macros to stick to 80 columns. (#756)
uniform macros
This commit is contained in:
@ -15,8 +15,8 @@
|
||||
|
||||
// A monotonically increasing numeric representation of the version number. Use
|
||||
// this if you want to do range checks over versions.
|
||||
#define WREN_VERSION_NUMBER (WREN_VERSION_MAJOR * 1000000 + \
|
||||
WREN_VERSION_MINOR * 1000 + \
|
||||
#define WREN_VERSION_NUMBER (WREN_VERSION_MAJOR * 1000000 + \
|
||||
WREN_VERSION_MINOR * 1000 + \
|
||||
WREN_VERSION_PATCH)
|
||||
|
||||
// A single virtual machine for executing Wren code.
|
||||
|
||||
@ -114,17 +114,17 @@
|
||||
#define MAX_FIELDS 255
|
||||
|
||||
// Use the VM's allocator to allocate an object of [type].
|
||||
#define ALLOCATE(vm, type) \
|
||||
#define ALLOCATE(vm, type) \
|
||||
((type*)wrenReallocate(vm, NULL, 0, sizeof(type)))
|
||||
|
||||
// Use the VM's allocator to allocate an object of [mainType] containing a
|
||||
// flexible array of [count] objects of [arrayType].
|
||||
#define ALLOCATE_FLEX(vm, mainType, arrayType, count) \
|
||||
((mainType*)wrenReallocate(vm, NULL, 0, \
|
||||
sizeof(mainType) + sizeof(arrayType) * (count)))
|
||||
#define ALLOCATE_FLEX(vm, mainType, arrayType, count) \
|
||||
((mainType*)wrenReallocate(vm, NULL, 0, \
|
||||
sizeof(mainType) + sizeof(arrayType) * (count)))
|
||||
|
||||
// Use the VM's allocator to allocate an array of [count] elements of [type].
|
||||
#define ALLOCATE_ARRAY(vm, type, count) \
|
||||
#define ALLOCATE_ARRAY(vm, type, count) \
|
||||
((type*)wrenReallocate(vm, NULL, 0, sizeof(type) * (count)))
|
||||
|
||||
// Use the VM's allocator to free the previously allocated memory at [pointer].
|
||||
@ -156,17 +156,15 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define ASSERT(condition, message) \
|
||||
do \
|
||||
{ \
|
||||
if (!(condition)) \
|
||||
{ \
|
||||
fprintf(stderr, "[%s:%d] Assert failed in %s(): %s\n", \
|
||||
__FILE__, __LINE__, __func__, message); \
|
||||
abort(); \
|
||||
} \
|
||||
} \
|
||||
while(0)
|
||||
#define ASSERT(condition, message) \
|
||||
do { \
|
||||
if (!(condition)) \
|
||||
{ \
|
||||
fprintf(stderr, "[%s:%d] Assert failed in %s(): %s\n", \
|
||||
__FILE__, __LINE__, __func__, message); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
// Indicates that we know execution should never reach this point in the
|
||||
// program. In debug mode, we assert this fact because it's a bug to get here.
|
||||
@ -175,18 +173,16 @@
|
||||
// compiler the code can't be reached. This avoids "missing return" warnings
|
||||
// in some cases and also lets it perform some optimizations by assuming the
|
||||
// code is never reached.
|
||||
#define UNREACHABLE() \
|
||||
do \
|
||||
{ \
|
||||
fprintf(stderr, "[%s:%d] This code should not be reached in %s()\n", \
|
||||
__FILE__, __LINE__, __func__); \
|
||||
abort(); \
|
||||
} \
|
||||
while (0)
|
||||
#define UNREACHABLE() \
|
||||
do { \
|
||||
fprintf(stderr, "[%s:%d] This code should not be reached in %s()\n", \
|
||||
__FILE__, __LINE__, __func__); \
|
||||
abort(); \
|
||||
} while (false)
|
||||
|
||||
#else
|
||||
|
||||
#define ASSERT(condition, message) do {} while (0)
|
||||
#define ASSERT(condition, message) do { } while (false)
|
||||
|
||||
// Tell the compiler that this part of the code will never be reached.
|
||||
#if defined( _MSC_VER )
|
||||
|
||||
@ -259,12 +259,12 @@ static void call_fn(WrenVM* vm, Value* args, int numArgs)
|
||||
wrenCallFunction(vm, vm->fiber, AS_CLOSURE(args[0]), numArgs + 1);
|
||||
}
|
||||
|
||||
#define DEF_FN_CALL(numArgs) \
|
||||
DEF_PRIMITIVE(fn_call##numArgs) \
|
||||
{ \
|
||||
call_fn(vm, args, numArgs); \
|
||||
return false; \
|
||||
} \
|
||||
#define DEF_FN_CALL(numArgs) \
|
||||
DEF_PRIMITIVE(fn_call##numArgs) \
|
||||
{ \
|
||||
call_fn(vm, args, numArgs); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
DEF_FN_CALL(0)
|
||||
DEF_FN_CALL(1)
|
||||
@ -600,11 +600,11 @@ DEF_PRIMITIVE(num_pi)
|
||||
}
|
||||
|
||||
// Defines a primitive on Num that calls infix [op] and returns [type].
|
||||
#define DEF_NUM_INFIX(name, op, type) \
|
||||
DEF_PRIMITIVE(num_##name) \
|
||||
{ \
|
||||
if (!validateNum(vm, args[1], "Right operand")) return false; \
|
||||
RETURN_##type(AS_NUM(args[0]) op AS_NUM(args[1])); \
|
||||
#define DEF_NUM_INFIX(name, op, type) \
|
||||
DEF_PRIMITIVE(num_##name) \
|
||||
{ \
|
||||
if (!validateNum(vm, args[1], "Right operand")) return false; \
|
||||
RETURN_##type(AS_NUM(args[0]) op AS_NUM(args[1])); \
|
||||
}
|
||||
|
||||
DEF_NUM_INFIX(minus, -, NUM)
|
||||
@ -617,13 +617,13 @@ DEF_NUM_INFIX(lte, <=, BOOL)
|
||||
DEF_NUM_INFIX(gte, >=, BOOL)
|
||||
|
||||
// Defines a primitive on Num that call infix bitwise [op].
|
||||
#define DEF_NUM_BITWISE(name, op) \
|
||||
DEF_PRIMITIVE(num_bitwise##name) \
|
||||
{ \
|
||||
if (!validateNum(vm, args[1], "Right operand")) return false; \
|
||||
uint32_t left = (uint32_t)AS_NUM(args[0]); \
|
||||
uint32_t right = (uint32_t)AS_NUM(args[1]); \
|
||||
RETURN_NUM(left op right); \
|
||||
#define DEF_NUM_BITWISE(name, op) \
|
||||
DEF_PRIMITIVE(num_bitwise##name) \
|
||||
{ \
|
||||
if (!validateNum(vm, args[1], "Right operand")) return false; \
|
||||
uint32_t left = (uint32_t)AS_NUM(args[0]); \
|
||||
uint32_t right = (uint32_t)AS_NUM(args[1]); \
|
||||
RETURN_NUM(left op right); \
|
||||
}
|
||||
|
||||
DEF_NUM_BITWISE(And, &)
|
||||
@ -633,10 +633,10 @@ DEF_NUM_BITWISE(LeftShift, <<)
|
||||
DEF_NUM_BITWISE(RightShift, >>)
|
||||
|
||||
// Defines a primitive method on Num that returns the result of [fn].
|
||||
#define DEF_NUM_FN(name, fn) \
|
||||
DEF_PRIMITIVE(num_##name) \
|
||||
{ \
|
||||
RETURN_NUM(fn(AS_NUM(args[0]))); \
|
||||
#define DEF_NUM_FN(name, fn) \
|
||||
DEF_PRIMITIVE(num_##name) \
|
||||
{ \
|
||||
RETURN_NUM(fn(AS_NUM(args[0]))); \
|
||||
}
|
||||
|
||||
DEF_NUM_FN(abs, fabs)
|
||||
|
||||
@ -121,9 +121,9 @@ static int dumpInstruction(WrenVM* vm, ObjFn* fn, int i, int* lastLine)
|
||||
#define READ_BYTE() (bytecode[i++])
|
||||
#define READ_SHORT() (i += 2, (bytecode[i - 2] << 8) | bytecode[i - 1])
|
||||
|
||||
#define BYTE_INSTRUCTION(name) \
|
||||
printf("%-16s %5d\n", name, READ_BYTE()); \
|
||||
break; \
|
||||
#define BYTE_INSTRUCTION(name) \
|
||||
printf("%-16s %5d\n", name, READ_BYTE()); \
|
||||
break
|
||||
|
||||
switch (code)
|
||||
{
|
||||
|
||||
@ -5,23 +5,27 @@
|
||||
|
||||
// Binds a primitive method named [name] (in Wren) implemented using C function
|
||||
// [fn] to `ObjClass` [cls].
|
||||
#define PRIMITIVE(cls, name, function) \
|
||||
{ \
|
||||
int symbol = wrenSymbolTableEnsure(vm, \
|
||||
&vm->methodNames, name, strlen(name)); \
|
||||
Method method; \
|
||||
method.type = METHOD_PRIMITIVE; \
|
||||
method.as.primitive = prim_##function; \
|
||||
wrenBindMethod(vm, cls, symbol, method); \
|
||||
}
|
||||
#define PRIMITIVE(cls, name, function) \
|
||||
do { \
|
||||
int symbol = wrenSymbolTableEnsure(vm, \
|
||||
&vm->methodNames, name, strlen(name)); \
|
||||
Method method; \
|
||||
method.type = METHOD_PRIMITIVE; \
|
||||
method.as.primitive = prim_##function; \
|
||||
wrenBindMethod(vm, cls, symbol, method); \
|
||||
} while (false)
|
||||
|
||||
// Defines a primitive method whose C function name is [name]. This abstracts
|
||||
// the actual type signature of a primitive function and makes it clear which C
|
||||
// functions are invoked as primitives.
|
||||
#define DEF_PRIMITIVE(name) \
|
||||
#define DEF_PRIMITIVE(name) \
|
||||
static bool prim_##name(WrenVM* vm, Value* args)
|
||||
|
||||
#define RETURN_VAL(value) do { args[0] = value; return true; } while (0)
|
||||
#define RETURN_VAL(value) \
|
||||
do { \
|
||||
args[0] = value; \
|
||||
return true; \
|
||||
} while (false)
|
||||
|
||||
#define RETURN_OBJ(obj) RETURN_VAL(OBJ_VAL(obj))
|
||||
#define RETURN_BOOL(value) RETURN_VAL(BOOL_VAL(value))
|
||||
@ -30,17 +34,17 @@
|
||||
#define RETURN_NUM(value) RETURN_VAL(NUM_VAL(value))
|
||||
#define RETURN_TRUE RETURN_VAL(TRUE_VAL)
|
||||
|
||||
#define RETURN_ERROR(msg) \
|
||||
do { \
|
||||
vm->fiber->error = wrenNewStringLength(vm, msg, sizeof(msg) - 1); \
|
||||
return false; \
|
||||
} while (0);
|
||||
#define RETURN_ERROR(msg) \
|
||||
do { \
|
||||
vm->fiber->error = wrenNewStringLength(vm, msg, sizeof(msg) - 1); \
|
||||
return false; \
|
||||
} while (false)
|
||||
|
||||
#define RETURN_ERROR_FMT(msg, arg) \
|
||||
do { \
|
||||
vm->fiber->error = wrenStringFormat(vm, msg, arg); \
|
||||
return false; \
|
||||
} while (0);
|
||||
#define RETURN_ERROR_FMT(msg, arg) \
|
||||
do { \
|
||||
vm->fiber->error = wrenStringFormat(vm, msg, arg); \
|
||||
return false; \
|
||||
} while (false)
|
||||
|
||||
// Validates that the given [arg] is a function. Returns true if it is. If not,
|
||||
// reports an error and returns false.
|
||||
|
||||
@ -13,54 +13,54 @@ typedef struct sObjString ObjString;
|
||||
// We need buffers of a few different types. To avoid lots of casting between
|
||||
// void* and back, we'll use the preprocessor as a poor man's generics and let
|
||||
// it generate a few type-specific ones.
|
||||
#define DECLARE_BUFFER(name, type) \
|
||||
typedef struct \
|
||||
{ \
|
||||
type* data; \
|
||||
int count; \
|
||||
int capacity; \
|
||||
} name##Buffer; \
|
||||
void wren##name##BufferInit(name##Buffer* buffer); \
|
||||
void wren##name##BufferClear(WrenVM* vm, name##Buffer* buffer); \
|
||||
void wren##name##BufferFill(WrenVM* vm, name##Buffer* buffer, type data, \
|
||||
int count); \
|
||||
#define DECLARE_BUFFER(name, type) \
|
||||
typedef struct \
|
||||
{ \
|
||||
type* data; \
|
||||
int count; \
|
||||
int capacity; \
|
||||
} name##Buffer; \
|
||||
void wren##name##BufferInit(name##Buffer* buffer); \
|
||||
void wren##name##BufferClear(WrenVM* vm, name##Buffer* buffer); \
|
||||
void wren##name##BufferFill(WrenVM* vm, name##Buffer* buffer, type data, \
|
||||
int count); \
|
||||
void wren##name##BufferWrite(WrenVM* vm, name##Buffer* buffer, type data)
|
||||
|
||||
// This should be used once for each type instantiation, somewhere in a .c file.
|
||||
#define DEFINE_BUFFER(name, type) \
|
||||
void wren##name##BufferInit(name##Buffer* buffer) \
|
||||
{ \
|
||||
buffer->data = NULL; \
|
||||
buffer->capacity = 0; \
|
||||
buffer->count = 0; \
|
||||
} \
|
||||
\
|
||||
void wren##name##BufferClear(WrenVM* vm, name##Buffer* buffer) \
|
||||
{ \
|
||||
wrenReallocate(vm, buffer->data, 0, 0); \
|
||||
wren##name##BufferInit(buffer); \
|
||||
} \
|
||||
\
|
||||
void wren##name##BufferFill(WrenVM* vm, name##Buffer* buffer, type data, \
|
||||
int count) \
|
||||
{ \
|
||||
if (buffer->capacity < buffer->count + count) \
|
||||
{ \
|
||||
int capacity = wrenPowerOf2Ceil(buffer->count + count); \
|
||||
buffer->data = (type*)wrenReallocate(vm, buffer->data, \
|
||||
buffer->capacity * sizeof(type), capacity * sizeof(type)); \
|
||||
buffer->capacity = capacity; \
|
||||
} \
|
||||
\
|
||||
for (int i = 0; i < count; i++) \
|
||||
{ \
|
||||
buffer->data[buffer->count++] = data; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
void wren##name##BufferWrite(WrenVM* vm, name##Buffer* buffer, type data) \
|
||||
{ \
|
||||
wren##name##BufferFill(vm, buffer, data, 1); \
|
||||
#define DEFINE_BUFFER(name, type) \
|
||||
void wren##name##BufferInit(name##Buffer* buffer) \
|
||||
{ \
|
||||
buffer->data = NULL; \
|
||||
buffer->capacity = 0; \
|
||||
buffer->count = 0; \
|
||||
} \
|
||||
\
|
||||
void wren##name##BufferClear(WrenVM* vm, name##Buffer* buffer) \
|
||||
{ \
|
||||
wrenReallocate(vm, buffer->data, 0, 0); \
|
||||
wren##name##BufferInit(buffer); \
|
||||
} \
|
||||
\
|
||||
void wren##name##BufferFill(WrenVM* vm, name##Buffer* buffer, type data, \
|
||||
int count) \
|
||||
{ \
|
||||
if (buffer->capacity < buffer->count + count) \
|
||||
{ \
|
||||
int capacity = wrenPowerOf2Ceil(buffer->count + count); \
|
||||
buffer->data = (type*)wrenReallocate(vm, buffer->data, \
|
||||
buffer->capacity * sizeof(type), capacity * sizeof(type)); \
|
||||
buffer->capacity = capacity; \
|
||||
} \
|
||||
\
|
||||
for (int i = 0; i < count; i++) \
|
||||
{ \
|
||||
buffer->data[buffer->count++] = data; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
void wren##name##BufferWrite(WrenVM* vm, name##Buffer* buffer, type data) \
|
||||
{ \
|
||||
wren##name##BufferFill(vm, buffer, data, 1); \
|
||||
}
|
||||
|
||||
DECLARE_BUFFER(Byte, uint8_t);
|
||||
|
||||
@ -797,36 +797,34 @@ static WrenInterpretResult runInterpreter(WrenVM* vm, register ObjFiber* fiber)
|
||||
|
||||
// Use this after a CallFrame has been pushed or popped to refresh the local
|
||||
// variables.
|
||||
#define LOAD_FRAME() \
|
||||
frame = &fiber->frames[fiber->numFrames - 1]; \
|
||||
stackStart = frame->stackStart; \
|
||||
ip = frame->ip; \
|
||||
fn = frame->closure->fn;
|
||||
#define LOAD_FRAME() \
|
||||
do { \
|
||||
frame = &fiber->frames[fiber->numFrames - 1]; \
|
||||
stackStart = frame->stackStart; \
|
||||
ip = frame->ip; \
|
||||
fn = frame->closure->fn; \
|
||||
} while (false)
|
||||
|
||||
// Terminates the current fiber with error string [error]. If another calling
|
||||
// fiber is willing to catch the error, transfers control to it, otherwise
|
||||
// exits the interpreter.
|
||||
#define RUNTIME_ERROR() \
|
||||
do \
|
||||
{ \
|
||||
STORE_FRAME(); \
|
||||
runtimeError(vm); \
|
||||
if (vm->fiber == NULL) return WREN_RESULT_RUNTIME_ERROR; \
|
||||
fiber = vm->fiber; \
|
||||
LOAD_FRAME(); \
|
||||
DISPATCH(); \
|
||||
} \
|
||||
while (false)
|
||||
#define RUNTIME_ERROR() \
|
||||
do { \
|
||||
STORE_FRAME(); \
|
||||
runtimeError(vm); \
|
||||
if (vm->fiber == NULL) return WREN_RESULT_RUNTIME_ERROR; \
|
||||
fiber = vm->fiber; \
|
||||
LOAD_FRAME(); \
|
||||
DISPATCH(); \
|
||||
} while (false)
|
||||
|
||||
#if WREN_DEBUG_TRACE_INSTRUCTIONS
|
||||
// Prints the stack and instruction before each instruction is executed.
|
||||
#define DEBUG_TRACE_INSTRUCTIONS() \
|
||||
do \
|
||||
{ \
|
||||
wrenDumpStack(fiber); \
|
||||
wrenDumpInstruction(vm, fn, (int)(ip - fn->code.data)); \
|
||||
} \
|
||||
while (false)
|
||||
#define DEBUG_TRACE_INSTRUCTIONS() \
|
||||
do { \
|
||||
wrenDumpStack(fiber); \
|
||||
wrenDumpInstruction(vm, fn, (int)(ip - fn->code.data)); \
|
||||
} while (false)
|
||||
#else
|
||||
#define DEBUG_TRACE_INSTRUCTIONS() do { } while (false)
|
||||
#endif
|
||||
@ -842,19 +840,17 @@ static WrenInterpretResult runInterpreter(WrenVM* vm, register ObjFiber* fiber)
|
||||
#define INTERPRET_LOOP DISPATCH();
|
||||
#define CASE_CODE(name) code_##name
|
||||
|
||||
#define DISPATCH() \
|
||||
do \
|
||||
{ \
|
||||
DEBUG_TRACE_INSTRUCTIONS(); \
|
||||
goto *dispatchTable[instruction = (Code)READ_BYTE()]; \
|
||||
} \
|
||||
while (false)
|
||||
#define DISPATCH() \
|
||||
do { \
|
||||
DEBUG_TRACE_INSTRUCTIONS(); \
|
||||
goto *dispatchTable[instruction = (Code)READ_BYTE()]; \
|
||||
} while (false)
|
||||
|
||||
#else
|
||||
|
||||
#define INTERPRET_LOOP \
|
||||
loop: \
|
||||
DEBUG_TRACE_INSTRUCTIONS(); \
|
||||
#define INTERPRET_LOOP \
|
||||
loop: \
|
||||
DEBUG_TRACE_INSTRUCTIONS(); \
|
||||
switch (instruction = (Code)READ_BYTE())
|
||||
|
||||
#define CASE_CODE(name) case CODE_##name
|
||||
|
||||
Reference in New Issue
Block a user