1 module wren.cli.vm; 2 import wren.vm; 3 4 __gshared WrenVM* vm; 5 6 // Reads the contents of the file at [path] and returns it as a heap allocated 7 // string. 8 // 9 // Returns `NULL` if the path could not be found. Exits if it was found but 10 // could not be read. 11 static char* readFile(const char* path) @nogc 12 { 13 import core.stdc.stdio : fopen, FILE, fread, fseek, ftell, rewind, fprintf, fclose, SEEK_END, stderr; 14 import core.stdc.stdlib : malloc; 15 16 FILE* file = fopen(path, "rb"); 17 if (file == null) return null; 18 19 // Find out how big the file is. 20 fseek(file, 0L, SEEK_END); 21 size_t fileSize = ftell(file); 22 rewind(file); 23 24 // Allocate a buffer for it. 25 char* buffer = cast(char*)malloc(fileSize + 1); 26 if (buffer == null) 27 { 28 fprintf(stderr, "Could not read file \"%s\".\n", path); 29 assert(0); 30 } 31 32 // Read the entire file. 33 size_t bytesRead = fread(buffer, 1, fileSize, file); 34 if (bytesRead < fileSize) 35 { 36 fprintf(stderr, "Could not read file \"%s\".\n", path); 37 assert(0); 38 } 39 40 // Terminate the string. 41 buffer[bytesRead] = '\0'; 42 43 fclose(file); 44 return buffer; 45 } 46 47 static void write(WrenVM* vm, const(char)* text) @nogc 48 { 49 import core.stdc.stdio : printf; 50 printf("%s", text); 51 } 52 53 static void reportError(WrenVM* vm, WrenErrorType type, 54 const(char)* module_, int line, const(char)* message) @nogc 55 { 56 import core.stdc.stdio : fprintf, stderr; 57 58 switch (type) with(WrenErrorType) 59 { 60 case WREN_ERROR_COMPILE: 61 fprintf(stderr, "[%s line %d] %s\n", module_, line, message); 62 break; 63 64 case WREN_ERROR_RUNTIME: 65 fprintf(stderr, "%s\n", message); 66 break; 67 68 case WREN_ERROR_STACK_TRACE: 69 fprintf(stderr, "[%s line %d] in %s\n", module_, line, message); 70 break; 71 default: 72 assert(0, "Unhandled error"); 73 } 74 } 75 76 static void initVM() 77 { 78 WrenConfiguration config; 79 wrenInitConfiguration(&config); 80 81 config.writeFn = &write; 82 config.errorFn = &reportError; 83 84 // Since we're running in a standalone process, be generous with memory. 85 config.initialHeapSize = 1024 * 1024 * 100; 86 vm = wrenNewVM(&config); 87 } 88 89 static void freeVM() 90 { 91 wrenFreeVM(vm); 92 } 93 94 WrenInterpretResult runFile(const(char)* path) 95 { 96 import core.stdc.stdio : fprintf, stderr; 97 import core.stdc.stdlib : free; 98 99 char* source = readFile(path); 100 if (source == null) 101 { 102 fprintf(stderr, "Could not find file for \"%s\".\n", path); 103 assert(0); 104 } 105 106 initVM(); 107 108 WrenInterpretResult result = wrenInterpret(vm, path, source); 109 110 if (result == WrenInterpretResult.WREN_RESULT_SUCCESS) 111 { 112 // Stub 113 } 114 115 freeVM(); 116 117 free(source); 118 119 return result; 120 } 121 122 WrenInterpretResult runRepl() 123 { 124 import core.stdc.stdio : printf; 125 import wren.common : WREN_VERSION_STRING; 126 127 initVM(); 128 129 printf("\\\\/\"-\n"); 130 printf(" \\_/ wren v%s\n", WREN_VERSION_STRING.ptr); 131 132 WrenInterpretResult result = wrenInterpret(vm, "<repl>", "import \"repl\"\n"); 133 134 if (result == WrenInterpretResult.WREN_RESULT_SUCCESS) 135 { 136 assert(0, "Stub"); 137 } 138 139 freeVM(); 140 141 return result; 142 }