Пример #1
0
static int runRepl()
{
  WrenVM* vm = wrenNewVM(reallocate);

  for (;;)
  {
    printf("> ");
    char line[MAX_LINE];
    fgets(line, MAX_LINE, stdin);

    // TODO: Handle failure.
    wrenInterpret(vm, line);
    // TODO: Figure out how this should work with wren API.
    /*
    ObjFn* fn = compile(vm, line);

    if (fn != NULL)
    {
      Value result = interpret(vm, fn);
      printf("= ");
      printValue(result);
      printf("\n");
    }
    */
  }

  wrenFreeVM(vm);
  return 0;
}
Пример #2
0
static int runRepl()
{
  WrenVM* vm = createVM(NULL);

  printf("\\\\/\"-\n");
  printf(" \\_/   wren v0.0.0\n");

  char line[MAX_LINE_LENGTH];

  for (;;)
  {
    printf("> ");

    if (!fgets(line, MAX_LINE_LENGTH, stdin))
    {
      printf("\n");
      break;
    }

    // TODO: Handle failure.
    wrenInterpret(vm, "Prompt", line);

    // TODO: Automatically print the result of expressions.
  }

  wrenFreeVM(vm);
  return 0;
}
Пример #3
0
Файл: vm.c Проект: 0x73/wren
int runRepl()
{
  initVM();

  printf("\\\\/\"-\n");
  printf(" \\_/   wren v0.0.0\n");

  char line[MAX_LINE_LENGTH];

  for (;;)
  {
    printf("> ");

    if (!fgets(line, MAX_LINE_LENGTH, stdin))
    {
      printf("\n");
      break;
    }

    // TODO: Handle failure.
    wrenInterpret(vm, line);

    // TODO: Automatically print the result of expressions.
  }

  freeVM();

  return 0;
}
Пример #4
0
void wrenLoadMetaLibrary(WrenVM* vm)
{
  wrenInterpret(vm, "", metaModuleSource);

  ObjModule* coreModule = wrenGetCoreModule(vm);

  // The methods on "Meta" are static, so get the metaclass for the Meta class.
  ObjClass* meta = AS_CLASS(wrenFindVariable(vm, coreModule, "Meta"));
  PRIMITIVE(meta->obj.classObj, "eval(_)", meta_eval);
}
Пример #5
0
static int runFile(const char* path)
{
  char* source = readFile(path);
  WrenVM* vm = wrenNewVM(reallocate);

  int result = wrenInterpret(vm, source);

  wrenFreeVM(vm);
  free(source);

  return result;
}
Пример #6
0
void Wren::executeString( const std::string& code ) {
    // set global variables for the C-callbacks
    boundForeignMethods = &foreignMethods_;
    boundForeignClasses = &foreignClasses_;
    
    auto res = wrenInterpret( vm_, "string", code.c_str() );
    
    if ( res == WrenInterpretResult::WREN_RESULT_COMPILE_ERROR ) {
        std::cerr << "WREN_RESULT_COMPILE_ERROR in string: " << code << std::endl;
    }
    
    if ( res == WrenInterpretResult::WREN_RESULT_RUNTIME_ERROR ) {
        std::cerr << "WREN_RESULT_RUNTIME_ERROR in string: " << code << std::endl;
    }
    
    boundForeignMethods = nullptr;
    boundForeignClasses = nullptr;
}
Пример #7
0
int main(int argc, char *argv[])
{
    const char* s = argc > 1 ? argv[1] : DEFAULT_SCRIPT;
    const int c = argc > 2 ? atoi(argv[2]) : DEFAULT_COUNT;
    
    count += c;
    
    char* script = readFile(s);
    if (script == NULL)
    {
        fprintf(stderr, "Could not locate %s\n", s);
        return 1;
    }
    
    WrenConfiguration config;
    wrenInitConfiguration(&config);

    config.bindForeignMethodFn = bindForeignMethod;
    //config.bindForeignClassFn = bindForeignClass;
    //config.loadModuleFn = readModule;
    config.writeFn = write;
    config.errorFn = reportError;

    // Since we're running in a standalone process, be generous with memory.
    config.initialHeapSize = 1024 * 1024 * 100;
    WrenVM* vm = wrenNewVM(&config);
    
    //fprintf(stdout, "Found hello.wren\n%s\n", script);
    
    WrenInterpretResult result = wrenInterpret(vm, script);
    if (result == WREN_RESULT_SUCCESS)
    {
        printf("%lld\n", ts_stop - ts_start);
    }
    else
    {
        fprintf(stderr, "Error executing hello.wren %d\n", result);
    }
        
    wrenFreeVM(vm);
    free(script);
    
    return result;
}
Пример #8
0
Файл: vm.c Проект: 0x73/wren
void runFile(const char* path)
{
  // Use the directory where the file is as the root to resolve imports
  // relative to.
  char* root = NULL;
  const char* lastSlash = strrchr(path, '/');
  if (lastSlash != NULL)
  {
    root = (char*)malloc(lastSlash - path + 2);
    memcpy(root, path, lastSlash - path + 1);
    root[lastSlash - path + 1] = '\0';
    rootDirectory = root;
  }

  char* source = readFile(path);
  if (source == NULL)
  {
    fprintf(stderr, "Could not find file \"%s\".\n", path);
    exit(66);
  }

  initVM();

  WrenInterpretResult result = wrenInterpret(vm, source);

  if (afterLoadFn != NULL) afterLoadFn(vm);
  
  if (result == WREN_RESULT_SUCCESS)
  {
    uv_run(loop, UV_RUN_DEFAULT);
  }

  freeVM();

  free(source);
  free(root);

  // Exit with an error code if the script failed.
  if (result == WREN_RESULT_COMPILE_ERROR) exit(65); // EX_DATAERR.
  if (result == WREN_RESULT_RUNTIME_ERROR) exit(70); // EX_SOFTWARE.
  
  if (defaultExitCode != 0) exit(defaultExitCode);
}
Пример #9
0
void Wren::executeModule( const std::string& mod ) {
    // set global variables for the C-callbacks
    boundForeignMethods = &foreignMethods_;
    boundForeignClasses = &foreignClasses_;
    
    std::string file = mod;
    file += ".wren";
    auto source = FileToString( file );
    auto res = wrenInterpret( vm_, file.c_str(), source.c_str() );
    
    if ( res == WrenInterpretResult::WREN_RESULT_COMPILE_ERROR ) {
        std::cerr << "WREN_RESULT_COMPILE_ERROR in module " << mod << std::endl;
    }
    
    if ( res == WrenInterpretResult::WREN_RESULT_RUNTIME_ERROR ) {
        std::cerr << "WREN_RESULT_RUNTIME_ERROR in module " << mod << std::endl;
    }
    
    boundForeignMethods = nullptr;
    boundForeignClasses = nullptr;
}
Пример #10
0
void wrenInitializeCore(WrenVM* vm)
{
  ObjModule* coreModule = wrenGetCoreModule(vm);
  
  // Define the root Object class. This has to be done a little specially
  // because it has no superclass.
  vm->objectClass = defineClass(vm, coreModule, "Object");
  PRIMITIVE(vm->objectClass, "!", object_not);
  PRIMITIVE(vm->objectClass, "==(_)", object_eqeq);
  PRIMITIVE(vm->objectClass, "!=(_)", object_bangeq);
  PRIMITIVE(vm->objectClass, "is(_)", object_is);
  PRIMITIVE(vm->objectClass, "toString", object_toString);
  PRIMITIVE(vm->objectClass, "type", object_type);

  // Now we can define Class, which is a subclass of Object.
  vm->classClass = defineClass(vm, coreModule, "Class");
  wrenBindSuperclass(vm, vm->classClass, vm->objectClass);
  PRIMITIVE(vm->classClass, "name", class_name);
  PRIMITIVE(vm->classClass, "supertype", class_supertype);
  PRIMITIVE(vm->classClass, "toString", class_toString);

  // Finally, we can define Object's metaclass which is a subclass of Class.
  ObjClass* objectMetaclass = defineClass(vm, coreModule, "Object metaclass");

  // Wire up the metaclass relationships now that all three classes are built.
  vm->objectClass->obj.classObj = objectMetaclass;
  objectMetaclass->obj.classObj = vm->classClass;
  vm->classClass->obj.classObj = vm->classClass;

  // Do this after wiring up the metaclasses so objectMetaclass doesn't get
  // collected.
  wrenBindSuperclass(vm, objectMetaclass, vm->classClass);

  PRIMITIVE(objectMetaclass, "same(_,_)", object_same);

  // The core class diagram ends up looking like this, where single lines point
  // to a class's superclass, and double lines point to its metaclass:
  //
  //        .------------------------------------. .====.
  //        |                  .---------------. | #    #
  //        v                  |               v | v    #
  //   .---------.   .-------------------.   .-------.  #
  //   | Object  |==>| Object metaclass  |==>| Class |=="
  //   '---------'   '-------------------'   '-------'
  //        ^                                 ^ ^ ^ ^
  //        |                  .--------------' # | #
  //        |                  |                # | #
  //   .---------.   .-------------------.      # | # -.
  //   |  Base   |==>|  Base metaclass   |======" | #  |
  //   '---------'   '-------------------'        | #  |
  //        ^                                     | #  |
  //        |                  .------------------' #  | Example classes
  //        |                  |                    #  |
  //   .---------.   .-------------------.          #  |
  //   | Derived |==>| Derived metaclass |=========="  |
  //   '---------'   '-------------------'            -'

  // The rest of the classes can now be defined normally.
  wrenInterpret(vm, "", coreLibSource);

  vm->boolClass = AS_CLASS(wrenFindVariable(vm, coreModule, "Bool"));
  PRIMITIVE(vm->boolClass, "toString", bool_toString);
  PRIMITIVE(vm->boolClass, "!", bool_not);

  vm->fiberClass = AS_CLASS(wrenFindVariable(vm, coreModule, "Fiber"));
  PRIMITIVE(vm->fiberClass->obj.classObj, "new(_)", fiber_new);
  PRIMITIVE(vm->fiberClass->obj.classObj, "abort(_)", fiber_abort);
  PRIMITIVE(vm->fiberClass->obj.classObj, "current", fiber_current);
  PRIMITIVE(vm->fiberClass->obj.classObj, "suspend()", fiber_suspend);
  PRIMITIVE(vm->fiberClass->obj.classObj, "yield()", fiber_yield);
  PRIMITIVE(vm->fiberClass->obj.classObj, "yield(_)", fiber_yield1);
  PRIMITIVE(vm->fiberClass, "call()", fiber_call);
  PRIMITIVE(vm->fiberClass, "call(_)", fiber_call1);
  PRIMITIVE(vm->fiberClass, "error", fiber_error);
  PRIMITIVE(vm->fiberClass, "isDone", fiber_isDone);
  PRIMITIVE(vm->fiberClass, "transfer()", fiber_transfer);
  PRIMITIVE(vm->fiberClass, "transfer(_)", fiber_transfer1);
  PRIMITIVE(vm->fiberClass, "try()", fiber_try);

  vm->fnClass = AS_CLASS(wrenFindVariable(vm, coreModule, "Fn"));
  PRIMITIVE(vm->fnClass->obj.classObj, "new(_)", fn_new);

  PRIMITIVE(vm->fnClass, "arity", fn_arity);
  PRIMITIVE(vm->fnClass, "call()", fn_call0);
  PRIMITIVE(vm->fnClass, "call(_)", fn_call1);
  PRIMITIVE(vm->fnClass, "call(_,_)", fn_call2);
  PRIMITIVE(vm->fnClass, "call(_,_,_)", fn_call3);
  PRIMITIVE(vm->fnClass, "call(_,_,_,_)", fn_call4);
  PRIMITIVE(vm->fnClass, "call(_,_,_,_,_)", fn_call5);
  PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_)", fn_call6);
  PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_,_)", fn_call7);
  PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_,_,_)", fn_call8);
  PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_,_,_,_)", fn_call9);
  PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_,_,_,_,_)", fn_call10);
  PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_,_,_,_,_,_)", fn_call11);
  PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_,_,_,_,_,_,_)", fn_call12);
  PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_,_,_,_,_,_,_,_)", fn_call13);
  PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_,_,_,_,_,_,_,_,_)", fn_call14);
  PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_,_,_,_,_,_,_,_,_,_)", fn_call15);
  PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_)", fn_call16);
  PRIMITIVE(vm->fnClass, "toString", fn_toString);

  vm->nullClass = AS_CLASS(wrenFindVariable(vm, coreModule, "Null"));
  PRIMITIVE(vm->nullClass, "!", null_not);
  PRIMITIVE(vm->nullClass, "toString", null_toString);

  vm->numClass = AS_CLASS(wrenFindVariable(vm, coreModule, "Num"));
  PRIMITIVE(vm->numClass->obj.classObj, "fromString(_)", num_fromString);
  PRIMITIVE(vm->numClass->obj.classObj, "pi", num_pi);
  PRIMITIVE(vm->numClass, "-(_)", num_minus);
  PRIMITIVE(vm->numClass, "+(_)", num_plus);
  PRIMITIVE(vm->numClass, "*(_)", num_multiply);
  PRIMITIVE(vm->numClass, "/(_)", num_divide);
  PRIMITIVE(vm->numClass, "<(_)", num_lt);
  PRIMITIVE(vm->numClass, ">(_)", num_gt);
  PRIMITIVE(vm->numClass, "<=(_)", num_lte);
  PRIMITIVE(vm->numClass, ">=(_)", num_gte);
  PRIMITIVE(vm->numClass, "&(_)", num_bitwiseAnd);
  PRIMITIVE(vm->numClass, "|(_)", num_bitwiseOr);
  PRIMITIVE(vm->numClass, "^(_)", num_bitwiseXor);
  PRIMITIVE(vm->numClass, "<<(_)", num_bitwiseLeftShift);
  PRIMITIVE(vm->numClass, ">>(_)", num_bitwiseRightShift);
  PRIMITIVE(vm->numClass, "abs", num_abs);
  PRIMITIVE(vm->numClass, "acos", num_acos);
  PRIMITIVE(vm->numClass, "asin", num_asin);
  PRIMITIVE(vm->numClass, "atan", num_atan);
  PRIMITIVE(vm->numClass, "ceil", num_ceil);
  PRIMITIVE(vm->numClass, "cos", num_cos);
  PRIMITIVE(vm->numClass, "floor", num_floor);
  PRIMITIVE(vm->numClass, "-", num_negate);
  PRIMITIVE(vm->numClass, "sin", num_sin);
  PRIMITIVE(vm->numClass, "sqrt", num_sqrt);
  PRIMITIVE(vm->numClass, "tan", num_tan);
  PRIMITIVE(vm->numClass, "%(_)", num_mod);
  PRIMITIVE(vm->numClass, "~", num_bitwiseNot);
  PRIMITIVE(vm->numClass, "..(_)", num_dotDot);
  PRIMITIVE(vm->numClass, "...(_)", num_dotDotDot);
  PRIMITIVE(vm->numClass, "atan(_)", num_atan2);
  PRIMITIVE(vm->numClass, "fraction", num_fraction);
  PRIMITIVE(vm->numClass, "isNan", num_isNan);
  PRIMITIVE(vm->numClass, "sign", num_sign);
  PRIMITIVE(vm->numClass, "toString", num_toString);
  PRIMITIVE(vm->numClass, "truncate", num_truncate);

  // These are defined just so that 0 and -0 are equal, which is specified by
  // IEEE 754 even though they have different bit representations.
  PRIMITIVE(vm->numClass, "==(_)", num_eqeq);
  PRIMITIVE(vm->numClass, "!=(_)", num_bangeq);

  vm->stringClass = AS_CLASS(wrenFindVariable(vm, coreModule, "String"));
  PRIMITIVE(vm->stringClass->obj.classObj, "fromCodePoint(_)", string_fromCodePoint);
  PRIMITIVE(vm->stringClass, "+(_)", string_plus);
  PRIMITIVE(vm->stringClass, "[_]", string_subscript);
  PRIMITIVE(vm->stringClass, "byteAt(_)", string_byteAt);
  PRIMITIVE(vm->stringClass, "codePointAt(_)", string_codePointAt);
  PRIMITIVE(vm->stringClass, "contains(_)", string_contains);
  PRIMITIVE(vm->stringClass, "count", string_count);
  PRIMITIVE(vm->stringClass, "endsWith(_)", string_endsWith);
  PRIMITIVE(vm->stringClass, "indexOf(_)", string_indexOf);
  PRIMITIVE(vm->stringClass, "iterate(_)", string_iterate);
  PRIMITIVE(vm->stringClass, "iterateByte_(_)", string_iterateByte);
  PRIMITIVE(vm->stringClass, "iteratorValue(_)", string_iteratorValue);
  PRIMITIVE(vm->stringClass, "startsWith(_)", string_startsWith);
  PRIMITIVE(vm->stringClass, "toString", string_toString);

  vm->listClass = AS_CLASS(wrenFindVariable(vm, coreModule, "List"));
  PRIMITIVE(vm->listClass->obj.classObj, "new()", list_new);
  PRIMITIVE(vm->listClass, "[_]", list_subscript);
  PRIMITIVE(vm->listClass, "[_]=(_)", list_subscriptSetter);
  PRIMITIVE(vm->listClass, "add(_)", list_add);
  PRIMITIVE(vm->listClass, "clear()", list_clear);
  PRIMITIVE(vm->listClass, "count", list_count);
  PRIMITIVE(vm->listClass, "insert(_,_)", list_insert);
  PRIMITIVE(vm->listClass, "iterate(_)", list_iterate);
  PRIMITIVE(vm->listClass, "iteratorValue(_)", list_iteratorValue);
  PRIMITIVE(vm->listClass, "removeAt(_)", list_removeAt);

  vm->mapClass = AS_CLASS(wrenFindVariable(vm, coreModule, "Map"));
  PRIMITIVE(vm->mapClass->obj.classObj, "new()", map_new);
  PRIMITIVE(vm->mapClass, "[_]", map_subscript);
  PRIMITIVE(vm->mapClass, "[_]=(_)", map_subscriptSetter);
  PRIMITIVE(vm->mapClass, "clear()", map_clear);
  PRIMITIVE(vm->mapClass, "containsKey(_)", map_containsKey);
  PRIMITIVE(vm->mapClass, "count", map_count);
  PRIMITIVE(vm->mapClass, "remove(_)", map_remove);
  PRIMITIVE(vm->mapClass, "iterate_(_)", map_iterate);
  PRIMITIVE(vm->mapClass, "keyIteratorValue_(_)", map_keyIteratorValue);
  PRIMITIVE(vm->mapClass, "valueIteratorValue_(_)", map_valueIteratorValue);

  vm->rangeClass = AS_CLASS(wrenFindVariable(vm, coreModule, "Range"));
  PRIMITIVE(vm->rangeClass, "from", range_from);
  PRIMITIVE(vm->rangeClass, "to", range_to);
  PRIMITIVE(vm->rangeClass, "min", range_min);
  PRIMITIVE(vm->rangeClass, "max", range_max);
  PRIMITIVE(vm->rangeClass, "isInclusive", range_isInclusive);
  PRIMITIVE(vm->rangeClass, "iterate(_)", range_iterate);
  PRIMITIVE(vm->rangeClass, "iteratorValue(_)", range_iteratorValue);
  PRIMITIVE(vm->rangeClass, "toString", range_toString);

  // While bootstrapping the core types and running the core library, a number
  // of string objects have been created, many of which were instantiated
  // before stringClass was stored in the VM. Some of them *must* be created
  // first -- the ObjClass for string itself has a reference to the ObjString
  // for its name.
  //
  // These all currently have a NULL classObj pointer, so go back and assign
  // them now that the string class is known.
  for (Obj* obj = vm->first; obj != NULL; obj = obj->next)
  {
    if (obj->type == OBJ_STRING) obj->classObj = vm->stringClass;
  }
}
Пример #11
0
void wrenInitializeCore(WrenVM* vm)
{
  // Define the root Object class. This has to be done a little specially
  // because it has no superclass and an unusual metaclass (Class).
  vm->objectClass = defineSingleClass(vm, "Object");
  NATIVE(vm->objectClass, "== ", object_eqeq);
  NATIVE(vm->objectClass, "!= ", object_bangeq);
  NATIVE(vm->objectClass, "new", object_new);
  NATIVE(vm->objectClass, "toString", object_toString);
  NATIVE(vm->objectClass, "type", object_type);
  NATIVE(vm->objectClass, " instantiate", object_instantiate);

  // Now we can define Class, which is a subclass of Object, but Object's
  // metaclass.
  vm->classClass = defineSingleClass(vm, "Class");

  // Now that Object and Class are defined, we can wire them up to each other.
  wrenBindSuperclass(vm, vm->classClass, vm->objectClass);
  vm->objectClass->metaclass = vm->classClass;
  vm->classClass->metaclass = vm->classClass;

  // Define the methods specific to Class after wiring up its superclass to
  // prevent the inherited ones from overwriting them.
  NATIVE(vm->classClass, " instantiate", class_instantiate);
  NATIVE(vm->classClass, "name", class_name);

  // The core class diagram ends up looking like this, where single lines point
  // to a class's superclass, and double lines point to its metaclass:
  //
  //             __________        /====\
  //            /          \      //    \\
  //           v            \     v      \\
  //     .---------.   .--------------.  //
  //     | Object  |==>|    Class     |==/
  //     '---------'   '--------------'
  //          ^               ^
  //          |               |
  //     .---------.   .--------------.   \
  //     |  Base   |==>|  Base.type   |    |
  //     '---------'   '--------------'    |
  //          ^               ^            | Hypothetical example classes
  //          |               |            |
  //     .---------.   .--------------.    |
  //     | Derived |==>| Derived.type |    |
  //     '---------'   '--------------'    /

  // The rest of the classes can not be defined normally.
  vm->boolClass = defineClass(vm, "Bool");
  NATIVE(vm->boolClass, "toString", bool_toString);
  NATIVE(vm->boolClass, "!", bool_not);

  // TODO: Make fibers inherit Sequence and be iterable.
  vm->fiberClass = defineClass(vm, "Fiber");
  NATIVE(vm->fiberClass->metaclass, " instantiate", fiber_instantiate);
  NATIVE(vm->fiberClass->metaclass, "new ", fiber_new);
  NATIVE(vm->fiberClass->metaclass, "yield", fiber_yield);
  NATIVE(vm->fiberClass->metaclass, "yield ", fiber_yield1);
  NATIVE(vm->fiberClass, "call", fiber_call);
  NATIVE(vm->fiberClass, "call ", fiber_call1);
  NATIVE(vm->fiberClass, "isDone", fiber_isDone);
  NATIVE(vm->fiberClass, "run", fiber_run);
  NATIVE(vm->fiberClass, "run ", fiber_run1);

  vm->fnClass = defineClass(vm, "Fn");

  NATIVE(vm->fnClass->metaclass, " instantiate", fn_instantiate);
  NATIVE(vm->fnClass->metaclass, "new ", fn_new);

  NATIVE(vm->fnClass, "call", fn_call0);
  NATIVE(vm->fnClass, "call ", fn_call1);
  NATIVE(vm->fnClass, "call  ", fn_call2);
  NATIVE(vm->fnClass, "call   ", fn_call3);
  NATIVE(vm->fnClass, "call    ", fn_call4);
  NATIVE(vm->fnClass, "call     ", fn_call5);
  NATIVE(vm->fnClass, "call      ", fn_call6);
  NATIVE(vm->fnClass, "call       ", fn_call7);
  NATIVE(vm->fnClass, "call        ", fn_call8);
  NATIVE(vm->fnClass, "call         ", fn_call9);
  NATIVE(vm->fnClass, "call          ", fn_call10);
  NATIVE(vm->fnClass, "call           ", fn_call11);
  NATIVE(vm->fnClass, "call            ", fn_call12);
  NATIVE(vm->fnClass, "call             ", fn_call13);
  NATIVE(vm->fnClass, "call              ", fn_call14);
  NATIVE(vm->fnClass, "call               ", fn_call15);
  NATIVE(vm->fnClass, "call                ", fn_call16);
  NATIVE(vm->fnClass, "toString", fn_toString);

  vm->nullClass = defineClass(vm, "Null");
  NATIVE(vm->nullClass, "toString", null_toString);

  vm->numClass = defineClass(vm, "Num");
  NATIVE(vm->numClass, "abs", num_abs);
  NATIVE(vm->numClass, "ceil", num_ceil);
  NATIVE(vm->numClass, "cos", num_cos);
  NATIVE(vm->numClass, "floor", num_floor);
  NATIVE(vm->numClass, "isNan", num_isNan);
  NATIVE(vm->numClass, "sin", num_sin);
  NATIVE(vm->numClass, "sqrt", num_sqrt);
  NATIVE(vm->numClass, "toString", num_toString)
  NATIVE(vm->numClass, "-", num_negate);
  NATIVE(vm->numClass, "- ", num_minus);
  NATIVE(vm->numClass, "+ ", num_plus);
  NATIVE(vm->numClass, "* ", num_multiply);
  NATIVE(vm->numClass, "/ ", num_divide);
  NATIVE(vm->numClass, "% ", num_mod);
  NATIVE(vm->numClass, "< ", num_lt);
  NATIVE(vm->numClass, "> ", num_gt);
  NATIVE(vm->numClass, "<= ", num_lte);
  NATIVE(vm->numClass, ">= ", num_gte);
  NATIVE(vm->numClass, "~", num_bitwiseNot);
  NATIVE(vm->numClass, "& ", num_bitwiseAnd);
  NATIVE(vm->numClass, "| ", num_bitwiseOr);
  NATIVE(vm->numClass, ".. ", num_dotDot);
  NATIVE(vm->numClass, "... ", num_dotDotDot);

  vm->stringClass = defineClass(vm, "String");
  NATIVE(vm->stringClass, "contains ", string_contains);
  NATIVE(vm->stringClass, "count", string_count);
  NATIVE(vm->stringClass, "toString", string_toString)
  NATIVE(vm->stringClass, "+ ", string_plus);
  NATIVE(vm->stringClass, "== ", string_eqeq);
  NATIVE(vm->stringClass, "!= ", string_bangeq);
  NATIVE(vm->stringClass, "[ ]", string_subscript);

  wrenInterpret(vm, "Wren core library", libSource);

  vm->listClass = AS_CLASS(findGlobal(vm, "List"));
  NATIVE(vm->listClass->metaclass, " instantiate", list_instantiate);
  NATIVE(vm->listClass, "add ", list_add);
  NATIVE(vm->listClass, "clear", list_clear);
  NATIVE(vm->listClass, "count", list_count);
  NATIVE(vm->listClass, "insert  ", list_insert);
  NATIVE(vm->listClass, "iterate ", list_iterate);
  NATIVE(vm->listClass, "iteratorValue ", list_iteratorValue);
  NATIVE(vm->listClass, "removeAt ", list_removeAt);
  NATIVE(vm->listClass, "[ ]", list_subscript);
  NATIVE(vm->listClass, "[ ]=", list_subscriptSetter);

  vm->rangeClass = AS_CLASS(findGlobal(vm, "Range"));
  NATIVE(vm->rangeClass, "from", range_from);
  NATIVE(vm->rangeClass, "to", range_to);
  NATIVE(vm->rangeClass, "min", range_min);
  NATIVE(vm->rangeClass, "max", range_max);
  NATIVE(vm->rangeClass, "isInclusive", range_isInclusive);
  NATIVE(vm->rangeClass, "iterate ", range_iterate);
  NATIVE(vm->rangeClass, "iteratorValue ", range_iteratorValue);
  NATIVE(vm->rangeClass, "toString", range_toString);

  // These are defined just so that 0 and -0 are equal, which is specified by
  // IEEE 754 even though they have different bit representations.
  NATIVE(vm->numClass, "== ", num_eqeq);
  NATIVE(vm->numClass, "!= ", num_bangeq);
}