Anyway, Host API functions are done in a basic way - the VM doesn't validate the number or type of parameters, but the stack will convert them for the app, which is nice. And, I successfully assembled and ran this script, which produced the expected output:
; Test.DASM; Test DruinkScript assembly file#define num 5; Function: Test; Input:; Stack[top] = count; Stack[top-1] = string; Remarks:; Prints 'string' 'count' timesfunc Test{ pop r1 pop r0Start: push r0 callhost Print sub r1, 1 cmp r1, 0 jne Start}; Function: _Main; Remarks: Script entry pointfunc _Main{ mov r9, "This is the first string. EVAR!!1" mov r1, 0xa ; r1 = 10 mov r2, num ; r2 = num (5) mul r1, r2 ; r1 *= r2 mov r0, "This is a test string with \"escaped\" bits\n" push r0 push r1 call Test strleft r0, "LOL!", 3 push r0 callhost Print}
I'm happy. I'll try and knock up a simple speed test of DruinkScript v.s. Lua, once I get a script thats slightly more involved.
So far, I got a speed test done in debug mode, in a frantic rush just as the train was pulling into the station, and it showed the above script execting in 0.01 seconds. Although a lot of the code will optimize away in release mode, and that is a pretty shonky test. And a lot of the time will be spent in the printf() call that Print() causes.
Ok, ok I'll stop making excuses and do a real test later. Sheesh...
Oh - almost forgot. How to register a function (This is off the top of my head since I can't be bothered fireing up my laptop to check it exactly):
#include "DruinkScript/DruinkScript.h"class Func_Print : public DruinkScript::HostFunction{public: Func_Print() {} virtual ~Func_Print() {} virtual bool Call(DruinkScript::VM* pVM, DruinkScript::Stack& rStack) { printf("%s", rStack.GetParamAsString(0)); rStack.Pop(1); return true; }};int main(int, char**){ DruinkScript::VM theVM; theVM.Init(); theVM.Register("Print", new Func_Print); DruinkScript::Script* pScript = theVM.LoadScript("test.ds"); return 0;}
LoadScript() invokes the _Main function, which then calls Print(), which executes the functor. The VM will delete the pointer passed to it when it gets shutdown (When the destructor is called), or when you call theVM.Unregister().