We run! We finally run!
This commit is contained in:
parent
ec533526df
commit
a22d91903f
10 changed files with 315 additions and 41 deletions
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace ker
|
|||
{
|
||||
public:
|
||||
typedef Pair<Key, Value> Entry;
|
||||
private:
|
||||
public:
|
||||
Vector<Entry> 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<Entry>();
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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<const uint8_t*>(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
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -23,12 +23,53 @@ namespace ker
|
|||
this->reserve(Vector<T>::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)
|
||||
|
|
200
src/vm.cpp
200
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<Variable> arguments) override;
|
||||
};
|
||||
|
||||
Variable PrintMethod::invoke(Vector<Variable> 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<int> &v)
|
||||
{
|
||||
kprintf("v[%d]: ", v.length());
|
||||
for(int i : v) { kprintf("%d,", i); }
|
||||
kprintf("\n");
|
||||
}
|
||||
|
||||
void put(Vector<String> &v)
|
||||
{
|
||||
kprintf("v[%d]: ", v.length());
|
||||
for(String &s : v) { kprintf("[%s],", s.str()); }
|
||||
kprintf("\n");
|
||||
}
|
||||
|
||||
void put(Dictionary<int, int> &d)
|
||||
{
|
||||
kprintf("dict: ");
|
||||
for(auto &it : d)
|
||||
{
|
||||
kprintf("[%d -> %d] ", it.first, it.second);
|
||||
}
|
||||
kprintf("\n");
|
||||
}
|
||||
|
||||
void put(Dictionary<String, String> &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<int, int> a(10, 20);
|
||||
Pair<String, String> 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<int, int> c(a);
|
||||
Pair<String, String> d(b);
|
||||
|
||||
Pair<int, int> e; e = a;
|
||||
Pair<String, String> 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<int> a;
|
||||
a.append(1);
|
||||
a.append(2);
|
||||
a.append(3);
|
||||
|
||||
Vector<int> c;
|
||||
Vector<int> b(a);
|
||||
c = a;
|
||||
|
||||
put(a);
|
||||
put(b);
|
||||
put(c);
|
||||
}
|
||||
{
|
||||
Vector<String> a;
|
||||
a.append("x");
|
||||
a.append("y");
|
||||
a.append("z");
|
||||
|
||||
Vector<String> c;
|
||||
Vector<String> b(a);
|
||||
c = a;
|
||||
|
||||
put(a);
|
||||
put(b);
|
||||
put(c);
|
||||
}
|
||||
|
||||
kprintf("Testing ker::Dictionary:\n");
|
||||
{
|
||||
kprintf("int -> int\n");
|
||||
Dictionary<int, int> 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<int, int> b(a);
|
||||
Dictionary<int, int> c;
|
||||
c = a;
|
||||
|
||||
put(a);
|
||||
put(b);
|
||||
put(c);
|
||||
}
|
||||
|
||||
{
|
||||
kprintf("String -> String\n");
|
||||
Dictionary<String, String> 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<String, String> b(a);
|
||||
Dictionary<String, String> c;
|
||||
c = a;
|
||||
|
||||
put(a);
|
||||
put(b);
|
||||
put(c);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<ker::String, Variable>(
|
||||
|
|
|
@ -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<Variable> arguments)
|
||||
Variable ScriptMethod::invoke(ker::Vector<Variable> arguments)
|
||||
{
|
||||
LocalContext context(this->module);
|
||||
|
||||
|
|
|
@ -164,7 +164,15 @@ namespace trainscript
|
|||
}
|
||||
};
|
||||
|
||||
class Method
|
||||
class Method
|
||||
{
|
||||
public:
|
||||
virtual ~Method() { }
|
||||
virtual Variable invoke(ker::Vector<Variable> arguments) = 0;
|
||||
};
|
||||
|
||||
class ScriptMethod :
|
||||
public Method
|
||||
{
|
||||
public:
|
||||
Module *module;
|
||||
|
@ -174,12 +182,12 @@ namespace trainscript
|
|||
ker::Dictionary<ker::String, Variable> locals;
|
||||
ker::Pair<ker::String, Variable> returnValue;
|
||||
|
||||
Method(Module *module, Instruction *block) : module(module), block(block)
|
||||
ScriptMethod(Module *module, Instruction *block) : module(module), block(block)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Variable invoke(ker::Vector<Variable> arguments);
|
||||
Variable invoke(ker::Vector<Variable> 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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue