Merge branch 'master' into constructor-methods

This commit is contained in:
Bob Nystrom
2015-07-19 12:49:23 -07:00
18 changed files with 254 additions and 191 deletions
+42 -30
View File
@@ -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
-1
View File
@@ -2673,7 +2673,6 @@ static int getNumArguments(const uint8_t* bytecode, const Value* constants,
default:
UNREACHABLE();
return 0;
}
}
+10 -18
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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