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"
namespace dms {
struct character : enviroment {
character();
bool seen = false;
double spd = 100;
bool fullname = true;

View File

@ -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!");
}

View File

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

View File

@ -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();

View File

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

View File

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

View File

@ -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));
}

View File

@ -21,7 +21,7 @@ namespace dms {
std::vector<value*> garbage;
std::unordered_map<std::string, chunk*> chunks;
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::string entry = "$undefined";
std::unordered_map<std::string, bool> 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<std::string, value*>* mem,value* var, value* val);
size_t seek(std::string label,std::vector<cmd*> 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();

View File

@ -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()];

Binary file not shown.

View File

@ -62,77 +62,93 @@ Line <17> 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

View File

@ -2,14 +2,15 @@
#include <string>
#include <unordered_map>
#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<std::string, value*> values;
env_type type = env_type::env;
bool has(std::string index);

View File

@ -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?")

View File

@ -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();
}