First buildin function for an object is done

This commit is contained in:
Ryan Ward 2020-10-21 23:02:23 -04:00
parent 52774b72cd
commit e738dae0c9
16 changed files with 218 additions and 65 deletions

View File

@ -5,6 +5,7 @@
#include "enviroment.h" #include "enviroment.h"
namespace dms { namespace dms {
struct character : enviroment { struct character : enviroment {
character();
bool seen = false; bool seen = false;
double spd = 100; double spd = 100;
bool fullname = true; bool fullname = true;

View File

@ -4,7 +4,7 @@
using namespace dms; using namespace dms;
//typedef void(*FNPTR)(); //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()); utils::print(args->args[0]->getPrintable());
return buildValue("I work!"); return buildValue("I work!");
} }

View File

@ -1,28 +1,44 @@
#include "Invoker.h" #include "Invoker.h"
#include "dms_state.h" #include "dms_state.h"
namespace dms { 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)) { if (preventOverwriting && funcs.count(str)) {
return false; return false;
} }
funcs.insert_or_assign(str, f); funcs.insert_or_assign(str, f);
return true; 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)) { if (preventoverride && funcs.count(str)) {
return false; return false;
} }
funcs.insert_or_assign(str, f); funcs.insert_or_assign(str, f);
return true; 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)) { if (funcs.count(str)) {
for (int i = 0; i < args->args.size() - 1; i++) { for (int i = 0; i < args->args.size() - 1; i++) {
args->args[i] = args->args[i]->resolve(state->memory); 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!" }); state->push_error(errors::error{ errors::non_existing_function, "Attempt to call a nil value!" });
return buildNil(); return nullptr;
}
std::unordered_map<std::string, value* (*)(void*, dms_state*, dms_args*)> Invoker::Export() {
return funcs;
}
void Invoker::Import(std::unordered_map<std::string, value* (*)(void*, dms_state*, dms_args*)> 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;
} }
} }

View File

