Merge pull request #751 from wren-lang/0.3.0-refactor

0.3.0 refactor
This commit is contained in:
ruby
2020-06-05 14:57:20 -07:00
committed by GitHub
parent 6ab4abe9e3
commit d585a080e8
476 changed files with 13159 additions and 93444 deletions

View File

@ -1,29 +1,8 @@
#include <stdio.h>
#include <string.h>
#include "./api_tests.h"
#include "vm.h"
#include "wren.h"
static const char* testName = NULL;
#include "benchmark.h"
#include "call.h"
#include "call_calls_foreign.h"
#include "call_wren_call_root.h"
#include "error.h"
#include "get_variable.h"
#include "foreign_class.h"
#include "handle.h"
#include "lists.h"
#include "new_vm.h"
#include "reset_stack_after_call_abort.h"
#include "reset_stack_after_foreign_construct.h"
#include "resolution.h"
#include "slots.h"
#include "user_data.h"
// The name of the currently executing API test.
const char* testName;
static WrenForeignMethodFn bindForeignMethod(
WrenForeignMethodFn APITest_bindForeignMethod(
WrenVM* vm, const char* module, const char* className,
bool isStatic, const char* signature)
{
@ -37,15 +16,15 @@ static WrenForeignMethodFn bindForeignMethod(
strcat(fullName, className);
strcat(fullName, ".");
strcat(fullName, signature);
WrenForeignMethodFn method = NULL;
method = benchmarkBindMethod(fullName);
if (method != NULL) return method;
method = callCallsForeignBindMethod(fullName);
if (method != NULL) return method;
method = errorBindMethod(fullName);
if (method != NULL) return method;
@ -54,22 +33,22 @@ static WrenForeignMethodFn bindForeignMethod(
method = foreignClassBindMethod(fullName);
if (method != NULL) return method;
method = handleBindMethod(fullName);
if (method != NULL) return method;
method = listsBindMethod(fullName);
if (method != NULL) return method;
method = newVMBindMethod(fullName);
if (method != NULL) return method;
method = resolutionBindMethod(fullName);
if (method != NULL) return method;
method = slotsBindMethod(fullName);
if (method != NULL) return method;
method = userDataBindMethod(fullName);
if (method != NULL) return method;
@ -79,61 +58,50 @@ static WrenForeignMethodFn bindForeignMethod(
return NULL;
}
static WrenForeignClassMethods bindForeignClass(
WrenForeignClassMethods APITest_bindForeignClass(
WrenVM* vm, const char* module, const char* className)
{
WrenForeignClassMethods methods = { NULL, NULL };
if (strncmp(module, "./test/", 7) != 0) return methods;
if (strncmp(module, "./test/api", 7) != 0) return methods;
foreignClassBindClass(className, &methods);
if (methods.allocate != NULL) return methods;
resetStackAfterForeignConstructBindClass(className, &methods);
if (methods.allocate != NULL) return methods;
slotsBindClass(className, &methods);
if (methods.allocate != NULL) return methods;
fprintf(stderr,
"Unknown foreign class '%s' for test '%s'\n", className, testName);
exit(1);
return methods;
}
static void afterLoad(WrenVM* vm)
int APITest_Run(WrenVM* vm, const char* inTestName)
{
if (strstr(testName, "/call.wren") != NULL)
testName = inTestName;
if (strstr(inTestName, "/call.wren") != NULL)
{
callRunTests(vm);
return callRunTests(vm);
}
else if (strstr(testName, "/call_calls_foreign.wren") != NULL)
else if (strstr(inTestName, "/call_calls_foreign.wren") != NULL)
{
callCallsForeignRunTests(vm);
return callCallsForeignRunTests(vm);
}
else if (strstr(testName, "/call_wren_call_root.wren") != NULL)
else if (strstr(inTestName, "/call_wren_call_root.wren") != NULL)
{
callWrenCallRootRunTests(vm);
return callWrenCallRootRunTests(vm);
}
else if (strstr(testName, "/reset_stack_after_call_abort.wren") != NULL)
else if (strstr(inTestName, "/reset_stack_after_call_abort.wren") != NULL)
{
resetStackAfterCallAbortRunTests(vm);
return resetStackAfterCallAbortRunTests(vm);
}
else if (strstr(testName, "/reset_stack_after_foreign_construct.wren") != NULL)
else if (strstr(inTestName, "/reset_stack_after_foreign_construct.wren") != NULL)
{
resetStackAfterForeignConstructRunTests(vm);
}
}
int main(int argc, const char* argv[])
{
if (argc != 2)
{
fprintf(stderr, "Usage: wren <test>\n");
return 64; // EX_USAGE.
return resetStackAfterForeignConstructRunTests(vm);
}
testName = argv[1];
setTestCallbacks(bindForeignMethod, bindForeignClass, afterLoad);
runFile(testName);
return getExitCode();
return 0;
}

36
test/api/api_tests.h Normal file
View File

@ -0,0 +1,36 @@
#pragma once
#ifndef WREN_API_TESTS_H
#define WREN_API_TESTS_H
#include <stdio.h>
#include <string.h>
#include "wren.h"
#include "benchmark.h"
#include "call.h"
#include "call_calls_foreign.h"
#include "call_wren_call_root.h"
#include "error.h"
#include "get_variable.h"
#include "foreign_class.h"
#include "handle.h"
#include "lists.h"
#include "new_vm.h"
#include "reset_stack_after_call_abort.h"
#include "reset_stack_after_foreign_construct.h"
#include "resolution.h"
#include "slots.h"
#include "user_data.h"
int APITest_Run(WrenVM* vm, const char* inTestName);
WrenForeignMethodFn APITest_bindForeignMethod(
WrenVM* vm, const char* module, const char* className,
bool isStatic, const char* signature);
WrenForeignClassMethods APITest_bindForeignClass(
WrenVM* vm, const char* module, const char* className);
#endif //WREN_API_TESTS_H

View File

@ -23,23 +23,23 @@ const char* testScript =
static void call(WrenVM* vm)
{
int iterations = (int)wrenGetSlotDouble(vm, 1);
// Since the VM is not re-entrant, we can't call from within this foreign
// method. Instead, make a new VM to run the call test in.
WrenConfiguration config;
wrenInitConfiguration(&config);
WrenVM* otherVM = wrenNewVM(&config);
wrenInterpret(otherVM, "main", testScript);
WrenHandle* method = wrenMakeCallHandle(otherVM, "method(_,_,_,_)");
wrenEnsureSlots(otherVM, 1);
wrenGetVariable(otherVM, "main", "Test", 0);
WrenHandle* testClass = wrenGetSlotHandle(otherVM, 0);
double startTime = (double)clock() / CLOCKS_PER_SEC;
double result = 0;
for (int i = 0; i < iterations; i++)
{
@ -49,18 +49,18 @@ static void call(WrenVM* vm)
wrenSetSlotDouble(otherVM, 2, 2.0);
wrenSetSlotDouble(otherVM, 3, 3.0);
wrenSetSlotDouble(otherVM, 4, 4.0);
wrenCall(otherVM, method);
result += wrenGetSlotDouble(otherVM, 0);
}
double elapsed = (double)clock() / CLOCKS_PER_SEC - startTime;
wrenReleaseHandle(otherVM, testClass);
wrenReleaseHandle(otherVM, method);
wrenFreeVM(otherVM);
if (result == (1.0 + 2.0 + 3.0 + 4.0) * iterations)
{
wrenSetSlotDouble(vm, 0, elapsed);

View File

@ -1,14 +1,14 @@
#include <stdio.h>
#include <string.h>
#include "call.h"
#include "vm.h"
void callRunTests(WrenVM* vm)
int callRunTests(WrenVM* vm)
{
wrenEnsureSlots(vm, 1);
wrenGetVariable(vm, "./test/api/call", "Call", 0);
WrenHandle* callClass = wrenGetSlotHandle(vm, 0);
WrenHandle* noParams = wrenMakeCallHandle(vm, "noParams");
WrenHandle* zero = wrenMakeCallHandle(vm, "zero()");
WrenHandle* one = wrenMakeCallHandle(vm, "one(_)");
@ -22,22 +22,22 @@ void callRunTests(WrenVM* vm)
wrenEnsureSlots(vm, 1);
wrenSetSlotHandle(vm, 0, callClass);
wrenCall(vm, noParams);
wrenEnsureSlots(vm, 1);
wrenSetSlotHandle(vm, 0, callClass);
wrenCall(vm, zero);
wrenEnsureSlots(vm, 2);
wrenSetSlotHandle(vm, 0, callClass);
wrenSetSlotDouble(vm, 1, 1.0);
wrenCall(vm, one);
wrenEnsureSlots(vm, 3);
wrenSetSlotHandle(vm, 0, callClass);
wrenSetSlotDouble(vm, 1, 1.0);
wrenSetSlotDouble(vm, 2, 2.0);
wrenCall(vm, two);
// Operators.
wrenEnsureSlots(vm, 1);
wrenSetSlotHandle(vm, 0, callClass);
@ -47,13 +47,13 @@ void callRunTests(WrenVM* vm)
wrenSetSlotHandle(vm, 0, callClass);
wrenSetSlotDouble(vm, 1, 1.0);
wrenCall(vm, binary);
wrenEnsureSlots(vm, 3);
wrenSetSlotHandle(vm, 0, callClass);
wrenSetSlotDouble(vm, 1, 1.0);
wrenSetSlotDouble(vm, 2, 2.0);
wrenCall(vm, subscript);
wrenEnsureSlots(vm, 4);
wrenSetSlotHandle(vm, 0, callClass);
wrenSetSlotDouble(vm, 1, 1.0);
@ -68,7 +68,7 @@ void callRunTests(WrenVM* vm)
wrenCall(vm, getValue);
printf("slots after call: %d\n", wrenGetSlotCount(vm));
WrenHandle* value = wrenGetSlotHandle(vm, 0);
// Different argument types.
wrenEnsureSlots(vm, 3);
wrenSetSlotHandle(vm, 0, callClass);
@ -81,26 +81,26 @@ void callRunTests(WrenVM* vm)
wrenSetSlotDouble(vm, 1, 1.2);
wrenSetSlotDouble(vm, 2, 3.4);
wrenCall(vm, two);
wrenEnsureSlots(vm, 3);
wrenSetSlotHandle(vm, 0, callClass);
wrenSetSlotString(vm, 1, "string");
wrenSetSlotString(vm, 2, "another");
wrenCall(vm, two);
wrenEnsureSlots(vm, 3);
wrenSetSlotHandle(vm, 0, callClass);
wrenSetSlotNull(vm, 1);
wrenSetSlotHandle(vm, 2, value);
wrenCall(vm, two);
// Truncate a string, or allow null bytes.
wrenEnsureSlots(vm, 3);
wrenSetSlotHandle(vm, 0, callClass);
wrenSetSlotBytes(vm, 1, "string", 3);
wrenSetSlotBytes(vm, 2, "b\0y\0t\0e", 7);
wrenCall(vm, two);
// Call ignores with extra temporary slots on stack.
wrenEnsureSlots(vm, 10);
wrenSetSlotHandle(vm, 0, callClass);
@ -109,7 +109,7 @@ void callRunTests(WrenVM* vm)
wrenSetSlotDouble(vm, i, i * 0.1);
}
wrenCall(vm, one);
wrenReleaseHandle(vm, callClass);
wrenReleaseHandle(vm, noParams);
wrenReleaseHandle(vm, zero);
@ -121,4 +121,6 @@ void callRunTests(WrenVM* vm)
wrenReleaseHandle(vm, binary);
wrenReleaseHandle(vm, subscript);
wrenReleaseHandle(vm, subscriptSet);
return 0;
}

View File

@ -1,3 +1,3 @@
#include "wren.h"
void callRunTests(WrenVM* vm);
int callRunTests(WrenVM* vm);

View File

@ -7,7 +7,7 @@ static void api(WrenVM *vm) {
// Grow the slot array. This should trigger the stack to be moved.
wrenEnsureSlots(vm, 10);
wrenSetSlotNewList(vm, 0);
for (int i = 1; i < 10; i++)
{
wrenSetSlotDouble(vm, i, i);
@ -18,27 +18,28 @@ static void api(WrenVM *vm) {
WrenForeignMethodFn callCallsForeignBindMethod(const char* signature)
{
if (strcmp(signature, "static CallCallsForeign.api()") == 0) return api;
return NULL;
}
void callCallsForeignRunTests(WrenVM* vm)
int callCallsForeignRunTests(WrenVM* vm)
{
wrenEnsureSlots(vm, 1);
wrenGetVariable(vm, "./test/api/call_calls_foreign", "CallCallsForeign", 0);
WrenHandle* apiClass = wrenGetSlotHandle(vm, 0);
WrenHandle *call = wrenMakeCallHandle(vm, "call(_)");
wrenEnsureSlots(vm, 2);
wrenSetSlotHandle(vm, 0, apiClass);
wrenSetSlotString(vm, 1, "parameter");
printf("slots before %d\n", wrenGetSlotCount(vm));
wrenCall(vm, call);
// We should have a single slot count for the return.
printf("slots after %d\n", wrenGetSlotCount(vm));
wrenReleaseHandle(vm, call);
wrenReleaseHandle(vm, apiClass);
return 0;
}

View File

@ -1,4 +1,4 @@
#include "wren.h"
WrenForeignMethodFn callCallsForeignBindMethod(const char* signature);
void callCallsForeignRunTests(WrenVM* vm);
int callCallsForeignRunTests(WrenVM* vm);

View File

@ -2,10 +2,10 @@
#include <string.h>
#include "wren.h"
#include "vm.h"
void callWrenCallRootRunTests(WrenVM* vm)
int callWrenCallRootRunTests(WrenVM* vm)
{
int exitCode = 0;
wrenEnsureSlots(vm, 1);
wrenGetVariable(vm, "./test/api/call_wren_call_root", "Test", 0);
WrenHandle* testClass = wrenGetSlotHandle(vm, 0);
@ -17,7 +17,7 @@ void callWrenCallRootRunTests(WrenVM* vm)
WrenInterpretResult result = wrenCall(vm, run);
if (result == WREN_RESULT_RUNTIME_ERROR)
{
setExitCode(70);
exitCode = 70;
}
else
{
@ -26,4 +26,5 @@ void callWrenCallRootRunTests(WrenVM* vm)
wrenReleaseHandle(vm, testClass);
wrenReleaseHandle(vm, run);
return exitCode;
}

View File

@ -1,3 +1,3 @@
#include "wren.h"
void callWrenCallRootRunTests(WrenVM* vm);
int callWrenCallRootRunTests(WrenVM* vm);

View File

@ -78,7 +78,7 @@ static void resourceFinalize(void* data)
// Make sure we get the right data back.
int* value = (int*)data;
if (*value != 123) exit(1);
finalized++;
}

View File

@ -21,7 +21,7 @@ static void otherSlot(WrenVM* vm)
{
wrenEnsureSlots(vm, 3);
wrenGetVariable(vm, "./test/api/get_variable", "B", 2);
// Move it into return position.
const char* string = wrenGetSlotString(vm, 2);
wrenSetSlotString(vm, 0, string);

View File

@ -18,19 +18,19 @@ static void insertNumber(WrenVM* vm, int index, double value)
static void insert(WrenVM* vm)
{
wrenSetSlotNewList(vm, 0);
wrenEnsureSlots(vm, 2);
// Appending.
insertNumber(vm, 0, 1.0);
insertNumber(vm, 1, 2.0);
insertNumber(vm, 2, 3.0);
// Inserting.
insertNumber(vm, 0, 4.0);
insertNumber(vm, 1, 5.0);
insertNumber(vm, 2, 6.0);
// Negative indexes.
insertNumber(vm, -1, 7.0);
insertNumber(vm, -2, 8.0);

View File

@ -5,11 +5,11 @@
static void nullConfig(WrenVM* vm)
{
WrenVM* otherVM = wrenNewVM(NULL);
// We should be able to execute code.
WrenInterpretResult result = wrenInterpret(otherVM, "main", "1 + 2");
wrenSetSlotBool(vm, 0, result == WREN_RESULT_SUCCESS);
wrenFreeVM(otherVM);
}

View File

@ -3,15 +3,15 @@
#include "wren.h"
void resetStackAfterCallAbortRunTests(WrenVM* vm)
int resetStackAfterCallAbortRunTests(WrenVM* vm)
{
wrenEnsureSlots(vm, 1);
wrenGetVariable(vm, "./test/api/reset_stack_after_call_abort", "Test", 0);
WrenHandle* testClass = wrenGetSlotHandle(vm, 0);
WrenHandle* abortFiber = wrenMakeCallHandle(vm, "abortFiber()");
WrenHandle* afterAbort = wrenMakeCallHandle(vm, "afterAbort(_,_)");
wrenEnsureSlots(vm, 1);
wrenSetSlotHandle(vm, 0, testClass);
wrenCall(vm, abortFiber);
@ -21,8 +21,9 @@ void resetStackAfterCallAbortRunTests(WrenVM* vm)
wrenSetSlotDouble(vm, 1, 1.0);
wrenSetSlotDouble(vm, 2, 2.0);
wrenCall(vm, afterAbort);
wrenReleaseHandle(vm, testClass);
wrenReleaseHandle(vm, abortFiber);
wrenReleaseHandle(vm, afterAbort);
return 0;
}

View File

@ -1,3 +1,3 @@
#include "wren.h"
void resetStackAfterCallAbortRunTests(WrenVM* vm);
int resetStackAfterCallAbortRunTests(WrenVM* vm);

View File

@ -19,16 +19,16 @@ void resetStackAfterForeignConstructBindClass(
}
}
void resetStackAfterForeignConstructRunTests(WrenVM* vm)
int resetStackAfterForeignConstructRunTests(WrenVM* vm)
{
wrenEnsureSlots(vm, 1);
wrenGetVariable(vm,
"./test/api/reset_stack_after_foreign_construct", "Test", 0);
WrenHandle* testClass = wrenGetSlotHandle(vm, 0);
WrenHandle* callConstruct = wrenMakeCallHandle(vm, "callConstruct()");
WrenHandle* afterConstruct = wrenMakeCallHandle(vm, "afterConstruct(_,_)");
wrenEnsureSlots(vm, 1);
wrenSetSlotHandle(vm, 0, testClass);
wrenCall(vm, callConstruct);
@ -38,8 +38,10 @@ void resetStackAfterForeignConstructRunTests(WrenVM* vm)
wrenSetSlotDouble(vm, 1, 1.0);
wrenSetSlotDouble(vm, 2, 2.0);
wrenCall(vm, afterConstruct);
wrenReleaseHandle(vm, testClass);
wrenReleaseHandle(vm, callConstruct);
wrenReleaseHandle(vm, afterConstruct);
return 0;
}

View File

@ -2,4 +2,4 @@
void resetStackAfterForeignConstructBindClass(
const char* className, WrenForeignClassMethods* methods);
void resetStackAfterForeignConstructRunTests(WrenVM* vm);
int resetStackAfterForeignConstructRunTests(WrenVM* vm);

View File

@ -17,7 +17,7 @@ static void reportError(WrenVM* vm, WrenErrorType type,
static char* loadModule(WrenVM* vm, const char* module)
{
printf("loading %s\n", module);
const char* source;
if (strcmp(module, "main/baz/bang") == 0)
{
@ -27,7 +27,7 @@ static char* loadModule(WrenVM* vm, const char* module)
{
source = "System.print(\"ok\")";
}
char* string = (char*)malloc(strlen(source) + 1);
strcpy(string, source);
return string;
@ -39,9 +39,9 @@ static void runTestVM(WrenVM* vm, WrenConfiguration* configuration,
configuration->writeFn = write;
configuration->errorFn = reportError;
configuration->loadModuleFn = loadModule;
WrenVM* otherVM = wrenNewVM(configuration);
// We should be able to execute code.
WrenInterpretResult result = wrenInterpret(otherVM, "main", source);
if (result != WREN_RESULT_SUCCESS)
@ -52,7 +52,7 @@ static void runTestVM(WrenVM* vm, WrenConfiguration* configuration,
{
wrenSetSlotString(vm, 0, "success");
}
wrenFreeVM(otherVM);
}
@ -60,14 +60,14 @@ static void noResolver(WrenVM* vm)
{
WrenConfiguration configuration;
wrenInitConfiguration(&configuration);
// Should default to no resolution function.
if (configuration.resolveModuleFn != NULL)
{
wrenSetSlotString(vm, 0, "Did not have null resolve function.");
return;
}
runTestVM(vm, &configuration, "import \"foo/bar\"");
}
@ -81,7 +81,7 @@ static void returnsNull(WrenVM* vm)
{
WrenConfiguration configuration;
wrenInitConfiguration(&configuration);
configuration.resolveModuleFn = resolveToNull;
runTestVM(vm, &configuration, "import \"foo/bar\"");
}
@ -95,13 +95,13 @@ static const char* resolveChange(WrenVM* vm, const char* importer,
strcpy(result, importer);
strcat(result, "/");
strcat(result, name);
// Replace "|" with "/".
for (size_t i = 0; i < length; i++)
{
if (result[i] == '|') result[i] = '/';
}
return result;
}
@ -109,7 +109,7 @@ static void changesString(WrenVM* vm)
{
WrenConfiguration configuration;
wrenInitConfiguration(&configuration);
configuration.resolveModuleFn = resolveChange;
runTestVM(vm, &configuration, "import \"foo|bar\"");
}
@ -118,7 +118,7 @@ static void shared(WrenVM* vm)
{
WrenConfiguration configuration;
wrenInitConfiguration(&configuration);
configuration.resolveModuleFn = resolveChange;
runTestVM(vm, &configuration, "import \"foo|bar\"\nimport \"foo/bar\"");
}
@ -127,7 +127,7 @@ static void importer(WrenVM* vm)
{
WrenConfiguration configuration;
wrenInitConfiguration(&configuration);
configuration.resolveModuleFn = resolveChange;
runTestVM(vm, &configuration, "import \"baz|bang\"");
}

View File

@ -12,7 +12,7 @@ static void getSlots(WrenVM* vm)
{
bool result = true;
if (wrenGetSlotBool(vm, 1) != true) result = false;
int length;
const char* bytes = wrenGetSlotBytes(vm, 2, &length);
if (length != 5) result = false;
@ -20,7 +20,7 @@ static void getSlots(WrenVM* vm)
if (wrenGetSlotDouble(vm, 3) != 1.5) result = false;
if (strcmp(wrenGetSlotString(vm, 4), "str") != 0) result = false;
WrenHandle* handle = wrenGetSlotHandle(vm, 5);
if (result)
@ -40,18 +40,18 @@ static void getSlots(WrenVM* vm)
static void setSlots(WrenVM* vm)
{
WrenHandle* handle = wrenGetSlotHandle(vm, 1);
wrenSetSlotBool(vm, 1, true);
wrenSetSlotBytes(vm, 2, "by\0te", 5);
wrenSetSlotDouble(vm, 3, 1.5);
wrenSetSlotString(vm, 4, "str");
wrenSetSlotNull(vm, 5);
// Read the slots back to make sure they were set correctly.
bool result = true;
if (wrenGetSlotBool(vm, 1) != true) result = false;
int length;
const char* bytes = wrenGetSlotBytes(vm, 2, &length);
if (length != 5) result = false;
@ -61,7 +61,7 @@ static void setSlots(WrenVM* vm)
if (strcmp(wrenGetSlotString(vm, 4), "str") != 0) result = false;
if (wrenGetSlotType(vm, 5) != WREN_TYPE_NULL) result = false;
if (result)
{
// Move the value into the return position.
@ -86,24 +86,24 @@ static void slotTypes(WrenVM* vm)
wrenGetSlotType(vm, 5) == WREN_TYPE_NUM &&
wrenGetSlotType(vm, 6) == WREN_TYPE_STRING &&
wrenGetSlotType(vm, 7) == WREN_TYPE_UNKNOWN;
wrenSetSlotBool(vm, 0, result);
}
static void ensure(WrenVM* vm)
{
int before = wrenGetSlotCount(vm);
wrenEnsureSlots(vm, 20);
int after = wrenGetSlotCount(vm);
// Use the slots to make sure they're available.
for (int i = 0; i < 20; i++)
{
wrenSetSlotDouble(vm, i, i);
}
int sum = 0;
for (int i = 0; i < 20; i++)

View File

@ -9,18 +9,18 @@ static void test(WrenVM* vm)
{
WrenConfiguration configuration;
wrenInitConfiguration(&configuration);
// Should default to NULL.
if (configuration.userData != NULL)
{
wrenSetSlotBool(vm, 0, false);
return;
}
configuration.userData = (void*)data;
WrenVM* otherVM = wrenNewVM(&configuration);
// Should be able to get it.
if (wrenGetUserData(otherVM) != data)
{
@ -28,10 +28,10 @@ static void test(WrenVM* vm)
wrenFreeVM(otherVM);
return;
}
// Should be able to set it.
wrenSetUserData(otherVM, (void*)otherData);
if (wrenGetUserData(otherVM) != otherData)
{
wrenSetSlotBool(vm, 0, false);