diff --git a/DMS/Invoker.cpp b/DMS/Invoker.cpp index a4f8b81..2a9a00d 100644 --- a/DMS/Invoker.cpp +++ b/DMS/Invoker.cpp @@ -1,5 +1,6 @@ #include "Invoker.h" #include "dms_state.h" +#include "utils.h" namespace dms { bool Invoker::registerFunction(std::string str, value* (*f)(void*, dms_state*, dms_args*)) { if (preventOverwriting && funcs.count(str)) { @@ -18,11 +19,11 @@ namespace dms { 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); + args->args[i] = args->args[i]->resolve(state); } 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, utils::concat("Attempt to call '",str,"' a nil value!") }); return nullptr; } std::unordered_map Invoker::Export() { diff --git a/DMS/Invoker.h b/DMS/Invoker.h index e3442c1..452350d 100644 --- a/DMS/Invoker.h +++ b/DMS/Invoker.h @@ -12,6 +12,7 @@ namespace dms { 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); + // Exports the methods from an Invoker object 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/LineParser.h b/DMS/LineParser.h index 9114ad1..8aeb6b3 100644 --- a/DMS/LineParser.h +++ b/DMS/LineParser.h @@ -75,7 +75,7 @@ namespace dms { bool match_process_wait(tokenstream* stream); bool match_process_standard(tokenstream* stream, value* v = nullptr); // All types that are matchable are handled here! bool match_process_index(tokenstream* stream,value* v = nullptr, bool leftside = false); - + bool match_process_return(tokenstream* stream); // Build void buildGoto(std::string g, bool v = false); diff --git a/DMS/LineParserMatchProcess.cpp b/DMS/LineParserMatchProcess.cpp index ab77090..f69609d 100644 --- a/DMS/LineParserMatchProcess.cpp +++ b/DMS/LineParserMatchProcess.cpp @@ -273,6 +273,31 @@ namespace dms { } return false; } + bool LineParser::match_process_return(tokenstream* stream) { + // Only handle this inside of a function block! + if (current_chunk->type == blocktype::bt_method) { + if (stream->match(tokens::ret)) { + cmd* c = new cmd; + c->opcode = codes::RETN; + value* ref = buildVariable(); + stream->next(); + if (match_process_standard(stream, ref)) { + c->args.push(ref); + current_chunk->addCmd(c); + return true; + } + else { + badSymbol(); + return false; + } + } + } + else if(stream->match(tokens::ret)) { + stream->next(); + badSymbol(); + } + return false; + } bool LineParser::match_process_assignment(tokenstream* stream) { value* v = buildVariable(); v->set(); diff --git a/DMS/LineParserParse.cpp b/DMS/LineParserParse.cpp index 97d94c0..1c64eac 100644 --- a/DMS/LineParserParse.cpp +++ b/DMS/LineParserParse.cpp @@ -489,9 +489,9 @@ namespace dms { // This will probably be the toughest one of them all } } - // Display cmd must be first!!! + // Let's handle function stuff! + match_process_return(stream); match_process_disp(stream); // Match and process dialogue - if (stream->match(tokens::newline,tokens::label)) { // Match and process labels stream->next(); buildLabel(stream->next().name); diff --git a/DMS/codes.h b/DMS/codes.h index 13ea8bc..a130545 100644 --- a/DMS/codes.h +++ b/DMS/codes.h @@ -3,55 +3,55 @@ #include namespace dms::codes { enum op { - NOOP, - ENTR, - ENAB, - DISA, - LOAD, - VERN, - USIN, + NOOP, // Done + ENTR, // Done + ENAB, // Done + DISA, // Done + LOAD, // Done + VERN, // Done + USIN, // TODO STAT, - DISP, - ASGN, + DISP, // Done + ASGN, // Done LABL, - CHOI, + CHOI, // Done OPTN, FORE, WHLE, - FUNC, + FUNC, // Done IFFF, ELIF, ELSE, DEFN, SKIP, COMP, - INDX, + INDX, // Done JMPZ, - INST, + INST, // Done ERRO, GOTO, - JUMP, + JUMP, // Done RETN, - EXIT, + EXIT, // Done DEBG, - DSPD, + DSPD, // Todo DACT, - WAIT, - APND, - SSPK, - ADD, - SUB, - MUL, - DIV, - POW, - MOD, - LIST, - LINE, - HALT, + WAIT, // Done + APND, // Done + SSPK, // Done + ADD, // Done + SUB, // Done + MUL, // Done + DIV, // Done + POW, // Done + MOD, // Done + LIST, // Done + LINE, // Done + HALT, // Todo FILE, GC, - ASID, - OFUN + ASID, // Done + OFUN // Done }; extern const std::string list[]; static bool isControl(const op code) { diff --git a/DMS/dms_state.cpp b/DMS/dms_state.cpp index 0bbc7c4..82be103 100644 --- a/DMS/dms_state.cpp +++ b/DMS/dms_state.cpp @@ -17,6 +17,12 @@ namespace dms { chunks["$INIT"]->addCmd(c); c = new cmd; } + else if (val->type == blocktype::bt_method) { + c->opcode = codes::RETN; + c->args.push(buildNil()); + val->addCmd(c); + c = new cmd; + } } c->opcode = codes::JUMP; @@ -28,13 +34,44 @@ namespace dms { if (!handler->OnStateInit(this)) stop = true; } + std::unordered_map* dms_state::getMem() { + return mem_stack.top(); + } + void dms_state::pushMem() { + mem_stack.push(new std::unordered_map); + } + void dms_state::popMem() { + mem_stack.pop(); + } + value* dms::blockInvoke(void* self, dms_state* state, dms_args* args) { + std::string func = state->call_stack.top(); + if (state->functionExists(func)) { + state->call_stack.pop(); + value* ret = nullptr; + state->pushMem(); + std::unordered_map* Fmem = state->getMem(); + for (int i = 0; i < state->chunks[func]->params.args.size(); i++) { + Fmem->insert_or_assign(state->chunks[func]->params.args[i]->getPrintable(), args->args[i]->resolve(state)->copy()); + } + state->run(func, Fmem); + ret = state->return_stack.top(); + state->return_stack.pop(); + state->popMem(); + return ret; + } + return buildNil(); + } + void dms_state::pushMem(std::unordered_map* m) { + mem_stack.push(m); + } dms_state::dms_state() { // We should define the defaults for the enables - enables.insert_or_assign("leaking",false); - enables.insert_or_assign("debugging",false); - enables.insert_or_assign("warnings",false); // - enables.insert_or_assign("statesave",true); // Allows you to save state - enables.insert_or_assign("omniscient",false); // Allows you to know who's who when you first meet them + pushMem(&memory); + enables.insert_or_assign("leaking", false); + enables.insert_or_assign("debugging", false); + enables.insert_or_assign("warnings", false); // + enables.insert_or_assign("statesave", true); // Allows you to save state + enables.insert_or_assign("omniscient", false); // Allows you to know who's who when you first meet them enables.insert_or_assign("fullname", true); chunk* c = new chunk; c->name = "$END"; @@ -45,6 +82,7 @@ namespace dms { c->addCmd(cc); push_chunk("$END", c); setHandler(new Handler); // Use the default implementation + invoker.registerFunction("$BlockInvoke$", blockInvoke); } bool dms_state::typeAssert(value* val, datatypes type) { if (val->type != type) { @@ -59,6 +97,9 @@ namespace dms { bool dms_state::environmentExists(std::string bk_name) { return (chunks.count(bk_name) && chunks[bk_name]->type == blocktype::bt_env); } + bool dms_state::functionExists(std::string bk_name) { + return (chunks.count(bk_name) && chunks[bk_name]->type == blocktype::bt_method); + } 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 705e0ae..62efee5 100644 --- a/DMS/dms_state.h +++ b/DMS/dms_state.h @@ -3,21 +3,24 @@ #include #include #include - #include "Invoker.h" #include "errors.h" #include "chunk.h" #include "dms_exceptions.h" #include "Character.h" #include "enviroment.h" +#include namespace dms { struct Handler; + value* blockInvoke(void*, dms_state*, dms_args*); struct dms_state { Handler* handler = nullptr; bool hasFirst = false; Invoker invoker; - std::unordered_map memory; + std::stack call_stack; + std::stack return_stack; + std::stack*> mem_stack; std::vector garbage; std::unordered_map chunks; std::unordered_map characters; @@ -37,7 +40,6 @@ namespace dms { void push_error(errors::error err); void push_warning(errors::error err); void push_chunk(std::string s, chunk* c); - bool run(std::string instance); double version = 1.0; void enable(std::string flag); void disable(std::string flag); @@ -55,17 +57,24 @@ namespace dms { 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 functionExists(std::string bk_name); bool blockExists(std::string bk_name); bool typeAssert(value* val, datatypes type); + std::unordered_map* getMem(); + void pushMem(); + void popMem(); + value* func(); bool run(); bool run(std::string ent,std::unordered_map* mem); + bool run(std::string instance); // This is called once and once only. Dynamically loading code is not a thing! void init(); - bool hasError(); private: // From what I gathered //std::mutex memory_mutex; + std::unordered_map memory; + void pushMem(std::unordered_map*); bool stop = false; bool init_init = false; void init(chunk* chunk, size_t &pos,size_t &max, std::vector& cmds); diff --git a/DMS/dms_state_interpret.cpp b/DMS/dms_state_interpret.cpp index 186f3c5..4e4ed39 100644 --- a/DMS/dms_state_interpret.cpp +++ b/DMS/dms_state_interpret.cpp @@ -177,6 +177,14 @@ namespace dms { } return true; break; + case RETN: + { + value* ret = c->args.args[0]->resolve(this)->copy(); + //c->args.args[0]->nuke(); // Lets clean this up + return_stack.push(ret); + return true; // We did it, let's return this + } + break; case OFUN: { std::string obj = c->args.args[0]->getPrintable(); @@ -207,22 +215,30 @@ namespace dms { std::string funcname = c->args.args[0]->getPrintable(); value* assn = c->args.args[1]; dms_args args; + value* ret = nullptr; for (int i = 2; i < c->args.args.size(); i++) { args.push(c->args.args[i]); } - value* ret = invoker.Invoke(funcname, this, &args); + // If we have a block made function we don't invoke like normal + if (functionExists(funcname)) { + call_stack.push(funcname); + ret = invoker.Invoke("$BlockInvoke$", this, &args); + } + else { + value* ret = invoker.Invoke(funcname, this, &args); + } if (ret == nullptr) return false; if (assn->type != datatypes::nil) { - assign(mem, assn, ret); + assign(getMem(), assn, ret); } } break; case ASID: { value* env = c->args.args[1]; - value* indx = c->args.args[2]->resolve(*mem); - value* assn = c->args.args[3]->resolve(*mem); + value* indx = c->args.args[2]->resolve(this); + value* assn = c->args.args[3]->resolve(this); if (env->type == datatypes::block && blockExists(env->getPrintable())) { // If this is a block let's handle this enviroment* e = nullptr; if (environments.count(env->getPrintable())) { @@ -249,11 +265,65 @@ namespace dms { } break; } + case ADD: + { + value* assn = c->args.args[0]; + value* o1 = c->args.args[1]; + value* o2 = c->args.args[2]; + value* ret = buildValue(o1->resolve(this)->n->getValue()+o2->resolve(this)->n->getValue()); + assign(getMem(), assn, ret); + } + break; + case SUB: + { + value* assn = c->args.args[0]; + value* o1 = c->args.args[1]; + value* o2 = c->args.args[2]; + value* ret = buildValue(o1->resolve(this)->n->getValue() - o2->resolve(this)->n->getValue()); + assign(getMem(), assn, ret); + } + break; + case MUL: + { + value* assn = c->args.args[0]; + value* o1 = c->args.args[1]; + value* o2 = c->args.args[2]; + value* ret = buildValue(o1->resolve(this)->n->getValue() * o2->resolve(this)->n->getValue()); + assign(getMem(), assn, ret); + } + break; + case DIV: + { + value* assn = c->args.args[0]; + value* o1 = c->args.args[1]; + value* o2 = c->args.args[2]; + value* ret = buildValue(o1->resolve(this)->n->getValue() / o2->resolve(this)->n->getValue()); + assign(getMem(), assn, ret); + } + break; + case POW: + { + value* assn = c->args.args[0]; + value* o1 = c->args.args[1]; + value* o2 = c->args.args[2]; + value* ret = buildValue(pow(o1->resolve(this)->n->getValue(), o2->resolve(this)->n->getValue())); + assign(getMem(), assn, ret); + } + break; + case MOD: + { + value* assn = c->args.args[0]; + value* o1 = c->args.args[1]; + value* o2 = c->args.args[2]; + value* ret = buildValue(std::fmod(o1->resolve(this)->n->getValue(),o2->resolve(this)->n->getValue())); + assign(getMem(), assn, ret); + } + break; case INDX: { value* assn = c->args.args[0]; value* env = c->args.args[1]; - value* indx = c->args.args[2]->resolve(*mem); + value* indx = c->args.args[2]->resolve(this); if (env->type == datatypes::block && blockExists(env->getPrintable())) { // If this is a block let's handle this enviroment* e = nullptr; if (environments.count(env->getPrintable())) { @@ -347,7 +417,7 @@ namespace dms { std::string prompt = c->args.args[0]->s->getValue(); std::string fn = c->args.args[1]->s->getValue(); for (size_t i = 2; i < c->args.args.size(); i++) - args.push_back(c->args.args[i]->resolve(*mem)->s->getValue()); + args.push_back(c->args.args[i]->resolve(this)->s->getValue()); size_t npos = handler->handleChoice(this, prompt, args); size_t nnpos = seek(concat("CHOI_", fn, "_", npos),cmds,LABL,npos); if (!nnpos) { @@ -361,8 +431,8 @@ namespace dms { break; case JUMP: // Value assert resolves the data so a variable must eventually equal a string - if (utils::valueassert(c->args, *mem, datatypes::string)) { - std::string block = c->args.args[0]->resolve(*mem)->s->getValue(); + if (utils::valueassert(c->args, this, datatypes::string)) { + std::string block = c->args.args[0]->resolve(this)->s->getValue(); if (chunks[block] == NULL) { push_error(errors::error{ errors::non_existing_block ,utils::concat("Attempted to Jump to a non existing block [",block,"]") }); return false; @@ -376,7 +446,7 @@ namespace dms { } } else { - datatypes set = c->args.args[0]->resolve(*mem)->type; + datatypes set = c->args.args[0]->resolve(this)->type; push_error(errors::error{ errors::invalid_arguments, utils::concat("String expected got ",datatype[set]), true,ln }); return false; } diff --git a/DMS/dump.bin b/DMS/dump.bin index af01380..cb4c772 100644 Binary files a/DMS/dump.bin and b/DMS/dump.bin differ diff --git a/DMS/dump.txt b/DMS/dump.txt index 3f44c13..4c66014 100644 --- a/DMS/dump.txt +++ b/DMS/dump.txt @@ -22,6 +22,9 @@ Line <6> name fullname Line <6> newline Line <6> newline Line <7> newline +Line <8> flag +Line <8> name debugging +Line <8> newline Line <8> newline Line <9> flag Line <9> string loadtest.dms @@ -42,113 +45,87 @@ Line <13> name main Line <13> bracketc ] Line <13> newline Line <13> newline +Line <14> string Time to test function calls! Line <14> newline Line <14> newline -Line <15> name list +Line <15> name val Line <15> equal = -Line <15> cbracketo { -Line <15> string Hello +Line <15> name newblock +Line <15> parao ( +Line <15> number 1 Line <15> seperator , Line <15> number 2 Line <15> seperator , Line <15> number 3 -Line <15> cbracketc } +Line <15> parac ) Line <15> newline Line <15> newline +Line <16> string val = `val` Line <16> newline Line <16> newline -Line <17> string Contents of list {`list:1`, `list:2`, `list:3`} Line <17> newline Line <17> newline +Line <18> bracketo [ +Line <18> name Bob +Line <18> colon : +Line <18> name char +Line <18> bracketc ] 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> string Ryan's name is `Ryan` -Line <21> newline Line <21> newline +Line <22> name unknown +Line <22> equal = +Line <22> string Some Random Guy Line <22> newline Line <22> newline +Line <23> name age +Line <23> equal = +Line <23> number 0.24 Line <23> newline +Line <23> newline +Line <24> name money +Line <24> equal = +Line <24> number 100 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> name excited +Line <25> colon : +Line <25> string path/to/file Line <25> newline Line <25> newline Line <26> newline Line <26> newline -Line <27> string The return of hmm is "`hmm`" +Line <27> bracketo [ +Line <27> name newblock +Line <27> colon : +Line <27> name function +Line <27> parao ( +Line <27> name a +Line <27> seperator , +Line <27> name b +Line <27> seperator , +Line <27> name c +Line <27> parac ) +Line <27> bracketc ] Line <27> newline Line <27> newline +Line <28> string Func Arguments: a = `a`, b = `b`, c = `c` Line <28> newline Line <28> newline +Line <29> string Time to return Line <29> newline Line <29> newline -Line <30> bracketo [ -Line <30> name Bob -Line <30> colon : -Line <30> name char -Line <30> bracketc ] +Line <30> ret +Line <30> name a +Line <30> plus + +Line <30> name b +Line <30> plus + +Line <30> name c Line <30> newline Line <30> newline -Line <31> newline -Line <32> newline -Line <33> newline -Line <34> name unknown -Line <34> equal = -Line <34> string Ya boi -Line <34> newline -Line <34> newline -Line <35> name age -Line <35> equal = -Line <35> number 0.24 -Line <35> newline -Line <35> newline -Line <36> name money -Line <36> equal = -Line <36> number 100 -Line <36> newline -Line <36> newline -Line <37> name excited -Line <37> colon : -Line <37> string path/to/file -Line <37> newline -Line <37> newline -Line <38> newline -Line <38> newline -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 <30> eof Line <1> newline Line <1> newline Line <1> flag diff --git a/DMS/test.dms b/DMS/test.dms index 2a74b3e..0c249c0 100644 --- a/DMS/test.dms +++ b/DMS/test.dms @@ -5,38 +5,26 @@ enable forseelabels enable savestate disable fullname //enable leaking -//enable debugging +enable debugging loadfile "loadtest.dms" version 0.2 using extendedDefine [main] - - list = {"Hello",2,3} - - "Contents of list {`list:1`, `list:2`, `list:3`}" - - "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?") - - "The return of hmm is \"`hmm`\"" - + "Time to test function calls!" + val = newblock(1,2,3) + "val = `val`" [Bob:char] //fname = "Bob" //known = true // defaults to false //lname = "Johnson" // defaults to "" - unknown = "Ya boi" + unknown = "Some Random Guy" age = .24 money = 100 excited: "path/to/file" -[newblock:function()] - "Test #2" - "Does it parse this part properly?" - "huh" +[newblock:function(a,b,c)] + "Func Arguments: a = `a`, b = `b`, c = `c`" + "Time to return" + return a+b+c diff --git a/DMS/token.h b/DMS/token.h index e774924..1004c60 100644 --- a/DMS/token.h +++ b/DMS/token.h @@ -49,7 +49,7 @@ namespace dms::tokens { dollar, ampersand, nil, - pipe + pipe, };//stream, t_vec, line, isNum, buffer struct token { tokentype type = noop; diff --git a/DMS/utils.cpp b/DMS/utils.cpp index f54e457..c36817d 100644 --- a/DMS/utils.cpp +++ b/DMS/utils.cpp @@ -41,31 +41,31 @@ namespace dms::utils { std::generate_n(str.begin(), length, randchar); return str; } - bool valueassert(dms_args args, std::unordered_map memory, datatypes t1, datatypes t2, datatypes t3, datatypes t4, datatypes t5, datatypes t6, datatypes t7, datatypes t8, datatypes t9, datatypes t10, datatypes t11, datatypes t12) { + bool valueassert(dms_args args, dms_state* state, datatypes t1, datatypes t2, datatypes t3, datatypes t4, datatypes t5, datatypes t6, datatypes t7, datatypes t8, datatypes t9, datatypes t10, datatypes t11, datatypes t12) { size_t size = args.args.size(); datatypes types[12] = { t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12 }; if (size >= 4) for (size_t i = 0; i < 4; i++) { - if (args.args[i]->resolve(memory)->type != types[i]) + if (args.args[i]->resolve(state)->type != types[i]) return false; } else for (size_t i = 0; i < size; i++) { - if (args.args[i]->resolve(memory)->type != types[i]) + if (args.args[i]->resolve(state)->type != types[i]) return false; } return true; } - bool valueassertall(dms_args args, std::unordered_map memory, datatypes t1) { + bool valueassertall(dms_args args, dms_state* state, datatypes t1) { size_t size = args.args.size(); if (size >= 4) for (size_t i = 0; i < 4; i++) { - if (args.args[i]->resolve(memory)->type != t1) + if (args.args[i]->resolve(state)->type != t1) return false; } else for (size_t i = 0; i < size; i++) { - if (args.args[i]->resolve(memory)->type != t1) + if (args.args[i]->resolve(state)->type != t1) return false; } return true; diff --git a/DMS/utils.h b/DMS/utils.h index 01d98a8..f63a986 100644 --- a/DMS/utils.h +++ b/DMS/utils.h @@ -27,8 +27,8 @@ namespace dms::utils { std::string random_string(size_t length); bool typeassert(dms_args args, datatypes t1=nil, datatypes t2 = nil, datatypes t3 = nil, datatypes t4 = nil, datatypes t5 = nil, datatypes t6 = nil, datatypes t7 = nil, datatypes t8 = nil, datatypes t9 = nil, datatypes t10 = nil, datatypes t11 = nil, datatypes t12 = nil); //Type asserting is mostly an internal thing for build in methods. It's not needed for dms code! bool typeassert(dms_state* state, dms_args args, datatypes t1 = nil, datatypes t2 = nil, datatypes t3 = nil, datatypes t4 = nil, datatypes t5 = nil, datatypes t6 = nil, datatypes t7 = nil, datatypes t8 = nil, datatypes t9 = nil, datatypes t10 = nil, datatypes t11 = nil, datatypes t12 = nil); - bool valueassert(dms_args args, std::unordered_map memory, datatypes t1 = nil, datatypes t2 = nil, datatypes t3 = nil, datatypes t4 = nil, datatypes t5 = nil, datatypes t6 = nil, datatypes t7 = nil, datatypes t8 = nil, datatypes t9 = nil, datatypes t10 = nil, datatypes t11 = nil, datatypes t12 = nil); - bool valueassertall(dms_args args, std::unordered_map memory, datatypes t1); + bool valueassert(dms_args args, dms_state* state, datatypes t1 = nil, datatypes t2 = nil, datatypes t3 = nil, datatypes t4 = nil, datatypes t5 = nil, datatypes t6 = nil, datatypes t7 = nil, datatypes t8 = nil, datatypes t9 = nil, datatypes t10 = nil, datatypes t11 = nil, datatypes t12 = nil); + bool valueassertall(dms_args args, dms_state* state, datatypes t1); std::string resolveTypes(datatypes t1 = nil, datatypes t2 = nil, datatypes t3 = nil, datatypes t4 = nil, datatypes t5 = nil, datatypes t6 = nil, datatypes t7 = nil, datatypes t8 = nil, datatypes t9 = nil, datatypes t10 = nil, datatypes t11 = nil, datatypes t12 = nil); bool isalphanum(std::string str); bool isalpha(std::string str); diff --git a/DMS/value.cpp b/DMS/value.cpp index 1e02164..d5b998c 100644 --- a/DMS/value.cpp +++ b/DMS/value.cpp @@ -11,9 +11,29 @@ namespace dms { // Values at runtime aren't "Deleted, they are set to nil" // At the end we actually delete them! } - value* value::resolve(std::unordered_map memory) { - if (type == datatypes::variable && this!=memory[this->s->getValue()]) { - return memory[s->getValue()]->resolve(memory); // Variable types return the value + value* value::copy() { + value* newVal = new value; + newVal->type = type; + newVal->c = c; + newVal->e = e; + if (type == datatypes::block || type == datatypes::string || type == datatypes::variable) { + newVal->s = buildString(s->getValue()); + } + else if (type == datatypes::boolean) { + newVal->b = buildBool(b->getValue()); + } + else if (type == datatypes::number) { + newVal->n = buildNumber(n->getValue()); + } + else if (type == datatypes::nil) { + delete newVal; + return buildNil(); + } + return newVal; + } + value* value::resolve(dms_state* state) { + if (type == datatypes::variable && this!=(*state->getMem())[this->s->getValue()]) { + return (*state->getMem())[s->getValue()]->resolve(state); // Variable types return the value } return this; } @@ -39,8 +59,8 @@ namespace dms { ind.clear(); varStart = false; indStart = false; - if (state->memory.count(lookup)) { - value* v = state->memory[lookup]; + if (state->getMem()->count(lookup)) { + value* v = (*state->getMem())[lookup]; if (v->type == datatypes::block) { if ((state->chunks.count(v->s->getValue()) && state->chunks[v->s->getValue()]->type == blocktype::bt_character) && state->getCharacter(v->s->getValue())!=nullptr) { character* cha = state->getCharacter(v->s->getValue()); @@ -64,14 +84,14 @@ namespace dms { temp << "nil"; } } - else if (v->resolve(state->memory)->type == datatypes::env) { - if(v->resolve(state->memory)->e->ipart.size()> std::stoi(index)) - temp << v->resolve(state->memory)->e->ipart[std::stoi(index)-1]->getPrintable(); + else if (v->resolve(state)->type == datatypes::env) { + if(v->resolve(state)->e->ipart.size()> std::stoi(index)) + temp << v->resolve(state)->e->ipart[std::stoi(index)-1]->getPrintable(); else temp << "nil"; } else { - temp << v->resolve(state->memory)->getPrintable(); + temp << v->resolve(state)->getPrintable(); } } else { @@ -100,8 +120,8 @@ namespace dms { var.str(""); var.clear(); varStart = false; - if (state->memory.count(lookup)) { - value* v = state->memory[lookup]; + if (state->getMem()->count(lookup)) { + value* v = (*state->getMem())[lookup]; if (v->type == datatypes::block) { if (state->getCharacter(v->s->getValue())) { temp << state->characters[v->s->getValue()]->getName(); @@ -111,7 +131,7 @@ namespace dms { } } else { - temp << v->resolve(state->memory)->getPrintable(); + temp << v->resolve(state)->getPrintable(); } } else { diff --git a/DMS/value.h b/DMS/value.h index 213e484..06dccdb 100644 --- a/DMS/value.h +++ b/DMS/value.h @@ -74,7 +74,8 @@ namespace dms { dms_env* e = nullptr; dms_custom* c = nullptr; value(); - value* resolve(std::unordered_map map); + value* resolve(dms_state*); + value* copy(); void nuke(); void set(dms_string* str); void set(dms_boolean* bo);