1#include "wren_opt_meta.h"
2
3#if WREN_OPT_META
4
5#include <string.h>
6
7#include "wren_vm.h"
8#include "wren_opt_meta.wren.inc"
9
10void metaCompile(WrenVM* vm)
11{
12 const char* source = wrenGetSlotString(vm, 1);
13 bool isExpression = wrenGetSlotBool(vm, 2);
14 bool printErrors = wrenGetSlotBool(vm, 3);
15
16 // TODO: Allow passing in module?
17 // Look up the module surrounding the callsite. This is brittle. The -2 walks
18 // up the callstack assuming that the meta module has one level of
19 // indirection before hitting the user's code. Any change to meta may require
20 // this constant to be tweaked.
21 ObjFiber* currentFiber = vm->fiber;
22 ObjFn* fn = currentFiber->frames[currentFiber->numFrames - 2].closure->fn;
23 ObjString* module = fn->module->name;
24
25 ObjClosure* closure = wrenCompileSource(vm, module->value, source,
26 isExpression, printErrors);
27
28 // Return the result. We can't use the public API for this since we have a
29 // bare ObjClosure*.
30 if (closure == NULL)
31 {
32 vm->apiStack[0] = NULL_VAL;
33 }
34 else
35 {
36 vm->apiStack[0] = OBJ_VAL(closure);
37 }
38}
39
40void metaGetModuleVariables(WrenVM* vm)
41{
42 wrenEnsureSlots(vm, 3);
43
44 Value moduleValue = wrenMapGet(vm->modules, vm->apiStack[1]);
45 if (IS_UNDEFINED(moduleValue))
46 {
47 vm->apiStack[0] = NULL_VAL;
48 return;
49 }
50
51 ObjModule* module = AS_MODULE(moduleValue);
52 ObjList* names = wrenNewList(vm, module->variableNames.count);
53 vm->apiStack[0] = OBJ_VAL(names);
54
55 // Initialize the elements to null in case a collection happens when we
56 // allocate the strings below.
57 for (int i = 0; i < names->elements.count; i++)
58 {
59 names->elements.data[i] = NULL_VAL;
60 }
61
62 for (int i = 0; i < names->elements.count; i++)
63 {
64 names->elements.data[i] = OBJ_VAL(module->variableNames.data[i]);
65 }
66}
67
68const char* wrenMetaSource()
69{
70 return metaModuleSource;
71}
72
73WrenForeignMethodFn wrenMetaBindForeignMethod(WrenVM* vm,
74 const char* className,
75 bool isStatic,
76 const char* signature)
77{
78 // There is only one foreign method in the meta module.
79 ASSERT(strcmp(className, "Meta") == 0, "Should be in Meta class.");
80 ASSERT(isStatic, "Should be static.");
81
82 if (strcmp(signature, "compile_(_,_,_)") == 0)
83 {
84 return metaCompile;
85 }
86
87 if (strcmp(signature, "getModuleVariables_(_)") == 0)
88 {
89 return metaGetModuleVariables;
90 }
91
92 ASSERT(false, "Unknown method.");
93 return NULL;
94}
95
96#endif
97