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 }