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