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 }