@ -4,11 +4,16 @@
namespace dms { namespace dms {
struct dms_state; struct dms_state;
class Invoker { class Invoker {
std::unordered_map<std::string, value* (*)(dms_state*, dms_args*)>funcs; std::unordered_map<std::string, value* (*)(void*, dms_state*, dms_args*)>funcs;
void* self = nullptr;
public: public:
bool preventOverwriting = true; bool preventOverwriting = true;
bool registerFunction(std::string str, value* (*f)(dms_state*, dms_args*)); bool registerFunction(std::string str, value* (*f)(void*, 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 preventoverride);
void _init(void* ref);
value* Invoke(std::string str, dms_state* state, dms_args* args); value* Invoke(std::string str, dms_state* state, dms_args* args);
std::unordered_map<std::string, value* (*)(void*, dms_state*, dms_args*)> Export();
// Imports methods from another Invoker, this will add and overwrite any method with the same name
void Import(std::unordered_map<std::string, value* (*)(void*, dms_state*, dms_args*)> tempf);
}; };
} }

View File

@ -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<token> 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; return false;
} }
bool LineParser::match_process_goto(tokenstream* stream) { bool LineParser::match_process_goto(tokenstream* stream) {

View File

@ -1,6 +1,19 @@
#include "character.h" #include "character.h"
#include "utils.h" #include "utils.h"
namespace dms { 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() { std::string character::getName() {
if (has("nickname")) { if (has("nickname")) {
return values["nickname"]->getPrintable(); return values["nickname"]->getPrintable();

View File

@ -48,5 +48,6 @@ const std::string dms::codes::list[] = {
"HALT", "HALT",
"FILE", "FILE",
"GC", "GC",
"ASID" "ASID",
"OFUN"
}; };

View File

@ -50,7 +50,8 @@ namespace dms::codes {
HALT, HALT,
FILE, FILE,
GC, GC,
ASID ASID,
OFUN
}; };
extern const std::string list[]; extern const std::string list[];
static bool isControl(const op code) { static bool isControl(const op code) {

View File

@ -56,6 +56,9 @@ namespace dms {
bool dms_state::characterExists(std::string bk_name) { bool dms_state::characterExists(std::string bk_name) {
return (chunks.count(bk_name) && chunks[bk_name]->type == blocktype::bt_character); 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) { bool dms_state::blockExists(std::string bk_name) {
return (chunks.count(bk_name)); return (chunks.count(bk_name));
} }

View File

@ -21,7 +21,7 @@ namespace dms {
std::vector<value*> garbage; std::vector<value*> garbage;
std::unordered_map<std::string, chunk*> chunks; std::unordered_map<std::string, chunk*> chunks;
std::unordered_map<std::string, character*> characters; std::unordered_map<std::string, character*> characters;
std::unordered_map<std::string, enviroment*> enviroments; std::unordered_map<std::string, enviroment*> environments;
std::unordered_map<std::string, size_t> labels; std::unordered_map<std::string, size_t> labels;
std::string entry = "$undefined"; std::string entry = "$undefined";
std::unordered_map<std::string, bool> enables; std::unordered_map<std::string, bool> enables;
@ -49,11 +49,12 @@ namespace dms {
// Gets or creates a character // Gets or creates a character
character* getCharacter(std::string c); character* getCharacter(std::string c);
enviroment* getEnviroment(std::string c); enviroment* getEnvironment(std::string c);
bool assign(std::unordered_map<std::string, value*>* mem,value* var, value* val); bool assign(std::unordered_map<std::string, value*>* mem,value* var, value* val);
size_t seek(std::string label,std::vector<cmd*> cmds ,codes::op code, size_t pos); size_t seek(std::string label,std::vector<cmd*> cmds ,codes::op code, size_t pos);
bool characterExists(std::string bk_name); bool characterExists(std::string bk_name);
bool environmentExists(std::string bk_name);
bool blockExists(std::string bk_name); bool blockExists(std::string bk_name);
bool typeAssert(value* val, datatypes type); bool typeAssert(value* val, datatypes type);
bool run(); bool run();

View File

@ -26,9 +26,9 @@ namespace dms {
} }
} }
} }
enviroment* dms_state::getEnviroment(std::string env) { enviroment* dms_state::getEnvironment(std::string env) {
if (enviroments.count(env)) { if (environments.count(env)) {
return enviroments[env]; return environments[env];
} }
else { else {
if (blockExists(env)) { if (blockExists(env)) {
@ -36,7 +36,7 @@ namespace dms {
if (!run(env, &e->values)) { if (!run(env, &e->values)) {
return nullptr; return nullptr;
} }
enviroments.insert_or_assign(env, e); environments.insert_or_assign(env, e);
handler->OnEnviromentCreated(this, e); handler->OnEnviromentCreated(this, e);
return e; return e;
} }
@ -71,6 +71,9 @@ namespace dms {
checkCharacter(cc, "lname", datatypes::string); checkCharacter(cc, "lname", datatypes::string);
checkCharacter(cc, "unknown", datatypes::string); checkCharacter(cc, "unknown", datatypes::string);
checkCharacter(cc, "known", datatypes::boolean); checkCharacter(cc, "known", datatypes::boolean);
if (cc->get("known")->b->getValue() == true) {
cc->seen = true;
}
} }
else { else {
return nullptr; return nullptr;
@ -174,6 +177,31 @@ namespace dms {
} }
return true; return true;
break; 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: case FUNC:
{ {
std::string funcname = c->args.args[0]->getPrintable(); std::string funcname = c->args.args[0]->getPrintable();
@ -183,6 +211,8 @@ namespace dms {
args.push(c->args.args[i]); args.push(c->args.args[i]);
} }
value* ret = invoker.Invoke(funcname, this, &args); value* ret = invoker.Invoke(funcname, this, &args);
if (ret == nullptr)
return false;
if (assn->type != datatypes::nil) { if (assn->type != datatypes::nil) {
assign(mem, assn, ret); assign(mem, assn, ret);
} }
@ -195,8 +225,8 @@ namespace dms {
value* assn = c->args.args[3]->resolve(*mem); 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 if (env->type == datatypes::block && blockExists(env->getPrintable())) { // If this is a block let's handle this
enviroment* e = nullptr; enviroment* e = nullptr;
if (enviroments.count(env->getPrintable())) { if (environments.count(env->getPrintable())) {
e = enviroments[env->getPrintable()]; e = environments[env->getPrintable()];
} }
else if (characters.count(env->getPrintable())) { else if (characters.count(env->getPrintable())) {
e = characters[env->getPrintable()]; e = characters[env->getPrintable()];
@ -226,8 +256,8 @@ namespace dms {
value* indx = c->args.args[2]->resolve(*mem); 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 if (env->type == datatypes::block && blockExists(env->getPrintable())) { // If this is a block let's handle this
enviroment* e = nullptr; enviroment* e = nullptr;
if (enviroments.count(env->getPrintable())) { if (environments.count(env->getPrintable())) {
e = enviroments[env->getPrintable()]; e = environments[env->getPrintable()];
} }
else if (characters.count(env->getPrintable())) { else if (characters.count(env->getPrintable())) {
e = characters[env->getPrintable()]; e = characters[env->getPrintable()];

Binary file not shown.

View File

@ -62,77 +62,93 @@ Line <17> newline
Line <17> newline Line <17> newline
Line <18> newline Line <18> newline
Line <18> newline Line <18> newline
Line <19> string Ryan's name is `Ryan`
Line <19> newline 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 <20> newline Line <20> newline
Line <21> name hmm Line <21> string Ryan's name is `Ryan`
Line <21> equal =
Line <21> name invokeTest
Line <21> parao (
Line <21> string Do I work?
Line <21> parac )
Line <21> newline Line <21> newline
Line <21> newline Line <21> newline
Line <22> newline Line <22> newline
Line <22> newline Line <22> newline
Line <23> string The return of hmm is "`hmm`"
Line <23> newline
Line <23> newline Line <23> newline
Line <24> newline Line <24> 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 <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 <26> newline Line <26> newline
Line <27> string The return of hmm is "`hmm`"
Line <27> newline
Line <27> newline Line <27> newline
Line <28> newline Line <28> newline
Line <28> newline
Line <29> newline Line <29> newline
Line <30> name unknown Line <29> newline
Line <30> equal = Line <30> bracketo [
Line <30> string Ya boi Line <30> name Bob
Line <30> colon :
Line <30> name char
Line <30> bracketc ]
Line <30> newline Line <30> newline
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 <31> newline
Line <32> name money
Line <32> equal =
Line <32> number 100
Line <32> newline 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 <33> newline
Line <34> name unknown
Line <34> equal =
Line <34> string Ya boi
Line <34> newline Line <34> newline
Line <34> newline Line <34> newline
Line <35> bracketo [ Line <35> name age
Line <35> name newblock Line <35> equal =
Line <35> colon : Line <35> number 0.24
Line <35> name function
Line <35> parao (
Line <35> parac )
Line <35> bracketc ]
Line <35> newline Line <35> newline
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 <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 <37> newline Line <37> newline
Line <38> string huh
Line <38> newline Line <38> newline
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> newline Line <1> newline
Line <1> flag Line <1> flag

View File

@ -2,14 +2,15 @@
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include "value.h" #include "value.h"
#include "Invoker.h"
namespace dms { namespace dms {
enum class env_type { enum class env_type {
env, env,
character, character,
function function
}; };
struct enviroment { struct enviroment : Invoker {
std::string name=""; std::string name = "";
std::unordered_map<std::string, value*> values; std::unordered_map<std::string, value*> values;
env_type type = env_type::env; env_type type = env_type::env;
bool has(std::string index); bool has(std::string index);

View File

@ -16,7 +16,11 @@ using extendedDefine
"Contents of list {`list:1`, `list:2`, `list:3`}" "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?") hmm = invokeTest("Do I work?")

View File

@ -51,8 +51,8 @@ namespace dms {
temp << cha->getName(); 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) { 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->getEnviroment(v->s->getValue()); enviroment* env = state->getEnvironment(v->s->getValue());
if (env->values.count(index)) { if (env->values.count(index)) {
temp << env->values[index]->getPrintable(); temp << env->values[index]->getPrintable();
} }