#include "server/snuviscript/Snuvi.h" #include "Compiler.h" #include "libraries/Math.h" #include "libraries/Time.h" #include "tokenizer/Tokenizer.h" #include "utils/HashMap.h" #include "utils/StringBuffer.h" #include "vm/Script.h" static const char* unicode(int32 c) { static char buffer[5]; int index = 0; if(c > 0xFFFF) { buffer[index++] = 0xF0 | ((c >> 18) & 0x07); buffer[index++] = 0x80 | ((c >> 12) & 0x3F); buffer[index++] = 0x80 | ((c >> 6) & 0x3F); buffer[index++] = 0x80 | (c & 0x3F); } else if(c > 0x7FF) { buffer[index++] = 0xE0 | ((c >> 12) & 0x0F); buffer[index++] = 0x80 | ((c >> 6) & 0x3F); buffer[index++] = 0x80 | (c & 0x3F); } else if(c > 0x7F) { buffer[index++] = 0xC0 | ((c >> 6) & 0x1F); buffer[index++] = 0x80 | (c & 0x3F); } else { buffer[index++] = c; } buffer[index++] = '\0'; return buffer; } static void printString(Script* sc) { int length; Pointer p; if(!sPopPointer(sc, &p) || sGetPointerLength(sc, &p, &length)) { return; } for(int i = 0; i < length; i++) { const void* data = sCheckAddress(sc, &p, sizeof(int)); if(data != nullptr) { int c; memcpy(&c, data, sizeof(int)); printf(unicode(c)); } p.offset += sizeof(int); } } static void printInt32(Script* sc) { int32 i; if(sPopInt32(sc, &i)) { printf("%d", i); } } static void wait(Script* sc) { sError(sc, "w"); } static Snuvi::Event event = Snuvi::Event::NONE; static void getEvent(Script* sc) { sPushInt32(sc, event); } static void initPrinter() { Snuvi::initFunction("print", dtVoid(), printString); Snuvi::addArgument(dtConst(dtText())); Snuvi::addFunction(); Snuvi::initFunction("print", dtVoid(), printInt32); Snuvi::addArgument(dtInt32()); Snuvi::addFunction(); } struct Scripts { int scriptId = 0; HashMap scripts; Scripts() { gfsInit(); gstsInit(); lTimeRegister(); lMathRegister(); initPrinter(); Snuvi::initFunction("wait", dtVoid(), wait); Snuvi::addFunction(); Snuvi::initFunction("getEvent", dtInt32(), getEvent); Snuvi::addFunction(); } ~Scripts() { gfsDelete(); gstsDelete(); Snuvi::termAll(); } }; static Scripts scripts; static Function function; void Snuvi::initFunction(const char* name, DataType returnType, ScriptFunction sf) { gfInit(&function, name, returnType, sf); } void Snuvi::addArgument(DataType type) { gfAddArgument(&function, type); } void Snuvi::addFunction() { gfsAdd(&function); } static void logError(const char* msg, int line) { puts(msg); printf("line: %d\n", line); } static bool runScript(Script* script) { sRun(script); if(script->error[0] == 'w' && script->error[1] == '\0') { script->error[0] = '\0'; return false; } else if(script->error[0] != '\0') { logError(script->error, script->line); return true; } return script->readIndex >= script->code->length; } int Snuvi::start(const char* path) { StringBuffer<256> s("resources/scripts/"); s.append(path).append(".snuvi"); if(tTokenize(s)) { logError(tGetError(), tGetLine()); return -1; } ByteCode* code = cCompile(); if(code == nullptr) { logError(cGetError(), cGetLine()); return -1; } Script* script = sInit(code); if(runScript(script)) { sDelete(script); return -1; } int id = scripts.scriptId++; scripts.scripts.tryEmplace(id, script); return id; } void Snuvi::termAll() { for(auto& entry : scripts.scripts) { sDelete(entry.value); } scripts.scripts.clear(); } void Snuvi::callEvent(Event e) { event = e; for(auto& entry : scripts.scripts) { if(runScript(entry.value)) { sDelete(entry.value); scripts.scripts.remove(entry.getKey()); } } } static int32 readChar(int& index, const char* s) { if(s[index] == '\0') { return '\0'; } return s[index++]; } Pointer Snuvi::toString(Script* sc, const char* s) { List data; int index = 0; while(s[index] != '\0') { int32 c = readChar(index, s); if((c & 0xE0) == 0xC0) { c = ((c & 0x1F) << 6) | (readChar(index, s) & 0x3F); } else if((c & 0xF0) == 0xE0) { c = ((c & 0xF) << 12) | ((readChar(index, s) & 0x3F) << 6); c |= readChar(index, s) & 0x3F; } else if((c & 0xF8) == 0xF0) { c = ((c & 0x7) << 18) | ((readChar(index, s) & 0x3F) << 12); c |= (readChar(index, s) & 0x3F) << 6; c |= readChar(index, s) & 0x3F; } data.add(c); } Pointer p; p.offset = 0; p.array = asAllocate(&sc->arrays, sizeof(int32), data.getLength()); printf("%d wsdfdg\n", data.getLength()); SnuviArray* array = asGet(&sc->arrays, p.array); if(array == nullptr) { sError(sc, "cannot allocate string memory"); p.offset = -1; p.array = -1; } else { memcpy(array->data, data.begin(), sizeof(int32) * data.getLength()); } return p; }