diff --git a/include/console.h b/include/console.h index 199a5c6..5445dfa 100644 --- a/include/console.h +++ b/include/console.h @@ -75,7 +75,7 @@ void kputs(const char *str); * @param format The format string that will be printed in formatted version. * @param ... The format parameters that will be used to print the string. */ -void kprintf(const char *format, ...); +void kprintf(const char *format, ...) __attribute__((format(printf,1,2))); #if defined(__cplusplus) } diff --git a/include/ker/dictionary.hpp b/include/ker/dictionary.hpp index 5fe2428..c64664c 100644 --- a/include/ker/dictionary.hpp +++ b/include/ker/dictionary.hpp @@ -10,7 +10,7 @@ namespace ker { public: typedef Pair Entry; - private: + public: Vector contents; public: Dictionary() : @@ -19,6 +19,24 @@ namespace ker } + Dictionary(const Dictionary &other) : + contents(other.contents) + { + + } + + Dictionary(Dictionary &&other) : + contents(other.contents) + { + other.contents = Vector(); + } + + Dictionary & operator = (const Dictionary &other) + { + this->contents = other.contents; + return *this; + } + Value &at(const Key &key) { for(auto &&pair : this->contents) @@ -39,6 +57,15 @@ namespace ker } } + Value get(const Key &key) const + { + if(this->contains(key)) { + return this->at(key); + } else { + return Value(); + } + } + bool contains(const Key &key) const { for(const auto &pair : this->contents) diff --git a/include/ker/pair.hpp b/include/ker/pair.hpp index 369d493..250d96a 100644 --- a/include/ker/pair.hpp +++ b/include/ker/pair.hpp @@ -16,5 +16,27 @@ namespace ker { } + + Pair(const Pair &other) : + first(other.first), + second(other.second) + { + + } + + Pair(Pair &&other) : + first(other.first), + second(other.second) + { + other.first = First(); + other.second = Second(); + } + + Pair & operator = (const Pair &other) + { + this->first = other.first; + this->second = other.second; + return *this; + } }; } diff --git a/include/ker/string.hpp b/include/ker/string.hpp index 3b031c9..9674829 100644 --- a/include/ker/string.hpp +++ b/include/ker/string.hpp @@ -34,29 +34,22 @@ namespace ker String & operator = (const String &other) { - free(this->mText); - this->mLength = other.mLength; - - this->mText = (uint8_t*)malloc(this->mLength + 1); - memcpy(this->mText, other.mText, this->mLength + 1); + this->copyFrom(other.mText, other.mLength); + return *this; } String(const char *text) : mText(nullptr), mLength(0) { - this->mLength = strlen(text); - this->mText = (uint8_t*)malloc(this->mLength + 1); - memcpy(this->mText, text, this->mLength); - this->mText[this->mLength] = 0; + this->copyFrom(reinterpret_cast(text), strlen(text)); } String(const uint8_t *bytes, size_t length) : - mText((uint8_t*)malloc(length + 1)), + mText(nullptr), mLength(length) { - memcpy(this->mText, bytes, length); - this->mText[this->mLength] = 0; // last byte is always 0 + this->copyFrom(bytes, length); } ~String() @@ -76,7 +69,7 @@ namespace ker if(this->mLength != other.mLength) { return false; } - return memcmp(this->mText, other.mText, this->mLength) != 0; + return memcmp(this->mText, other.mText, this->mLength) == 0; } const uint8_t *text() const @@ -123,5 +116,16 @@ namespace ker { return !this->equals(other); } + private: + void copyFrom(const uint8_t *bytes, size_t length) + { + if(this->mText != nullptr) { + free(this->mText); + } + this->mText = (uint8_t*)malloc(length + 1); + memcpy(this->mText, bytes, length); + this->mLength = length; + this->mText[this->mLength] = 0; // last byte is always 0 + } }; }; diff --git a/include/ker/vector.hpp b/include/ker/vector.hpp index 6dc11c1..25b9742 100644 --- a/include/ker/vector.hpp +++ b/include/ker/vector.hpp @@ -23,12 +23,53 @@ namespace ker this->reserve(Vector::initialCap); } + Vector(const Vector &other) : + mData(nullptr), + mLength(0), + mReserved(0) + { + this->mLength = other.mLength; + if(this->mLength > 0) { + this->reserve(this->mLength); + for(size_t i = 0; i < this->mLength; i++) { + new (&this->mData[i]) T(other.mData[i]); + } + } + } + + Vector(Vector &&other) : + mData(other.mData), + mLength(other.mLength), + mReserved(other.mReserved) + { + other.mData = nullptr; + other.mLength = 0; + other.mReserved = 0; + } + + Vector & operator = (const Vector &other) + { + this->resize(other.mLength); + for(size_t i = 0; i < this->mLength; i++) + { + this->mData[i] = other.mData[i]; + } + return *this; + } + explicit Vector(size_t initialReserve) : Vector() { this->reserve(initialReserve); } + ~Vector() + { + if(this->mData != nullptr) { + free(this->mData); + } + } + size_t length() const { return this->mLength; @@ -47,7 +88,7 @@ namespace ker void append(const T &value) { this->reserve(this->mLength + 1); - new (&this->mData[this->mLength - 1]) T(value); + new (&this->mData[this->mLength]) T(value); this->mLength += 1; } @@ -67,6 +108,7 @@ namespace ker new (&this->mData[i]) T (); } } + this->mLength = size; } void reserve(size_t space) @@ -82,6 +124,7 @@ namespace ker free(this->mData); } this->mData = newData; + this->mReserved = space; } T& operator [](size_t idx) diff --git a/src/console.c b/src/console.c index bb5cb4e..a82dda3 100644 --- a/src/console.c +++ b/src/console.c @@ -219,4 +219,4 @@ void kprintf(const char *format, ...) } } va_end(vl); -} \ No newline at end of file +} diff --git a/src/vm.cpp b/src/vm.cpp index a1d4f07..19f5883 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -10,17 +10,120 @@ extern "C" { // extern size_t file01_size; } -char file01[] = "VAR global : INT;\0"; +char file01[] = R"code( +VAR global : INT; +PUB main() | i : INT +BEGIN + print(10, 20, 30); + 0 -> i; + REPEAT + BEGIN + print(i); + i + 1 -> i; + END +END)code"; + +void cpp_test(); + +class PrintMethod : + public Method +{ +public: + Variable invoke(Vector arguments) override; +}; + +Variable PrintMethod::invoke(Vector arguments) +{ + for(auto &var : arguments) + { + var.printval(); + kprintf(" "); + } + kprintf("\n"); + return Variable::Void; +} + +extern "C" void vm_start() +{ + // cpp_test(); + + kprintf("Parse kernel module: "); + Module *module = VM::load(file01, sizeof(file01) - 1); + if(module == nullptr) { + kprintf("Could not load module :(\n"); + return; + } + + kprintf("Module successfully loaded :)\n"); + + module->methods.add("print", new PrintMethod()); + + 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"); + return; + } + + main->invoke({ }); + + delete module; +} + String fn() { return String("keks"); } -extern "C" void vm_start() +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); @@ -33,20 +136,89 @@ extern "C" void vm_start() 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"); - kprintf("Parse kernel module:"); - Module *module = VM::load(file01, sizeof(file01)); - if(module == nullptr) { - kprintf("Could not load module :(\n"); - return; + 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("Module successfully loaded :)\n"); - - for(const auto &var : module->variables) + kprintf("Testing ker::Vector:\n"); { - kprintf("Variable: '%s' => '"); - var.second->printval(); - kprintf("\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); } } diff --git a/trainscript/trainscript.y b/trainscript/trainscript.y index 0d006b2..be2370b 100644 --- a/trainscript/trainscript.y +++ b/trainscript/trainscript.y @@ -151,7 +151,7 @@ input: using namespace trainscript; auto *mod = context->module; - Method *method = new Method(mod, $2.body); + ScriptMethod *method = new ScriptMethod(mod, $2.body); method->isPublic = $2.header.isPublic; if($2.header.returnValue) { method->returnValue = ker::Pair( diff --git a/trainscript/tsvm.cpp b/trainscript/tsvm.cpp index 9c723f8..9974fd1 100644 --- a/trainscript/tsvm.cpp +++ b/trainscript/tsvm.cpp @@ -42,9 +42,7 @@ namespace trainscript data.module = module; yylex_init_extra(&data, &data.scanner); - int error = yyparse(&data); - kprintf("[E:%d]", error); - bool valid = error == 0; + bool valid = yyparse(&data) == 0; yylex_destroy(data.scanner); free(internalStorage); @@ -78,7 +76,7 @@ namespace trainscript } } - Variable Method::invoke(ker::Vector arguments) + Variable ScriptMethod::invoke(ker::Vector arguments) { LocalContext context(this->module); diff --git a/trainscript/tsvm.hpp b/trainscript/tsvm.hpp index be627a5..61197b0 100644 --- a/trainscript/tsvm.hpp +++ b/trainscript/tsvm.hpp @@ -164,7 +164,15 @@ namespace trainscript } }; - class Method + class Method + { + public: + virtual ~Method() { } + virtual Variable invoke(ker::Vector arguments) = 0; + }; + + class ScriptMethod : + public Method { public: Module *module; @@ -174,12 +182,12 @@ namespace trainscript ker::Dictionary locals; ker::Pair returnValue; - Method(Module *module, Instruction *block) : module(module), block(block) + ScriptMethod(Module *module, Instruction *block) : module(module), block(block) { } - Variable invoke(ker::Vector arguments); + Variable invoke(ker::Vector arguments) override; }; class Module @@ -193,12 +201,12 @@ namespace trainscript Method *method(const char *name) { - return this->methods[name]; + return this->methods.get(name); } Variable *variable(const char *name) { - return this->variables[name]; + return this->variables.get(name); } };