diff --git a/scripts/main.ts b/scripts/main.ts index f4b1b56..95c21f0 100644 --- a/scripts/main.ts +++ b/scripts/main.ts @@ -2,7 +2,7 @@ VAR global : INT; PUB main() | i : INT BEGIN - fun(1) -> i; + fun() -> i; END PUB fun() -> i : INT diff --git a/src/vm.cpp b/src/vm.cpp index ea06ece..3975f3c 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -128,12 +128,6 @@ Variable NativeMethod::invoke(Vector arguments) return mkvar((Int)result); } -extern "C" uint32_t __cdecl cCodeFunction(int a, int b) -{ - kprintf("a=%d, b=%d\n", a, b); - return 666; -} - struct NativeModuleDef { const char *name; @@ -174,24 +168,13 @@ extern "C" void vm_start() return; } + // Load native modules NativeModuleDef *mod = methods; while(mod->name != nullptr) { module->methods.add(mod->name, new NativeMethod(mod->function)); mod++; } - for(const auto &var : module->variables) - { - kprintf("Variable: '%s' => '", var.first.str()); - var.second->printval(); - kprintf("'\n"); - } - - for(const auto &fn : module->methods) - { - kprintf("Function: '%s'\n", fn.first.str()); - } - Method *main = module->method("main"); if(main == nullptr) { kprintf("Script has no main method.\n"); diff --git a/src/vm.cpp.autosave b/src/vm.cpp.autosave new file mode 100644 index 0000000..03ad6c4 --- /dev/null +++ b/src/vm.cpp.autosave @@ -0,0 +1,331 @@ +#include +#include +#include "../trainscript/tsvm.hpp" + +using namespace ker; +using namespace trainscript; + +extern "C" { + extern const char mainscript_start; + extern const char mainscript_end; + extern const char mainscript_size; +} + +void cpp_test(); + +class NativeMethod : + public Method +{ +private: + void *function; +public: + NativeMethod(void *fn) : + function(fn) + { + + } + + Variable invoke(Vector arguments) override; + + bool validate(ker::String &errorCode) const + { + if(this->function == nullptr) { + errorCode = "Native method with nullptr interface."; + return false; + } + return true; + } + + Vector arguments() const { + return Vector(); + } + + Type returnType() const { + return Type::Int; + } +}; + +static void copyCode(uint8_t **ptr, const uint8_t *src, size_t length) +{ + for(size_t i = 0; i < length; i++) { + // Copy byte + **ptr = src[i]; + // Iterate + (*ptr)++; + } +} + + + +/** + * @brief Invokes a cdecl function + * @param arguments Arguments passed to the c function + * @return uint32_t return value of the c function + */ +Variable NativeMethod::invoke(Vector arguments) +{ + if(this->function == nullptr) { + return Variable::Invalid; + } + + // ASM code: + // push ebp + // mov ebp, esp + // (push imm32) * num + // call [function] + // add esp, 4 * num + // ret + + uint8_t headerCode[] = { + 0x55, // push ebp + 0x89, 0xE5, // mov ebp, esp + }; + uint8_t tailCode[] = { + 0xB8, 0x42, 0x00, 0x00, 0x00, // mov eax,0x42 + 0xFF, 0xD0, // call eax + 0x83, 0xC4, 0x08, // add esp, 0x00 + 0xC9, // leave + // 0x5D, // pop ebp + 0xC3, // ret + }; + + // Store some memory for a function + uint8_t pushCode[] = { + 0x68, 0x00, 0x00, 0x00, 0x00 // push 0x00 + }; + + size_t stackSize = 4 * arguments.length(); + + // Copy target address to mov eax, 0x42 + *reinterpret_cast(&tailCode[1]) = reinterpret_cast(this->function); + // Copy stack size to add esp, 0x00 + *reinterpret_cast(&tailCode[9]) = static_cast(stackSize); + + uint8_t code[128]; + // Built the function + { + uint8_t *codePtr = &code[0]; + // Copy function header + copyCode(&codePtr, headerCode, sizeof(headerCode)); + + // Copy arguments + for(int i = arguments.length() - 1; i >= 0; i--) { + + // Copy argument value to push 0x00 + *reinterpret_cast(&pushCode[1]) = reinterpret_cast(arguments[i].integer); + + // Copy push code + copyCode(&codePtr, pushCode, sizeof(pushCode)); + } + + // Copy function end + copyCode(&codePtr, tailCode, sizeof(tailCode)); + } + + // Call some crazy + uint32_t (*func)() = (uint32_t(*)())code; + + uint32_t result = func(); + + return mkvar((Int)result); +} + +struct NativeModuleDef +{ + const char *name; + void *function; +}; + +NativeModuleDef methods[] = { + { "sleep", (void*)sleep }, + { "timer_get", (void*)timer_get }, + { "timer_set", (void*)timer_set }, + { nullptr, 0 } +}; + +extern "C" void vm_start() +{ + struct { + const char *ptr; + uint32_t size; + } mainfile { + &mainscript_start, + (uint32_t)&mainscript_size + }; + + // cpp_test(); + + kprintf("Parse kernel module: "); + Module *module = VM::load(mainfile.ptr, mainfile.size); + if(module == nullptr) { + kprintf("Could not load module :(\n"); + return; + } + + kprintf("Module successfully loaded :)\n"); + + String errorCode; + if(module->validate(errorCode) == false) { + kprintf("Module validation failed: \x12\x06%s\x12\x07\n", errorCode.str()); + return; + } + + // Load native modules + NativeModuleDef *mod = methods; + while(mod->name != nullptr) { + module->methods.add(mod->name, new NativeMethod(mod->function)); + mod++; + } + + Method *main = module->method("main"); + if(main == nullptr) { + kprintf("Script has no main method.\n"); + return; + } + + main->invoke({ }); + + delete module; +} + + +String fn() +{ + return String("keks"); +} + +void put(Vector &v) +{ + kprintf("v[%d]: ", v.length()); + for(int i : v) { kprintf("%d,", i); } + kprintf("\n"); +} + +void put(Vector &v) +{ + kprintf("v[%d]: ", v.length()); + for(String &s : v) { kprintf("[%s],", s.str()); } + kprintf("\n"); +} + +void put(Dictionary &d) +{ + kprintf("dict: "); + for(auto &it : d) + { + kprintf("[%d -> %d] ", it.first, it.second); + } + kprintf("\n"); +} + +void put(Dictionary &d) +{ + kprintf("dict: "); + for(auto &it : d) + { + kprintf("[%s -> %s] ", it.first.str(), it.second.str()); + } + kprintf("\n"); +} + +void cpp_test() +{ + kprintf("Testing ker::String:\n"); + { + String a("hello"); + String b(a); + String c; + String d(fn()); + String e; + c = a; + e = fn(); + + kprintf("'%s' '%s' '%s' '%s' '%s'\n", a.str(), b.str(), c.str(), d.str(), e.str()); + } + + kprintf("Testing ker::Pair:\n"); + { + Pair a(10, 20); + Pair b("Hey", "Affe"); + + Pair c(a); + Pair d(b); + + Pair e; e = a; + Pair f; f = b; + + kprintf("'%d,%d' '%d,%d' '%d,%d'\n", a.first, a.second, c.first, c.second, e.first, e.second); + kprintf("'%s,%s' '%s,%s' '%s,%s'\n", b.first.str(), b.second.str(), d.first.str(), d.second.str(), f.first.str(), f.second.str()); + } + + kprintf("Testing ker::Vector:\n"); + { + Vector a; + a.append(1); + a.append(2); + a.append(3); + + Vector c; + Vector b(a); + c = a; + + put(a); + put(b); + put(c); + } + { + Vector a; + a.append("x"); + a.append("y"); + a.append("z"); + + Vector c; + Vector b(a); + c = a; + + put(a); + put(b); + put(c); + } + + kprintf("Testing ker::Dictionary:\n"); + { + kprintf("int -> int\n"); + Dictionary a; + a.add(1, 30); + a.add(2, 20); + a.add(3, 10); + + kprintf("%d %d\n", a.contains(1), a.contains(4)); + kprintf("%d %d\n", a.at(1), a.at(3)); + kprintf("%d %d\n", a[1], a[3]); + + Dictionary b(a); + Dictionary c; + c = a; + + put(a); + put(b); + put(c); + } + + { + kprintf("String -> String\n"); + Dictionary a; + a.add("x", "30"); + a.add("y", "20"); + a.add("z", "10"); + + kprintf("%d %d\n", a.contains("x"), a.contains("w")); + kprintf("%s %s\n", a.at("x").str(), a.at("z").str()); + kprintf("%s %s\n", a["x"].str(), a["z"].str()); + + Dictionary b(a); + Dictionary c; + c = a; + + put(a); + put(b); + put(c); + } +}