Merge branch 'master' into constructor-methods
This commit is contained in:
+42
-30
@@ -26,7 +26,7 @@
|
||||
//
|
||||
// Defaults to on.
|
||||
#ifndef WREN_NAN_TAGGING
|
||||
#define WREN_NAN_TAGGING 1
|
||||
#define WREN_NAN_TAGGING 1
|
||||
#endif
|
||||
|
||||
// If true, the VM's interpreter loop uses computed gotos. See this for more:
|
||||
@@ -48,14 +48,14 @@
|
||||
//
|
||||
// Defaults to on.
|
||||
#ifndef WREN_USE_LIB_IO
|
||||
#define WREN_USE_LIB_IO 1
|
||||
#define WREN_USE_LIB_IO 1
|
||||
#endif
|
||||
|
||||
// If true, loads the "Meta" class in the standard library.
|
||||
//
|
||||
// Defaults to on.
|
||||
#ifndef WREN_USE_LIB_META
|
||||
#define WREN_USE_LIB_META 1
|
||||
#define WREN_USE_LIB_META 1
|
||||
#endif
|
||||
|
||||
// These flags are useful for debugging and hacking on Wren itself. They are not
|
||||
@@ -136,18 +136,18 @@
|
||||
// The Microsoft compiler does not support the "inline" modifier when compiling
|
||||
// as plain C.
|
||||
#if defined( _MSC_VER ) && !defined(__cplusplus)
|
||||
#define inline _inline
|
||||
#define inline _inline
|
||||
#endif
|
||||
|
||||
// This is used to clearly mark flexible-sized arrays that appear at the end of
|
||||
// some dynamically-allocated structs, known as the "struct hack".
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
// In C99, a flexible array member is just "[]".
|
||||
#define FLEXIBLE_ARRAY
|
||||
// In C99, a flexible array member is just "[]".
|
||||
#define FLEXIBLE_ARRAY
|
||||
#else
|
||||
// Elsewhere, use a zero-sized array. It's technically undefined behavior, but
|
||||
// works reliably in most known compilers.
|
||||
#define FLEXIBLE_ARRAY 0
|
||||
// Elsewhere, use a zero-sized array. It's technically undefined behavior,
|
||||
// but works reliably in most known compilers.
|
||||
#define FLEXIBLE_ARRAY 0
|
||||
#endif
|
||||
|
||||
// Assertions are used to validate program invariants. They indicate things the
|
||||
@@ -157,34 +157,46 @@
|
||||
// Assertions add significant overhead, so are only enabled in debug builds.
|
||||
#ifdef DEBUG
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define ASSERT(condition, message) \
|
||||
do \
|
||||
{ \
|
||||
if (!(condition)) \
|
||||
#define ASSERT(condition, message) \
|
||||
do \
|
||||
{ \
|
||||
fprintf(stderr, "[%s:%d] Assert failed in %s(): %s\n", \
|
||||
__FILE__, __LINE__, __func__, message); \
|
||||
if (!(condition)) \
|
||||
{ \
|
||||
fprintf(stderr, "[%s:%d] Assert failed in %s(): %s\n", \
|
||||
__FILE__, __LINE__, __func__, message); \
|
||||
abort(); \
|
||||
} \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
// 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.
|
||||
//
|
||||
// In release mode, we use compiler-specific built in functions to tell the
|
||||
// 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)
|
||||
|
||||
// Assertion to indicate that the given point in the code should never be
|
||||
// reached.
|
||||
#define UNREACHABLE() \
|
||||
do \
|
||||
{ \
|
||||
fprintf(stderr, "This line should not be reached.\n"); \
|
||||
abort(); \
|
||||
} \
|
||||
while (0)
|
||||
while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define ASSERT(condition, message) do { } while (0)
|
||||
#define UNREACHABLE() do { } while (0)
|
||||
#define ASSERT(condition, message) do {} while (0)
|
||||
|
||||
// Tell the compiler that this part of the code will never be reached.
|
||||
#if defined( _MSC_VER )
|
||||
#define UNREACHABLE() __assume(0)
|
||||
#else
|
||||
#define UNREACHABLE() __builtin_unreachable()
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -2673,7 +2673,6 @@ static int getNumArguments(const uint8_t* bytecode, const Value* constants,
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-18
@@ -9,15 +9,7 @@ void wrenDebugPrintStackTrace(ObjFiber* fiber)
|
||||
for (int i = fiber->numFrames - 1; i >= 0; i--)
|
||||
{
|
||||
CallFrame* frame = &fiber->frames[i];
|
||||
ObjFn* fn;
|
||||
if (frame->fn->type == OBJ_FN)
|
||||
{
|
||||
fn = (ObjFn*)frame->fn;
|
||||
}
|
||||
else
|
||||
{
|
||||
fn = ((ObjClosure*)frame->fn)->fn;
|
||||
}
|
||||
ObjFn* fn = wrenGetFrameFunction(frame);
|
||||
|
||||
// Built-in libraries and method call stubs have no source path and are
|
||||
// explicitly omitted from stack traces since we don't want to highlight to
|
||||
@@ -70,21 +62,21 @@ void wrenDumpValue(Value value)
|
||||
{
|
||||
switch (GET_TAG(value))
|
||||
{
|
||||
case TAG_FALSE: printf("false"); break;
|
||||
case TAG_NAN: printf("NaN"); break;
|
||||
case TAG_NULL: printf("null"); break;
|
||||
case TAG_TRUE: printf("true"); break;
|
||||
case TAG_FALSE: printf("false"); break;
|
||||
case TAG_NAN: printf("NaN"); break;
|
||||
case TAG_NULL: printf("null"); break;
|
||||
case TAG_TRUE: printf("true"); break;
|
||||
case TAG_UNDEFINED: UNREACHABLE();
|
||||
}
|
||||
}
|
||||
#else
|
||||
switch (value.type)
|
||||
{
|
||||
case VAL_FALSE: printf("false"); break;
|
||||
case VAL_NULL: printf("null"); break;
|
||||
case VAL_NUM: printf("%.14g", AS_NUM(value)); break;
|
||||
case VAL_TRUE: printf("true"); break;
|
||||
case VAL_OBJ: printObject(AS_OBJ(value)); break;
|
||||
case VAL_FALSE: printf("false"); break;
|
||||
case VAL_NULL: printf("null"); break;
|
||||
case VAL_NUM: printf("%.14g", AS_NUM(value)); break;
|
||||
case VAL_TRUE: printf("true"); break;
|
||||
case VAL_OBJ: dumpObject(AS_OBJ(value)); break;
|
||||
case VAL_UNDEFINED: UNREACHABLE();
|
||||
}
|
||||
#endif
|
||||
|
||||
+31
-30
@@ -6,111 +6,111 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
// TODO: This is an arbitrary limit Do something smarter.
|
||||
// TODO: This is an arbitrary limit. Do something smarter.
|
||||
#define MAX_READ_LEN 1024
|
||||
|
||||
// This string literal is generated automatically from io.wren. Do not edit.
|
||||
static const char* ioLibSource =
|
||||
"class IO {\n"
|
||||
" static print {\n"
|
||||
" IO.writeString_(\"\n\")\n"
|
||||
" writeString_(\"\n\")\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(obj) {\n"
|
||||
" IO.writeObject_(obj)\n"
|
||||
" IO.writeString_(\"\n\")\n"
|
||||
" writeObject_(obj)\n"
|
||||
" writeString_(\"\n\")\n"
|
||||
" return obj\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(a1, a2) {\n"
|
||||
" printList_([a1, a2])\n"
|
||||
" printAll([a1, a2])\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(a1, a2, a3) {\n"
|
||||
" printList_([a1, a2, a3])\n"
|
||||
" printAll([a1, a2, a3])\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(a1, a2, a3, a4) {\n"
|
||||
" printList_([a1, a2, a3, a4])\n"
|
||||
" printAll([a1, a2, a3, a4])\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(a1, a2, a3, a4, a5) {\n"
|
||||
" printList_([a1, a2, a3, a4, a5])\n"
|
||||
" printAll([a1, a2, a3, a4, a5])\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(a1, a2, a3, a4, a5, a6) {\n"
|
||||
" printList_([a1, a2, a3, a4, a5, a6])\n"
|
||||
" printAll([a1, a2, a3, a4, a5, a6])\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(a1, a2, a3, a4, a5, a6, a7) {\n"
|
||||
" printList_([a1, a2, a3, a4, a5, a6, a7])\n"
|
||||
" printAll([a1, a2, a3, a4, a5, a6, a7])\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(a1, a2, a3, a4, a5, a6, a7, a8) {\n"
|
||||
" printList_([a1, a2, a3, a4, a5, a6, a7, a8])\n"
|
||||
" printAll([a1, a2, a3, a4, a5, a6, a7, a8])\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9) {\n"
|
||||
" printList_([a1, a2, a3, a4, a5, a6, a7, a8, a9])\n"
|
||||
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9])\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {\n"
|
||||
" printList_([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10])\n"
|
||||
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10])\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) {\n"
|
||||
" printList_([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11])\n"
|
||||
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11])\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) {\n"
|
||||
" printList_([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12])\n"
|
||||
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12])\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) {\n"
|
||||
" printList_([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13])\n"
|
||||
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13])\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) {\n"
|
||||
" printList_([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14])\n"
|
||||
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14])\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) {\n"
|
||||
" printList_([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15])\n"
|
||||
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15])\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) {\n"
|
||||
" printList_([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16])\n"
|
||||
" printAll([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16])\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static printList_(objects) {\n"
|
||||
" for (object in objects) IO.writeObject_(object)\n"
|
||||
" IO.writeString_(\"\n\")\n"
|
||||
" static printAll(sequence) {\n"
|
||||
" for (object in sequence) writeObject_(object)\n"
|
||||
" writeString_(\"\n\")\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static write(obj) {\n"
|
||||
" IO.writeObject_(obj)\n"
|
||||
" writeObject_(obj)\n"
|
||||
" return obj\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static read(prompt) {\n"
|
||||
" if (!(prompt is String)) Fiber.abort(\"Prompt must be a string.\")\n"
|
||||
" IO.write(prompt)\n"
|
||||
" return IO.read\n"
|
||||
" write(prompt)\n"
|
||||
" return read()\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static writeObject_(obj) {\n"
|
||||
" var string = obj.toString\n"
|
||||
" if (string is String) {\n"
|
||||
" IO.writeString_(string)\n"
|
||||
" writeString_(string)\n"
|
||||
" } else {\n"
|
||||
" IO.writeString_(\"[invalid toString]\")\n"
|
||||
" writeString_(\"[invalid toString]\")\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" foreign static writeString_(string)\n"
|
||||
" foreign static clock\n"
|
||||
" foreign static time\n"
|
||||
" foreign static read\n"
|
||||
" foreign static read()\n"
|
||||
"}\n";
|
||||
|
||||
static void ioWriteString(WrenVM* vm)
|
||||
@@ -125,7 +125,8 @@ static void ioRead(WrenVM* vm)
|
||||
char buffer[MAX_READ_LEN];
|
||||
char* result = fgets(buffer, MAX_READ_LEN, stdin);
|
||||
|
||||
if (result != NULL) {
|
||||
if (result != NULL)
|
||||
{
|
||||
wrenReturnString(vm, buffer, (int)strlen(buffer));
|
||||
}
|
||||
}
|
||||
@@ -153,7 +154,7 @@ WrenForeignMethodFn wrenBindIOForeignMethod(WrenVM* vm, const char* className,
|
||||
if (strcmp(signature, "writeString_(_)") == 0) return ioWriteString;
|
||||
if (strcmp(signature, "clock") == 0) return ioClock;
|
||||
if (strcmp(signature, "time") == 0) return ioTime;
|
||||
if (strcmp(signature, "read") == 0) return ioRead;
|
||||
if (strcmp(signature, "read()") == 0) return ioRead;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
+5
-7
@@ -359,13 +359,11 @@ static uint32_t hashValue(Value value)
|
||||
switch (value.type)
|
||||
{
|
||||
case VAL_FALSE: return 0;
|
||||
case VAL_NULL: return 1;
|
||||
case VAL_NUM: return hashNumber(AS_NUM(value));
|
||||
case VAL_TRUE: return 2;
|
||||
case VAL_OBJ: return hashObject(AS_OBJ(value));
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
case VAL_NULL: return 1;
|
||||
case VAL_NUM: return hashNumber(AS_NUM(value));
|
||||
case VAL_TRUE: return 2;
|
||||
case VAL_OBJ: return hashObject(AS_OBJ(value));
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
+15
-12
@@ -586,10 +586,10 @@ typedef struct
|
||||
#define IS_UNDEFINED(value) ((value).type == VAL_UNDEFINED)
|
||||
|
||||
// Singleton values.
|
||||
#define FALSE_VAL ((Value){ VAL_FALSE })
|
||||
#define NULL_VAL ((Value){ VAL_NULL })
|
||||
#define TRUE_VAL ((Value){ VAL_TRUE })
|
||||
#define UNDEFINED_VAL ((Value){ VAL_UNDEFINED })
|
||||
#define FALSE_VAL ((Value){ VAL_FALSE, { 0 } })
|
||||
#define NULL_VAL ((Value){ VAL_NULL, { 0 } })
|
||||
#define TRUE_VAL ((Value){ VAL_TRUE, { 0 } })
|
||||
#define UNDEFINED_VAL ((Value){ VAL_UNDEFINED, { 0 } })
|
||||
|
||||
#endif
|
||||
|
||||
@@ -628,6 +628,16 @@ ObjFiber* wrenNewFiber(WrenVM* vm, Obj* fn);
|
||||
// Resets [fiber] back to an initial state where it is ready to invoke [fn].
|
||||
void wrenResetFiber(WrenVM* vm, ObjFiber* fiber, Obj* fn);
|
||||
|
||||
static inline ObjFn* wrenGetFrameFunction(CallFrame* frame)
|
||||
{
|
||||
switch (frame->fn->type)
|
||||
{
|
||||
case OBJ_FN: return (ObjFn*)frame->fn;
|
||||
case OBJ_CLOSURE: return ((ObjClosure*)frame->fn)->fn;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
// Adds a new [CallFrame] to [fiber] invoking [function] whose stack starts at
|
||||
// [stackStart].
|
||||
static inline void wrenAppendCallFrame(WrenVM* vm, ObjFiber* fiber,
|
||||
@@ -639,14 +649,7 @@ static inline void wrenAppendCallFrame(WrenVM* vm, ObjFiber* fiber,
|
||||
CallFrame* frame = &fiber->frames[fiber->numFrames++];
|
||||
frame->stackStart = stackStart;
|
||||
frame->fn = function;
|
||||
if (function->type == OBJ_FN)
|
||||
{
|
||||
frame->ip = ((ObjFn*)function)->bytecode;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame->ip = ((ObjClosure*)function)->fn->bytecode;
|
||||
}
|
||||
frame->ip = wrenGetFrameFunction(frame)->bytecode;
|
||||
}
|
||||
|
||||
// TODO: The argument list here is getting a bit gratuitous.
|
||||
|
||||
+1
-9
@@ -613,14 +613,7 @@ static WrenInterpretResult runInterpreter(WrenVM* vm, register ObjFiber* fiber)
|
||||
frame = &fiber->frames[fiber->numFrames - 1]; \
|
||||
stackStart = frame->stackStart; \
|
||||
ip = frame->ip; \
|
||||
if (frame->fn->type == OBJ_FN) \
|
||||
{ \
|
||||
fn = (ObjFn*)frame->fn; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
fn = ((ObjClosure*)frame->fn)->fn; \
|
||||
}
|
||||
fn = wrenGetFrameFunction(frame);
|
||||
|
||||
// Terminates the current fiber with error string [error]. If another calling
|
||||
// fiber is willing to catch the error, transfers control to it, otherwise
|
||||
@@ -1164,7 +1157,6 @@ static WrenInterpretResult runInterpreter(WrenVM* vm, register ObjFiber* fiber)
|
||||
// We should only exit this function from an explicit return from CODE_RETURN
|
||||
// or a runtime error.
|
||||
UNREACHABLE();
|
||||
return WREN_RESULT_RUNTIME_ERROR;
|
||||
|
||||
#undef READ_BYTE
|
||||
#undef READ_SHORT
|
||||
|
||||
+9
-10
@@ -195,26 +195,25 @@ static inline ObjClass* wrenGetClassInline(WrenVM* vm, Value value)
|
||||
#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_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_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
|
||||
|
||||
Reference in New Issue
Block a user