From e738dae0c901495c812382d3491874dde3fdd489 Mon Sep 17 00:00:00 2001 From: Ryan Ward Date: Wed, 21 Oct 2020 23:02:23 -0400 Subject: [PATCH] First buildin function for an object is done --- DMS/Character.h | 1 + DMS/DMS.cpp | 2 +- DMS/Invoker.cpp | 26 +++++++-- DMS/Invoker.h | 11 ++-- DMS/LineParserMatchProcess.cpp | 61 +++++++++++++++++++++ DMS/character.cpp | 13 +++++ DMS/codes.cpp | 3 +- DMS/codes.h | 3 +- DMS/dms_state.cpp | 3 ++ DMS/dms_state.h | 5 +- DMS/dms_state_interpret.cpp | 46 +++++++++++++--- DMS/dump.bin | Bin 1394 -> 1510 bytes DMS/dump.txt | 94 +++++++++++++++++++-------------- DMS/enviroment.h | 5 +- DMS/test.dms | 6 ++- DMS/value.cpp | 4 +- 16 files changed, 218 insertions(+), 65 deletions(-) diff --git a/DMS/Character.h b/DMS/Character.h index dda4029..e79aa72 100644 --- a/DMS/Character.h +++ b/DMS/Character.h @@ -5,6 +5,7 @@ #include "enviroment.h" namespace dms { struct character : enviroment { + character(); bool seen = false; double spd = 100; bool fullname = true; diff --git a/DMS/DMS.cpp b/DMS/DMS.cpp index 3747d08..0ffb4c0 100644 --- a/DMS/DMS.cpp +++ b/DMS/DMS.cpp @@ -4,7 +4,7 @@ using namespace dms; //typedef void(*FNPTR)(); -value* invokeTest(dms_state* state, dms_args* args) { +value* invokeTest(void* self, dms_state* state, dms_args* args) { utils::print(args->args[0]->getPrintable()); return buildValue("I work!"); } diff --git a/DMS/Invoker.cpp b/DMS/Invoker.cpp index c72f722..a4f8b81 100644 --- a/DMS/Invoker.cpp +++ b/DMS/Invoker.cpp @@ -1,28 +1,44 @@ #include "Invoker.h" #include "dms_state.h" namespace dms { - bool Invoker::registerFunction(std::string str, value* (*f)(dms_state*, dms_args*)) { + bool Invoker::registerFunction(std::string str, value* (*f)(void*, dms_state*, dms_args*)) { if (preventOverwriting && funcs.count(str)) { return false; } funcs.insert_or_assign(str, f); return true; } - bool Invoker::registerFunction(std::string str, value* (*f)(dms_state*, dms_args*), bool preventoverride) { + bool Invoker::registerFunction(std::string str, value* (*f)(void*, dms_state*, dms_args*), bool preventoverride) { if (preventoverride && funcs.count(str)) { return false; } funcs.insert_or_assign(str, f); return true; } - value* Invoker:: Invoke(std::string str, dms_state* state, dms_args* args) { + value* Invoker::Invoke(std::string str, dms_state* state, dms_args* args) { if (funcs.count(str)) { for (int i = 0; i < args->args.size() - 1; i++) { args->args[i] = args->args[i]->resolve(state->memory); } - return funcs[str](state, args); + return funcs[str](self, state, args); } state->push_error(errors::error{ errors::non_existing_function, "Attempt to call a nil value!" }); - return buildNil(); + return nullptr; + } + std::unordered_map Invoker::Export() { + return funcs; + } + void Invoker::Import(std::unordered_map tempf) { + for (auto const& x : tempf) + { + // Copy the contents of the imported invoker into + funcs.insert_or_assign(x.first, x.second); + } + } + void Invoker::_init(void* ref) { + // You can only init once + if (self != nullptr) + return; + self = ref; } } \ No newline at end of file diff --git a/DMS/Invoker.h b/DMS/Invoker.h index d6712d2..e3442c1 100644 --- a/DMS/Invoker.h +++ b/DMS/Invoker.h @@ -4,11 +4,16 @@ namespace dms { struct dms_state; class Invoker { - std::unordered_mapfuncs; + std::unordered_mapfuncs; + void* self = nullptr; public: bool preventOverwriting = true; - bool registerFunction(std::string str, value* (*f)(dms_state*, dms_args*)); - bool registerFunction(std::string str, value* (*f)(dms_state*, dms_args*), bool preventoverride); + bool registerFunction(std::string str, value* (*f)(void*, dms_state*, dms_args*)); + bool registerFunction(std::string str, value* (*f)(void*, dms_state*, dms_args*), bool preventoverride); + void _init(void* ref); value* Invoke(std::string str, dms_state* state, dms_args* args); + std::unordered_map Export(); + // Imports methods from another Invoker, this will add and overwrite any method with the same name + void Import(std::unordered_map tempf); }; } diff --git a/DMS/LineParserMatchProcess.cpp b/DMS/LineParserMatchProcess.cpp index 4c293c7..ab77090 100644 --- a/DMS/LineParserMatchProcess.cpp +++ b/DMS/LineParserMatchProcess.cpp @@ -526,6 +526,67 @@ namespace dms { } } } + else if (stream->match(tokens::name,tokens::dot,tokens::name,tokens::parao)) { + cmd* c = new cmd; + c->opcode = codes::OFUN; + // OFUN obj fname target args + c->args.push(buildVariable(stream->next().name)); // push the obj + stream->next(); // consume the dot + c->args.push(buildVariable(stream->next().name)); // push the fname + // Let's set the target + if (v != nullptr) { + c->args.push(v); // Push the supplied variable + } + else { + c->args.push(buildValue()); // Creates a nil value + } + // Already we have built: FUNC name val + // Next we add arguments this is where things get interesting + tokenstream tempstream; + // This is a balanced consuming method (()(())) + std::vector t = stream->next(tokens::parao, tokens::parac); // Consume and get tokens + if (t.size() == 1) { // No arg function! + current_chunk->addCmd(c); + return true; + } + token end = t.back(); + t.pop_back(); + t.push_back(token{ tokens::seperator,codes::NOOP,"",t[0].line_num }); + t.push_back(token{ tokens::nil,codes::NOOP,"",t[0].line_num }); + t.push_back(end); + tempstream.init(&t); // Turn tokens we consumed into a tokenstream + value* tempval; + token tok; + value* ref = buildVariable(); + // This part we add values to the opcodes for the bytecode FUNC val a1 a2 a3 ... an + while (tempstream.peek().type != tokens::none) { // End of stream + debugInvoker(stream); + tempval = buildVariable(); + tok = tempstream.peek(); + if (tempstream.match(tokens::seperator)) { + // We have a seperator for function arguments + tempstream.next(); // Consume it + cleanup(tempval); // We don't need it + } + else if (match_process_standard(&tempstream, tempval)) { + c->args.push(tempval); + } + else if (tempstream.match(tokens::newline)) { + tempstream.next(); + } + else if (tempstream.match(tokens::parac)) { + cleanup(tempval); + tempstream.next(); + current_chunk->addCmd(c); // We push this onto the chunk after all dependants if any have been handled + //lastCall.pop(); + return true; + } + else { + cleanup(tempval); // Cleanup + badSymbol(&tempstream); + } + } + } return false; } bool LineParser::match_process_goto(tokenstream* stream) { diff --git a/DMS/character.cpp b/DMS/character.cpp index d729d01..a0d1924 100644 --- a/DMS/character.cpp +++ b/DMS/character.cpp @@ -1,6 +1,19 @@ #include "character.h" #include "utils.h" namespace dms { + value* character_setName(void* self, dms_state* state, dms_args* args) { + if(utils::typeassert(*args, datatypes::string)) { + character* me = (character*)self; + me->set("fname", buildValue(args->args[0]->getPrintable())); + } + return buildNil(); + } + character::character() { + // Set the self so the registered function can access themselves + _init(this); + // Here we register the functions that the character object should have + registerFunction("setName", character_setName); + } std::string character::getName() { if (has("nickname")) { return values["nickname"]->getPrintable(); diff --git a/DMS/codes.cpp b/DMS/codes.cpp index 700bd18..066a3fc 100644 --- a/DMS/codes.cpp +++ b/DMS/codes.cpp @@ -48,5 +48,6 @@ const std::string dms::codes::list[] = { "HALT", "FILE", "GC", - "ASID" + "ASID", + "OFUN" }; \ No newline at end of file diff --git a/DMS/codes.h b/DMS/codes.h index f5bc641..13ea8bc 100644 --- a/DMS/codes.h +++ b/DMS/codes.h @@ -50,7 +50,8 @@ namespace dms::codes { HALT, FILE, GC, - ASID + ASID, + OFUN }; extern const std::string list[]; static bool isControl(const op code) { diff --git a/DMS/dms_state.cpp b/DMS/dms_state.cpp index 9ac3d0b..0bbc7c4 100644 --- a/DMS/dms_state.cpp +++ b/DMS/dms_state.cpp @@ -56,6 +56,9 @@ namespace dms { bool dms_state::characterExists(std::string bk_name) { return (chunks.count(bk_name) && chunks[bk_name]->type == blocktype::bt_character); } + bool dms_state::environmentExists(std::string bk_name) { + return (chunks.count(bk_name) && chunks[bk_name]->type == blocktype::bt_env); + } bool dms_state::blockExists(std::string bk_name) { return (chunks.count(bk_name)); } diff --git a/DMS/dms_state.h b/DMS/dms_state.h index 520140e..705e0ae 100644 --- a/DMS/dms_state.h +++ b/DMS/dms_state.h @@ -21,7 +21,7 @@ namespace dms { std::vector garbage; std::unordered_map chunks; std::unordered_map characters; - std::unordered_map enviroments; + std::unordered_map environments; std::unordered_map labels; std::string entry = "$undefined"; std::unordered_map enables; @@ -49,11 +49,12 @@ namespace dms { // Gets or creates a character character* getCharacter(std::string c); - enviroment* getEnviroment(std::string c); + enviroment* getEnvironment(std::string c); bool assign(std::unordered_map* mem,value* var, value* val); size_t seek(std::string label,std::vector cmds ,codes::op code, size_t pos); bool characterExists(std::string bk_name); + bool environmentExists(std::string bk_name); bool blockExists(std::string bk_name); bool typeAssert(value* val, datatypes type); bool run(); diff --git a/DMS/dms_state_interpret.cpp b/DMS/dms_state_interpret.cpp index 14dbdbc..186f3c5 100644 --- a/DMS/dms_state_interpret.cpp +++ b/DMS/dms_state_interpret.cpp @@ -26,9 +26,9 @@ namespace dms { } } } - enviroment* dms_state::getEnviroment(std::string env) { - if (enviroments.count(env)) { - return enviroments[env]; + enviroment* dms_state::getEnvironment(std::string env) { + if (environments.count(env)) { + return environments[env]; } else { if (blockExists(env)) { @@ -36,7 +36,7 @@ namespace dms { if (!run(env, &e->values)) { return nullptr; } - enviroments.insert_or_assign(env, e); + environments.insert_or_assign(env, e); handler->OnEnviromentCreated(this, e); return e; } @@ -71,6 +71,9 @@ namespace dms { checkCharacter(cc, "lname", datatypes::string); checkCharacter(cc, "unknown", datatypes::string); checkCharacter(cc, "known", datatypes::boolean); + if (cc->get("known")->b->getValue() == true) { + cc->seen = true; + } } else { return nullptr; @@ -174,6 +177,31 @@ namespace dms { } return true; break; + case OFUN: + { + std::string obj = c->args.args[0]->getPrintable(); + std::string funcname = c->args.args[1]->getPrintable(); + value* assn = c->args.args[2]; + dms_args args; + for (int i = 3; i < c->args.args.size(); i++) { + args.push(c->args.args[i]); + } + + value* ret = nullptr; + if (characterExists(obj)) { + ret = getCharacter(obj)->Invoke(funcname, this, &args); + } + else if (environmentExists(obj)) { + ret = getEnvironment(obj)->Invoke(funcname, this, &args); + } + //value* ret = invoker.Invoke(funcname, nullptr, this, &args); + if (ret == nullptr) + return false; + if (assn->type != datatypes::nil) { + assign(mem, assn, ret); + } + } + break; case FUNC: { std::string funcname = c->args.args[0]->getPrintable(); @@ -183,6 +211,8 @@ namespace dms { args.push(c->args.args[i]); } value* ret = invoker.Invoke(funcname, this, &args); + if (ret == nullptr) + return false; if (assn->type != datatypes::nil) { assign(mem, assn, ret); } @@ -195,8 +225,8 @@ namespace dms { value* assn = c->args.args[3]->resolve(*mem); if (env->type == datatypes::block && blockExists(env->getPrintable())) { // If this is a block let's handle this enviroment* e = nullptr; - if (enviroments.count(env->getPrintable())) { - e = enviroments[env->getPrintable()]; + if (environments.count(env->getPrintable())) { + e = environments[env->getPrintable()]; } else if (characters.count(env->getPrintable())) { e = characters[env->getPrintable()]; @@ -226,8 +256,8 @@ namespace dms { value* indx = c->args.args[2]->resolve(*mem); if (env->type == datatypes::block && blockExists(env->getPrintable())) { // If this is a block let's handle this enviroment* e = nullptr; - if (enviroments.count(env->getPrintable())) { - e = enviroments[env->getPrintable()]; + if (environments.count(env->getPrintable())) { + e = environments[env->getPrintable()]; } else if (characters.count(env->getPrintable())) { e = characters[env->getPrintable()]; diff --git a/DMS/dump.bin b/DMS/dump.bin index ab98c9a0d635c8f991f1384662c06937e95aad5f..af01380c16c5929918a8715466c61032f4382385 100644 GIT binary patch delta 128 zcmeyw^^AMMo=g|d-~a{IpvuHN^ newline Line <17> newline Line <18> newline Line <18> newline +Line <19> string Ryan's name is `Ryan` Line <19> newline +Line <19> newline +Line <20> name Ryan +Line <20> dot . +Line <20> name setName +Line <20> parao ( +Line <20> string Bryan +Line <20> parac ) Line <20> newline Line <20> newline -Line <21> name hmm -Line <21> equal = -Line <21> name invokeTest -Line <21> parao ( -Line <21> string Do I work? -Line <21> parac ) +Line <21> string Ryan's name is `Ryan` Line <21> newline Line <21> newline Line <22> newline Line <22> newline -Line <23> string The return of hmm is "`hmm`" -Line <23> newline Line <23> newline Line <24> newline Line <24> newline +Line <25> name hmm +Line <25> equal = +Line <25> name invokeTest +Line <25> parao ( +Line <25> string Do I work? +Line <25> parac ) Line <25> newline Line <25> newline -Line <26> bracketo [ -Line <26> name Bob -Line <26> colon : -Line <26> name char -Line <26> bracketc ] Line <26> newline Line <26> newline +Line <27> string The return of hmm is "`hmm`" +Line <27> newline Line <27> newline Line <28> newline +Line <28> newline Line <29> newline -Line <30> name unknown -Line <30> equal = -Line <30> string Ya boi +Line <29> newline +Line <30> bracketo [ +Line <30> name Bob +Line <30> colon : +Line <30> name char +Line <30> bracketc ] Line <30> newline Line <30> newline -Line <31> name age -Line <31> equal = -Line <31> number 0.24 Line <31> newline -Line <31> newline -Line <32> name money -Line <32> equal = -Line <32> number 100 Line <32> newline -Line <32> newline -Line <33> name excited -Line <33> colon : -Line <33> string path/to/file -Line <33> newline Line <33> newline +Line <34> name unknown +Line <34> equal = +Line <34> string Ya boi Line <34> newline Line <34> newline -Line <35> bracketo [ -Line <35> name newblock -Line <35> colon : -Line <35> name function -Line <35> parao ( -Line <35> parac ) -Line <35> bracketc ] +Line <35> name age +Line <35> equal = +Line <35> number 0.24 Line <35> newline Line <35> newline -Line <36> string Test #2 +Line <36> name money +Line <36> equal = +Line <36> number 100 Line <36> newline Line <36> newline -Line <37> string Does it parse this part properly? +Line <37> name excited +Line <37> colon : +Line <37> string path/to/file Line <37> newline Line <37> newline -Line <38> string huh Line <38> newline Line <38> newline -Line <38> eof +Line <39> bracketo [ +Line <39> name newblock +Line <39> colon : +Line <39> name function +Line <39> parao ( +Line <39> parac ) +Line <39> bracketc ] +Line <39> newline +Line <39> newline +Line <40> string Test #2 +Line <40> newline +Line <40> newline +Line <41> string Does it parse this part properly? +Line <41> newline +Line <41> newline +Line <42> string huh +Line <42> newline +Line <42> newline +Line <42> eof Line <1> newline Line <1> newline Line <1> flag diff --git a/DMS/enviroment.h b/DMS/enviroment.h index f063fb0..1ca61b3 100644 --- a/DMS/enviroment.h +++ b/DMS/enviroment.h @@ -2,14 +2,15 @@ #include #include #include "value.h" +#include "Invoker.h" namespace dms { enum class env_type { env, character, function }; - struct enviroment { - std::string name=""; + struct enviroment : Invoker { + std::string name = ""; std::unordered_map values; env_type type = env_type::env; bool has(std::string index); diff --git a/DMS/test.dms b/DMS/test.dms index fdc1a41..2a74b3e 100644 --- a/DMS/test.dms +++ b/DMS/test.dms @@ -16,7 +16,11 @@ using extendedDefine "Contents of list {`list:1`, `list:2`, `list:3`}" - //Ryan:setNickname(Bob,"Bobby") // Not yet implemeted! + "Ryan's name is `Ryan`" + Ryan.setName("Bryan") + "Ryan's name is `Ryan`" + + //Ryan.setNickname(Bob,"Bobby") // Not yet implemeted! hmm = invokeTest("Do I work?") diff --git a/DMS/value.cpp b/DMS/value.cpp index 6fb5211..1e02164 100644 --- a/DMS/value.cpp +++ b/DMS/value.cpp @@ -51,8 +51,8 @@ namespace dms { temp << cha->getName(); } } - else if ((state->chunks.count(v->s->getValue()) && state->chunks[v->s->getValue()]->type == blocktype::bt_env) && state->getEnviroment(v->s->getValue()) != nullptr) { - enviroment* env = state->getEnviroment(v->s->getValue()); + else if ((state->chunks.count(v->s->getValue()) && state->chunks[v->s->getValue()]->type == blocktype::bt_env) && state->getEnvironment(v->s->getValue()) != nullptr) { + enviroment* env = state->getEnvironment(v->s->getValue()); if (env->values.count(index)) { temp << env->values[index]->getPrintable(); }