1 /++ 2 Contains everything needed to run QScript scripts. 3 +/ 4 module qscript.qscript; 5 6 import utils.misc; 7 import utils.lists; 8 import qscript.compiler.compiler; 9 import qscript.compiler.misc; 10 import std.stdio; 11 import std.conv:to; 12 13 import navm.navm; 14 15 alias ExternFunction = navm.navm.ExternFunction; 16 alias NaData = navm.navm.NaData; 17 deprecated alias QData = NaData; 18 alias CompileError = qscript.compiler.misc.CompileError; 19 alias Function = qscript.compiler.misc.Function; 20 alias DataType = qscript.compiler.misc.DataType; 21 22 /// Runs generated byte code generated from the compiler. 23 /// Uses NaVM, so any ordinary NaVM bytecode can also be run 24 class QScript{ 25 private: 26 NaVM _vm; /// the vm doing all the heavylifting 27 Function[] _externFunctionMap; /// stores external functions 28 ExternFunction[] _externFunctionPtr; /// stores external function's pointers 29 Function[] _functionMap; /// stores script defined functions 30 uinteger[string] _functionID; /// stores function names as index, and IDs are read using `_functionID[ID]` 31 public: 32 /// constructor 33 this(Function[] externalFunctions, ExternFunction[] externalFunctionPtr){ 34 _externFunctionMap = externalFunctions.dup; 35 _externFunctionPtr = externalFunctionPtr.dup; 36 _vm = null; 37 } 38 ~this(){ 39 if (_vm) 40 .destroy(_vm); 41 } 42 /// adds an external function. 43 /// 44 /// Returns: the ID assigned to that function that will be used in the bytecode 45 uinteger addFunction(Function externalFunc, ExternFunction externalFuncPtr){ 46 _externFunctionMap ~= externalFunc; 47 _externFunctionPtr ~= externalFuncPtr; 48 return _externFunctionPtr.length-1; 49 } 50 /// 51 void addFunction(Function[] externalFunc, ExternFunction[] externalFuncPtr){ 52 _externFunctionMap ~= externalFunc.dup; 53 _externFunctionPtr ~= externalFuncPtr.dup; 54 } 55 /// Initializes the VM. must be called before executing anything in the script. And should only be called after all 56 /// external functions have been added 57 void initialize(){ 58 if (_vm) 59 .destroy(_vm); 60 _vm = new NaVM(_externFunctionPtr); 61 } 62 /// loads a script, and compiles it 63 /// 64 /// Returns: CompileErrors in an array, or arary length == 0 if no errors 65 CompileError[] loadScript(string[] script, ref string[] byteCode){ 66 _vm = new NaVM(_externFunctionPtr); 67 CompileError[] errors; 68 byteCode = compileScript(script, _externFunctionMap, errors, _functionMap); 69 // load bytecode 70 if (!_vm) 71 throw new Exception("this.initizlize not called before loadScript"); 72 _vm.load(byteCode); 73 // put function names and IDs in _functionID 74 foreach (i, func; _functionMap){ 75 _functionID[func.name] = i; 76 } 77 return errors; 78 } 79 /// Returns: ID of a function, -1 if it does not exist 80 integer functionID(string functionName){ 81 if (functionName in _functionID){ 82 return _functionID[functionName]; 83 } 84 return -1; 85 } 86 /// executes a function 87 /// 88 /// Returns: the return value, if function returned any, otherwise, garbage data 89 NaData execute(uinteger functionID, NaData[] args){ 90 return _vm.execute(functionID, args); 91 } 92 }