From 34208eacff6b315d71f7e1f313769b902443a448 Mon Sep 17 00:00:00 2001 From: Ryan Ward Date: Thu, 12 Nov 2020 00:02:07 -0500 Subject: [PATCH] Rewrote so much code --- DMS/DMS.cpp | 13 +- DMS/DMS.vcxproj | 4 +- DMS/DMS.vcxproj.filters | 12 +- DMS/Handlers.cpp | 4 +- DMS/Invoker.cpp | 16 +- DMS/Invoker.h | 12 +- DMS/LineParser.h | 10 +- DMS/LineParserBuilds.cpp | 18 +- DMS/LineParserMatchProcess.cpp | 195 ++++++------- DMS/LineParserParse.cpp | 32 ++- DMS/LineParserUtils.cpp | 22 +- DMS/character.cpp | 14 +- DMS/cmd.h | 2 +- DMS/dms.h | 2 + DMS/dms_custom.cpp | 32 +-- DMS/dms_list.h | 11 + DMS/dms_state.cpp | 61 ++-- DMS/dms_state.h | 19 +- DMS/dms_state_interpret.cpp | 254 +++++++++-------- DMS/dump.bin | Bin 1742 -> 2038 bytes DMS/dump.txt | 495 +++++++++++++++++++-------------- DMS/enviroment.cpp | 6 +- DMS/enviroment.h | 7 +- DMS/loadtest.dms | 2 - DMS/memory.cpp | 13 + DMS/memory.h | 14 + DMS/number_utils.cpp | 35 --- DMS/string_utils.cpp | 189 ------------- DMS/test.dms | 30 +- DMS/utils.cpp | 20 +- DMS/utils.h | 4 +- DMS/value.cpp | 457 ++++++++++++++++++++---------- DMS/value.h | 161 ++++------- 33 files changed, 1095 insertions(+), 1071 deletions(-) create mode 100644 DMS/dms_list.h create mode 100644 DMS/memory.cpp create mode 100644 DMS/memory.h delete mode 100644 DMS/string_utils.cpp diff --git a/DMS/DMS.cpp b/DMS/DMS.cpp index 0ffb4c0..8b717ce 100644 --- a/DMS/DMS.cpp +++ b/DMS/DMS.cpp @@ -1,22 +1,25 @@ #include "dms.h" +//#include "memory.h" //#include +//#include "utils.h" #include +#include "value.h" using namespace dms; +using namespace utils; //typedef void(*FNPTR)(); -value* invokeTest(void* self, dms_state* state, dms_args* args) { - utils::print(args->args[0]->getPrintable()); - return buildValue("I work!"); +value invokeTest(void* self, dms_state* state, dms_args* args) { + utils::print(args->args[0].getPrintable()); + return "I work!"; } int main() { + LineParser parser = LineParser("test.dms"); dms_state* state = parser.Parse(); state->invoker.registerFunction("invokeTest", invokeTest); state->dump(); state->run(); - utils::print("Exitcode: ",state->exitcode); - /*HINSTANCE hInst = LoadLibrary(L"C:\\Users\\rayam\\Desktop\\test.dll"); if (!hInst) { diff --git a/DMS/DMS.vcxproj b/DMS/DMS.vcxproj index 41a94eb..b53b930 100644 --- a/DMS/DMS.vcxproj +++ b/DMS/DMS.vcxproj @@ -160,7 +160,7 @@ - + @@ -169,6 +169,7 @@ + @@ -176,6 +177,7 @@ + diff --git a/DMS/DMS.vcxproj.filters b/DMS/DMS.vcxproj.filters index d07c084..5c16978 100644 --- a/DMS/DMS.vcxproj.filters +++ b/DMS/DMS.vcxproj.filters @@ -48,9 +48,6 @@ Source Files - - Source Files\DMS - Source Files\DMS @@ -87,6 +84,9 @@ Source Files\DMS + + Source Files\DMS + @@ -140,5 +140,11 @@ Header Files\DMS + + Header Files\DMS + + + Source Files\DMS + \ No newline at end of file diff --git a/DMS/Handlers.cpp b/DMS/Handlers.cpp index 73e845e..e0563ce 100644 --- a/DMS/Handlers.cpp +++ b/DMS/Handlers.cpp @@ -7,8 +7,8 @@ namespace dms { std::cout << prompt << " "; std::cin >> pos; try { - if (std::stoi(pos) > 0 && std::stoi(pos) < args.size()) - return std::stoi(pos) - 1; + if (std::stoi(pos)-1 >= 0 && std::stoi(pos)-1 < args.size()) + return std::stoi(pos)-1; else throw exceptions::InvalidChoice(); } diff --git a/DMS/Invoker.cpp b/DMS/Invoker.cpp index 2a9a00d..ee4058d 100644 --- a/DMS/Invoker.cpp +++ b/DMS/Invoker.cpp @@ -2,34 +2,34 @@ #include "dms_state.h" #include "utils.h" namespace dms { - bool Invoker::registerFunction(std::string str, value* (*f)(void*, 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)(void*, 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); - } + if(args->size()) + for (int i = 0; i < args->args.size() - 1; i++) + args->args[i] = args->args[i].resolve(state); return funcs[str](self, state, args); } 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() { + std::unordered_map Invoker::Export() { return funcs; } - void Invoker::Import(std::unordered_map tempf) { + void Invoker::Import(std::unordered_map tempf) { for (auto const& x : tempf) { // Copy the contents of the imported invoker into diff --git a/DMS/Invoker.h b/DMS/Invoker.h index 452350d..47d9ab0 100644 --- a/DMS/Invoker.h +++ b/DMS/Invoker.h @@ -4,17 +4,17 @@ 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)(void*, dms_state*, dms_args*)); - bool registerFunction(std::string str, value* (*f)(void*, 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); + value Invoke(std::string str, dms_state* state, dms_args* args); // Exports the methods from an Invoker object - std::unordered_map Export(); + 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); + void Import(std::unordered_map tempf); }; } diff --git a/DMS/LineParser.h b/DMS/LineParser.h index 8aeb6b3..c486f91 100644 --- a/DMS/LineParser.h +++ b/DMS/LineParser.h @@ -64,17 +64,17 @@ namespace dms { bool match_process_debug(tokenstream* stream); bool match_process_disp(tokenstream* stream); bool match_process_choice(tokenstream* stream); - bool match_process_function(tokenstream* stream, value* v=nullptr, bool nested = true); + bool match_process_function(tokenstream* stream, value& v, bool nested = true); bool match_process_goto(tokenstream* stream); bool match_process_jump(tokenstream* stream); bool match_process_exit(tokenstream* stream); - bool match_process_expression(tokenstream* stream, value* v); + bool match_process_expression(tokenstream* stream, value& v); bool match_process_IFFF(tokenstream* stream); bool match_process_assignment(tokenstream* stream); - bool match_process_list(tokenstream* stream, value* v = nullptr); + bool match_process_list(tokenstream* stream, value& v); 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_standard(tokenstream* stream, value& v); // All types that are matchable are handled here! + bool match_process_index(tokenstream* stream,value& v, bool leftside = false); bool match_process_return(tokenstream* stream); // Build diff --git a/DMS/LineParserBuilds.cpp b/DMS/LineParserBuilds.cpp index 1faead0..821362c 100644 --- a/DMS/LineParserBuilds.cpp +++ b/DMS/LineParserBuilds.cpp @@ -4,10 +4,10 @@ namespace dms { cmd* c = new cmd; c->opcode = codes::GOTO; if (v) { - c->args.push(buildVariable(g)); + c->args.push(value(g,datatypes::variable)); } else { - c->args.push(buildValue(g)); + c->args.push(value(g)); } current_chunk->addCmd(c); } @@ -19,8 +19,20 @@ namespace dms { void LineParser::buildLabel(std::string l) { cmd* c = new cmd; c->opcode = codes::LABL; - c->args.push(buildValue(l)); + c->args.push(value(l)); current_chunk->addCmd(c); current_chunk->addLabel(l); } + void LineParser::buildSpeed(double s) { + cmd* c = new cmd; + c->opcode = codes::DSPD; + c->args.push(value(s)); + current_chunk->addCmd(c); + } + void LineParser::buildWait(double w) { + cmd* c = new cmd; + c->opcode = codes::WAIT; + c->args.push(value(w)); + current_chunk->addCmd(c); + } } \ No newline at end of file diff --git a/DMS/LineParserMatchProcess.cpp b/DMS/LineParserMatchProcess.cpp index f69609d..bfbf164 100644 --- a/DMS/LineParserMatchProcess.cpp +++ b/DMS/LineParserMatchProcess.cpp @@ -3,7 +3,7 @@ using namespace dms::tokens; using namespace dms::utils; // TODO: process if elseif else statements, for loops and while loops namespace dms { - bool LineParser::match_process_standard(tokenstream* stream, value* v) { + bool LineParser::match_process_standard(tokenstream* stream, value& v) { if (match_process_expression(stream, v)) { return true; } @@ -17,38 +17,38 @@ namespace dms { return true; } else if (stream->match(tokens::True)) { - v->set(buildBool(true)); + v.set(buildBool(true)); stream->next(); return true; } else if (stream->match(tokens::False)) { - v->set(buildBool(false)); + v.set(buildBool(false)); stream->next(); return true; } else if (stream->match(tokens::number)) { - v->set(buildNumber(std::stod(stream->next().name))); + v.set(std::stod(stream->next().name)); return true; } else if (stream->match(tokens::string)) { - v->set(buildString(stream->next().name)); + v.set(buildString(stream->next().name)); return true; } else if (stream->match(tokens::name)) { - v->set(buildString(stream->next().name)); - v->type = datatypes::variable; + v.set(buildString(stream->next().name)); + v.type = datatypes::variable; return true; } else if (stream->match(tokens::nil)) { stream->next(); - v->set(); + v.set(); return true; } else if (stream->match(tokens::bracketo, tokens::name, tokens::bracketc)) { // We are assigning a block as a variable stream->next(); - v->set(buildString(stream->next().name)); - v->type = datatypes::block; + v.set(buildString(stream->next().name)); + v.type = datatypes::block; stream->next(); return true; } @@ -57,16 +57,16 @@ namespace dms { } return false; } - bool LineParser::match_process_list(tokenstream* stream, value* v) { + bool LineParser::match_process_list(tokenstream* stream, value& v) { if (stream->match(tokens::cbracketo)) { token start = stream->peek(); token ancor = start; std::vector t = stream->next(tokens::cbracketo, tokens::cbracketc); tokenstream tempstream; tempstream.init(&t); - value* ref = buildVariable(); - value* length = new value; - value* dict = nullptr; + value ref = value(datatypes::variable); + value length = value(); + value dict = value(); size_t count = 0; cmd* c = new cmd; c->opcode = codes::LIST; @@ -91,7 +91,7 @@ namespace dms { } // Match Dict else if (tempstream.match(tokens::name,tokens::colon)) { - dict = buildVariable(tempstream.next().name); + dict = value(tempstream.next().name,datatypes::variable); tempstream.next(); if (!match_process_standard(&tempstream,ref)) { badSymbol(); @@ -123,7 +123,7 @@ namespace dms { } current_chunk->addCmd(c); // Build new value - ref = buildVariable(); + ref = value(datatypes::variable); tempstream.next(); } else if (tempstream.match(tokens::cbracketo)) { @@ -133,11 +133,11 @@ namespace dms { badSymbol(&tempstream); } } - length->set(buildNumber(count)); // the second argument is the length of the list! This should be modified if lists are changed at runtime! + length.set((double)count); // the second argument is the length of the list! This should be modified if lists are changed at runtime! c = new cmd; c->opcode = codes::INST; c->args.push(v); - c->args.push(buildNil()); + c->args.push(value()); if (dict != nullptr) { c->args.push(dict); dict = nullptr; @@ -150,10 +150,9 @@ namespace dms { bool LineParser::match_process_disp(tokenstream* stream) { if ((isBlock(bt_block) || isBlock(bt_method)) && stream->match(tokens::newline, tokens::string, tokens::newline)) { stream->next(); // Standard consumption - std::string msg = stream->next().name; cmd* c = new cmd; c->opcode = codes::DISP; - c->args.push(buildValue(msg)); + c->args.push(value(stream->next().name)); current_chunk->addCmd(c); // Add the cmd to the current chunk current_chunk->addCmd(new cmd{ codes::HALT }); return true; @@ -167,7 +166,7 @@ namespace dms { std::string msg = stream->next().name; cmd* c = new cmd; c->opcode = codes::APND; - c->args.push(buildValue(concat(" ", msg))); + c->args.push(value(concat(" ", msg))); current_chunk->addCmd(c); // Add the cmd to the current chunk current_chunk->addCmd(new cmd{ codes::HALT }); return true; @@ -179,8 +178,8 @@ namespace dms { std::string msg = stream->next().name; cmd* c = new cmd; c->opcode = codes::STAT; - c->args.push(buildVariable(name)); - c->args.push(buildValue(msg)); + c->args.push(value(name,datatypes::variable)); + c->args.push(value(msg)); current_chunk->addCmd(c); // Add the cmd to the current chunk } else if ((isBlock(bt_block) || isBlock(bt_method)) && stream->match(tokens::newline, tokens::name, tokens::colon, tokens::string, tokens::newline)) { @@ -192,11 +191,11 @@ namespace dms { std::string msg = stream->next().name; cmd* c = new cmd; c->opcode = codes::SSPK; - c->args.push(buildVariable(name)); + c->args.push(value(name, datatypes::variable)); current_chunk->addCmd(c); c = new cmd; c->opcode = codes::DISP; - c->args.push(buildValue(msg)); + c->args.push(value(msg)); current_chunk->addCmd(c); // Add the cmd to the current chunk current_chunk->addCmd(new cmd{ codes::HALT }); return true; @@ -206,7 +205,7 @@ namespace dms { // Command to set the speaker cmd* c = new cmd; c->opcode = codes::SSPK; - c->args.push(buildVariable(name)); + c->args.push(value(name,datatypes::variable)); current_chunk->addCmd(c); stream->next(); stream->next(); @@ -239,12 +238,12 @@ namespace dms { } cmd* c = new cmd; c->opcode = codes::DACT; - c->args.push(buildValue(mode)); + c->args.push(value(mode)); current_chunk->addCmd(c); // Now build the apnd msg cmd c = new cmd; c->opcode = codes::APND; - c->args.push(buildValue(stream->next().name)); + c->args.push(value(stream->next().name)); current_chunk->addCmd(c); } else { @@ -256,7 +255,7 @@ namespace dms { else if (stream->match(tokens::string)) { cmd* c = new cmd; c->opcode = codes::APND; - c->args.push(buildValue(stream->next().name)); + c->args.push(value(stream->next().name)); current_chunk->addCmd(c); } else if (stream->match(tokens::newline)) { @@ -279,7 +278,7 @@ namespace dms { if (stream->match(tokens::ret)) { cmd* c = new cmd; c->opcode = codes::RETN; - value* ref = buildVariable(); + value ref = value(datatypes::variable); stream->next(); if (match_process_standard(stream, ref)) { c->args.push(ref); @@ -299,11 +298,10 @@ namespace dms { return false; } bool LineParser::match_process_assignment(tokenstream* stream) { - value* v = buildVariable(); - v->set(); + value v = value(); if (match_process_index(stream, v, true)) { cmd* c = current_chunk->cmds.back(); - value* ref = buildVariable(); + value ref = value(datatypes::variable); if (stream->peek().type == tokens::equal) { stream->next(); } @@ -320,26 +318,21 @@ namespace dms { } } else if (stream->match(tokens::name,tokens::equal)) { - value* var = buildVariable(stream->next().name); // The variable that we will be setting stuff to + value var = value(stream->next().name,datatypes::variable); // The variable that we will be setting stuff to stream->next(); // Consume the equal cmd* c = new cmd; c->opcode = codes::ASGN; c->args.push(var); - value* ref = buildVariable(); + value ref = value(datatypes::variable); if (match_process_standard(stream,ref)) { c->args.push(ref); current_chunk->addCmd(c); - delete[] v; return true; } else if (stream->match(tokens::newline)) { stream->next(); } } - else { - // We should clean up this - delete[] v; - } return false; } bool LineParser::match_process_debug(tokenstream* stream) { @@ -350,10 +343,10 @@ namespace dms { cmd* c = new cmd; c->opcode = codes::DEBG; if (stream->match(tokens::string)) { - c->args.push(buildValue(stream->next().name)); + c->args.push(value(stream->next().name)); } else { - c->args.push(buildVariable(stream->next().name)); + c->args.push(value(stream->next().name,datatypes::variable)); } current_chunk->addCmd(c); return true; @@ -379,8 +372,8 @@ namespace dms { std::string choi_str = concat("CHOI_", fn); std::string choicelabel = concat("$CHOI_END_", choi_str,"_", stream->peek().line_num); c->opcode = codes::CHOI; - c->args.push(buildValue(prompt)); - c->args.push(buildValue(fn)); + c->args.push(prompt); + c->args.push(fn); current_chunk->addCmd(c); // We will keep a reference to this and add to it as we go through the list bool start = false; bool hasfunc = false; @@ -416,10 +409,10 @@ namespace dms { } else if (stream->match(tokens::string)) { std::string name = stream->next().name; - c->args.push(buildValue(name)); // We append the choice to the first part of the CHOI cmd + c->args.push(value(name)); // We append the choice to the first part of the CHOI cmd - // We consumed the option now lets do some matching, note that all of these are one liners in the bytecode! - if (match_process_function(stream,nullptr,false)) { // No returns and also no nesting of functions! + value val = value(); + if (match_process_function(stream,val,false)) { // No returns and also no nesting of functions! // We cannot have a nested function here, but if we dont have that then we add our goto hasfunc = true; buildGoto(choicelabel); @@ -436,6 +429,7 @@ namespace dms { badSymbol(stream); } } + buildGoto(choicelabel); cmd* cc = current_chunk->cmds.back(); // Delete last element current_chunk->cmds.pop_back(); delete cc; @@ -448,9 +442,9 @@ namespace dms { void cleanup(value* v) { v->nuke(); // Make sure we clean up the data - delete[] v; // We didn't need it, lets clean it up! + delete v; // We didn't need it, lets clean it up! } - bool LineParser::match_process_function(tokenstream* stream, value* v, bool nested) { + bool LineParser::match_process_function(tokenstream* stream, value& v, bool nested) { /* Functions should be able to handle function calls as arguments, HOWEVER functions cannot be passed as values since they aren't values like they are in other languages! @@ -496,13 +490,13 @@ namespace dms { cmd* c = new cmd; c->opcode = codes::FUNC; std::string n = stream->next().name; - c->args.push(buildVariable(n)); // Set the func identifier as the first variable + c->args.push(value(n,datatypes::variable)); // Set the func identifier as the first variable // Let's set the target - if (v != nullptr) { + if (!v.isNil()) { c->args.push(v); // Push the supplied variable } else { - c->args.push(buildValue()); // Creates a nil value + c->args.push(value()); // Creates a nil value } // Already we have built: FUNC name val // Next we add arguments this is where things get interesting @@ -519,18 +513,17 @@ namespace dms { 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; + value tempval; token tok; - value* ref = buildVariable(); + value ref = value(datatypes::variable); // 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(); + tempval = value(datatypes::variable); 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); @@ -539,14 +532,11 @@ namespace dms { 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); } } @@ -555,15 +545,15 @@ namespace dms { cmd* c = new cmd; c->opcode = codes::OFUN; // OFUN obj fname target args - c->args.push(buildVariable(stream->next().name)); // push the obj + c->args.push(value(stream->next().name,datatypes::variable)); // push the obj stream->next(); // consume the dot - c->args.push(buildVariable(stream->next().name)); // push the fname + c->args.push(value(stream->next().name,datatypes::variable)); // push the fname // Let's set the target - if (v != nullptr) { + if (!v.isNil()) { c->args.push(v); // Push the supplied variable } else { - c->args.push(buildValue()); // Creates a nil value + c->args.push(value()); // Creates a nil value } // Already we have built: FUNC name val // Next we add arguments this is where things get interesting @@ -580,18 +570,17 @@ namespace dms { 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; + value tempval; token tok; - value* ref = buildVariable(); + value ref = value(datatypes::variable); // 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(); + tempval = value(datatypes::variable); 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); @@ -600,14 +589,12 @@ namespace dms { 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); } } @@ -627,7 +614,7 @@ namespace dms { } return false; } - bool LineParser::match_process_index(tokenstream* stream, value* v, bool leftside) { + bool LineParser::match_process_index(tokenstream* stream, value& v, bool leftside) { if (stream->match(tokens::name,tokens::bracketo)) { std::string name = stream->next().name; std::vector tok = stream->next(tokens::bracketo, tokens::bracketc); @@ -635,7 +622,7 @@ namespace dms { tok.push_back(token{ tokens::newline,codes::NOOP,"",tok[0].line_num }); tokenstream tempstream; // As usual the tokens are balanced match to [...] where the contents of tok = ... tempstream.init(&tok); - value* tempval = buildVariable(); + value tempval = value(datatypes::variable); cmd* c = new cmd; if (leftside) { c->opcode = codes::ASID; @@ -647,7 +634,7 @@ namespace dms { while (tempstream.peek().type != tokens::none) { // Keep going until we hit the end if (match_process_standard(&tempstream, tempval)) { c->args.push(v); - c->args.push(buildBlock(name)); + c->args.push(value(name,datatypes::block)); c->args.push(tempval); } else if (nlcount) { @@ -677,10 +664,10 @@ namespace dms { c->opcode = codes::JUMP; stream->next(); // consume jump if (stream->match(tokens::name)) { - c->args.push(buildVariable(stream->next().name)); + c->args.push(value(stream->next().name,datatypes::variable)); } else { - c->args.push(buildValue(stream->next().name)); + c->args.push(value(stream->next().name)); } current_chunk->addCmd(c); return true; @@ -694,10 +681,10 @@ namespace dms { c->opcode = codes::EXIT; if (stream->match(tokens::number) || stream->match(tokens::name)) { if(stream->match(tokens::number)){ - c->args.push(buildValue(std::stod(stream->next().name))); + c->args.push(value(std::stod(stream->next().name))); } else { - c->args.push(buildVariable(stream->next().name)); + c->args.push(value(stream->next().name,datatypes::variable)); } } current_chunk->addCmd(c); @@ -722,13 +709,13 @@ namespace dms { return false; } - void reset(value*& l, codes::op& op, value*& r) { - l = nullptr; + void reset(value& l, codes::op& op, value& r) { + l = value(); op = codes::NOOP; - r = nullptr; + r = value(); } - bool LineParser::match_process_expression(tokenstream* stream, value* v) { + bool LineParser::match_process_expression(tokenstream* stream, value& v) { // I will have to consume for this to work so we need to keep track of what was incase we return false! stream->store(current_chunk); cmd* lastcmd = nullptr; @@ -736,10 +723,10 @@ namespace dms { if ((stream->match(tokens::number) || stream->match(tokens::name) || stream->match(tokens::parao)) && stream->tokens.size()>=3) { // What do we know, math expressions can only be on a single line. We know where to stop looking if we have to cmd* c = new cmd; - value* wv = nullptr; - value* left; // lefthand + value wv; + value left; // lefthand codes::op op; // opperator - value* right; // righthand + value right; // righthand reset(left, op, right); size_t loops = 0; bool hasOP = false; @@ -748,11 +735,11 @@ namespace dms { if (stream->match(tokens::parao)) { tokenstream temp; temp.init(&(stream->next(tokens::parao, tokens::parac))); // Balanced match! - value* tmpvalue = buildVariable(); + value tmpvalue = value(datatypes::variable); if (match_process_expression(&temp, tmpvalue)) { - if (left == nullptr) + if (left.isNil()) left = tmpvalue; - else if (right == nullptr) + else if (right.isNil()) right = tmpvalue; else badSymbol(stream); @@ -772,8 +759,8 @@ namespace dms { } else if (stream->match(tokens::minus)) { hasOP = true; - if (left == nullptr) { - left = buildValue(0); // -5 is the same as 0-5 right? Also -(5+5) is the same as 0-(5+5) So we good + if (left.isNil()) { + left = value(0); // -5 is the same as 0-5 right? Also -(5+5) is the same as 0-(5+5) So we good } if (op == codes::NOOP) op = codes::SUB; @@ -815,11 +802,11 @@ namespace dms { } else if (stream->match(tokens::name,tokens::parao)) { //Function template ^^^ If we encounter an issue the method should push an error, incase it misses something we will! - value* tmpvalue = buildVariable(); + value tmpvalue = value(datatypes::variable); if (match_process_function(stream,tmpvalue)) { - if (left == nullptr) + if (left.isNil()) left = tmpvalue; - else if (right == nullptr) + else if (right.isNil()) right = tmpvalue; else badSymbol(stream); @@ -830,24 +817,24 @@ namespace dms { } else if (stream->match(tokens::number)) { double num = std::stod(stream->next().name); - if (left == nullptr) - left = buildValue(num); - else if (right == nullptr) - right = buildValue(num); + if (left.isNil()) + left = value(num); + else if (right.isNil()) + right = value(num); else badSymbol(stream); } else if (stream->match(tokens::name)) { // We tested functions already! So if that fails and we have a name then... we have a variable lets handle this! - if (left == nullptr) - left = buildVariable(stream->next().name); - else if (right == nullptr) - right = buildVariable(stream->next().name); + if (left.isNil()) + left = value(stream->next().name,datatypes::variable); + else if (right.isNil()) + right = value(stream->next().name,datatypes::variable); else badSymbol(stream); } else if (stream->match(tokens::newline) || stream->match(tokens::parac) || stream->match(tokens::seperator)) { - if (wv == nullptr) + if (wv.isNil()) return stream->restore(lastcmd, current_chunk); // Always return false and restores the position in stream! cmd* cc = new cmd; cc->opcode = codes::ASGN; @@ -866,16 +853,16 @@ namespace dms { else { return stream->restore(lastcmd, current_chunk); } - if (left != nullptr && right != nullptr && op != codes::NOOP) { + if (!left.isNil() && !right.isNil() && op != codes::NOOP) { cmd* c = new cmd; c->opcode = op; - if (wv == nullptr) { - value* temp = buildVariable(); + if (wv.isNil()) { + value temp = value(datatypes::variable); c->args.push(temp); wv = temp; } else { - wv = buildVariable(); + wv = value(datatypes::variable); c->args.push(wv); } c->args.push(left); diff --git a/DMS/LineParserParse.cpp b/DMS/LineParserParse.cpp index 1c64eac..61dffec 100644 --- a/DMS/LineParserParse.cpp +++ b/DMS/LineParserParse.cpp @@ -353,11 +353,13 @@ namespace dms { if (state->isEnabled("debugging")) { cmd* c = new cmd; c->opcode = codes::FILE; - c->args.push(buildValue(fn)); + c->args.push(value(fn)); current_chunk->addCmd(c); } while (stream->peek().type != tokens::eof) { debugInvoker(stream); + //utils::print(current); + //utils::print("[flags]"); if (current.type == tokens::flag) { temp = stream->next(tokens::newline); stream->prev(); // Unconsume the newline piece @@ -370,14 +372,14 @@ namespace dms { tolower(temp[0].name); state->enable(temp[0].name); flagcmd->opcode = code; - flagcmd->args.push(buildValue(temp[0].name)); + flagcmd->args.push(value(temp[0].name)); current_chunk->addCmd(flagcmd); flagcmd = new cmd; } else if (code == codes::ENTR && tok == tokens::name) { state->entry = temp[0].name; flagcmd->opcode = code; - flagcmd->args.push(buildValue(temp[0].name)); + flagcmd->args.push(value(temp[0].name)); current_chunk->addCmd(flagcmd); flagcmd = new cmd; } @@ -385,14 +387,14 @@ namespace dms { tolower(temp[0].name); state->disable(temp[0].name); flagcmd->opcode = code; - flagcmd->args.push(buildValue(temp[0].name)); + flagcmd->args.push(value(temp[0].name)); current_chunk->addCmd(flagcmd); flagcmd = new cmd; } else if (code == codes::VERN && tok == tokens::number) { state->version = std::stod(temp[0].name); flagcmd->opcode = code; - flagcmd->args.push(buildValue(std::stod(temp[0].name))); + flagcmd->args.push(value(std::stod(temp[0].name))); current_chunk->addCmd(flagcmd); flagcmd = new cmd; } @@ -456,9 +458,9 @@ namespace dms { for (size_t i = 0; i < tokens.size() - 1; i++) {//The lase symbol is parac since that was the consume condition if (tokens[i].type == tokens::name) { // We got a name which is refering to a variable so lets build one - value* v = new value{}; - v->type = datatypes::variable; // Special type, it writes data to the string portion, but is interperted as a lookup - v->s = buildString(tokens[i].name); + value v; + v.type = datatypes::variable; // Special type, it writes data to the string portion, but is interperted as a lookup + v.s = buildString(tokens[i].name); args.push(v); } else if (tokens[i].type == tokens::seperator) { @@ -490,19 +492,29 @@ namespace dms { } } // Let's handle function stuff! + //utils::print("[return]"); match_process_return(stream); + //utils::print("[disp]"); match_process_disp(stream); // Match and process dialogue + //utils::print("[label]"); if (stream->match(tokens::newline,tokens::label)) { // Match and process labels stream->next(); buildLabel(stream->next().name); } - match_process_function(stream); // Naked Function + //utils::print("[func]"); + value nil; + match_process_function(stream, nil); // Naked Function + //utils::print("[assn]"); match_process_assignment(stream); + //utils::print("[debug]"); match_process_debug(stream); + //utils::print("[goto]"); match_process_goto(stream); - + //utils::print("[exit]"); match_process_exit(stream); + //utils::print("[wait]"); match_process_wait(stream); + //utils::print("[jump]"); match_process_jump(stream); current = stream->next(); } diff --git a/DMS/LineParserUtils.cpp b/DMS/LineParserUtils.cpp index e2c8a5f..ba81b43 100644 --- a/DMS/LineParserUtils.cpp +++ b/DMS/LineParserUtils.cpp @@ -203,29 +203,17 @@ namespace dms { void LineParser::badSymbol() { state->push_error(errors::error{ errors::unknown,concat("Unexpected symbol '",_stream->peek().toString(),"'"),true,_stream->next().line_num,current_chunk }); } - void LineParser::buildSpeed(double s) { - cmd* c = new cmd; - c->opcode = codes::DSPD; - c->args.push(buildValue(s)); - current_chunk->addCmd(c); - } - void LineParser::buildWait(double w) { - cmd* c = new cmd; - c->opcode = codes::WAIT; - c->args.push(buildValue(w)); - current_chunk->addCmd(c); - } void LineParser::debugInvoker(tokenstream* stream) { if (state->isEnabled("debugging") && stream->peek().type != tokens::newline) { // A very nasty if statement, I won't hide it, this could be made much more readable // This checks if the last cmd is a LINE cmd and if its the same line number as the current one we simply skip it - if (current_chunk->cmds.size() >= 2 && current_chunk->cmds[current_chunk->cmds.size() - 1]!=nullptr && current_chunk->cmds[current_chunk->cmds.size() - 1]->opcode==codes::LINE && (size_t)current_chunk->cmds[current_chunk->cmds.size()-1]->args.args[0]->n->getValue()== (size_t)stream->peek().line_num) { + if (current_chunk->cmds.size() >= 2 && current_chunk->cmds[current_chunk->cmds.size() - 1]!=nullptr && current_chunk->cmds[current_chunk->cmds.size() - 1]->opcode==codes::LINE && (size_t)current_chunk->cmds[current_chunk->cmds.size()-1]->args.args[0].n== (size_t)stream->peek().line_num) { return; } int current_line = stream->peek().line_num; cmd* ln = new cmd; ln->opcode = codes::LINE; - ln->args.push(buildValue(current_line)); + ln->args.push(value(current_line)); current_chunk->addCmd(ln); } } @@ -259,16 +247,16 @@ namespace dms { if (state->isEnabled("leaking") && (current_chunk != nullptr && current_chunk->name != "$INIT")) { cmd* c = new cmd; c->opcode = codes::JUMP; - c->args.push(buildValue(bk_name)); + c->args.push(value(bk_name)); current_chunk->addCmd(c); } if (current_chunk != nullptr && current_chunk->name == "$END") { cmd* c = new cmd; c->opcode = codes::EXIT; if (state->entry != "$undefined") - c->args.push(buildValue(0)); + c->args.push(value(0)); else - c->args.push(buildValue(bk_name)); + c->args.push(value(bk_name)); current_chunk->addCmd(c); } current_chunk = new chunk; diff --git a/DMS/character.cpp b/DMS/character.cpp index a0d1924..215f2ed 100644 --- a/DMS/character.cpp +++ b/DMS/character.cpp @@ -1,12 +1,12 @@ #include "character.h" #include "utils.h" namespace dms { - value* character_setName(void* self, dms_state* state, dms_args* args) { + 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())); + me->set("fname", args->args[0]); } - return buildNil(); + return value(); } character::character() { // Set the self so the registered function can access themselves @@ -16,16 +16,16 @@ namespace dms { } std::string character::getName() { if (has("nickname")) { - return values["nickname"]->getPrintable(); + return values["nickname"].getPrintable(); } if (seen && has("fname") && has("lname")) { - return utils::concat(values["fname"]->getPrintable()," ", values["lname"]->getPrintable()); + return utils::concat(values["fname"].getPrintable()," ", values["lname"].getPrintable()); } else if (seen && has("fname")) { - return utils::concat(values["fname"]->getPrintable()); + return utils::concat(values["fname"].getPrintable()); } else if (!seen && has("unknown")) { - return values["unknown"]->getPrintable(); + return values["unknown"].getPrintable(); } else { return "unknown"; diff --git a/DMS/cmd.h b/DMS/cmd.h index fe3a3b0..f405fe3 100644 --- a/DMS/cmd.h +++ b/DMS/cmd.h @@ -11,7 +11,7 @@ namespace dms { friend std::ostream& operator << (std::ostream& out, const cmd& c) { out << codes::list[c.opcode] << " "; for (size_t i = 0; i < c.args.args.size(); i++) { - out << *c.args.args[i] << " "; + out << c.args.args[i] << " "; } return out; } diff --git a/DMS/dms.h b/DMS/dms.h index 14c889b..26276ca 100644 --- a/DMS/dms.h +++ b/DMS/dms.h @@ -14,4 +14,6 @@ #include "utils.h" #include "value.h" #include "Invoker.h" +#include "memory.h" +#include "dms_list.h" diff --git a/DMS/dms_custom.cpp b/DMS/dms_custom.cpp index 36664f9..1c4cbcd 100644 --- a/DMS/dms_custom.cpp +++ b/DMS/dms_custom.cpp @@ -14,48 +14,48 @@ namespace dms { void dms_custom::Init(dms_state* state) { this->state = state; } - value* dms_custom::Index(value* data) { + value dms_custom::Index(value data) { state->push_error(errors::error{ errors::unknown,"Attempting to index a non enviroment!" }); return nullptr; } - bool dms_custom::NewIndex(value* var, value* val) { + bool dms_custom::NewIndex(value var, value val) { state->push_error(errors::error{ errors::unknown,"Attempting to create a new index on a non enviroment!" }); return false; } - value* dms_custom::Call(dms_args* args) { + value dms_custom::Call(dms_args* args) { state->push_error(errors::error{errors::unknown,"Attempting to call a non function value!"}); return nullptr; } - value* dms_custom::ToString() { - return buildValue(utils::concat("Custom: ",this)); + value dms_custom::ToString() { + return value(utils::concat("Custom: ",this)); } - value* dms_custom::ADD(value* left, value* right) { + value dms_custom::ADD(value left, value right) { state->push_error(errors::error{ errors::unknown,"Attempting to add a non number value!" }); return nullptr; } - value* dms_custom::SUB(value* left, value* right) { + value dms_custom::SUB(value left, value right) { state->push_error(errors::error{ errors::unknown,"Attempting to subtract a non number value!" }); return nullptr; } - value* dms_custom::MUL(value* left, value* right) { + value dms_custom::MUL(value left, value right) { state->push_error(errors::error{ errors::unknown,"Attempting to multiply a non number value!" }); return nullptr; } - value* dms_custom::DIV(value* left, value* right) { + value dms_custom::DIV(value left, value right) { state->push_error(errors::error{ errors::unknown,"Attempting to divide a non number value!" }); return nullptr; } - value* dms_custom::POW(value* left, value* right) { + value dms_custom::POW(value left, value right) { state->push_error(errors::error{ errors::unknown,"Attempting to raise a non number value!" }); return nullptr; } - value* dms_custom::EQUAL(value* left, value* right) { - return buildValue(left->getPrintable() == right->getPrintable()); + value dms_custom::EQUAL(value left, value right) { + return value(left.getPrintable() == right.getPrintable()); } - value* dms_custom::LESS_THAN(value* left, value* right) { - return buildValue(left->getPrintable() < right->getPrintable()); + value dms_custom::LESS_THAN(value left, value right) { + return value(left.getPrintable() < right.getPrintable()); } - value* dms_custom::LESS_THAN_EQUAL(value* left, value* right) { - return buildValue(left->getPrintable() <= right->getPrintable()); + value dms_custom::LESS_THAN_EQUAL(value left, value right) { + return value(left.getPrintable() <= right.getPrintable()); } } \ No newline at end of file diff --git a/DMS/dms_list.h b/DMS/dms_list.h new file mode 100644 index 0000000..32ec3a6 --- /dev/null +++ b/DMS/dms_list.h @@ -0,0 +1,11 @@ +#pragma once +#include "memory.h" +namespace dms { + struct dms_list + { + memory hpart; + std::vector ipart; + void pushValue(value val); + value getValue(value val); + }; +} \ No newline at end of file diff --git a/DMS/dms_state.cpp b/DMS/dms_state.cpp index 82be103..fe54c0e 100644 --- a/DMS/dms_state.cpp +++ b/DMS/dms_state.cpp @@ -8,18 +8,15 @@ namespace dms { cmd* c = new cmd; for (const auto& [key, val] : chunks) { if (val->type == blocktype::bt_character || val->type == blocktype::bt_env) { - value* v = buildVariable(); - v->set(buildString(key)); - v->type = datatypes::block; c->opcode = codes::ASGN; - c->args.push(buildVariable(key)); - c->args.push(v); + c->args.push(value(key, datatypes::variable)); + c->args.push(value(key, datatypes::block)); chunks["$INIT"]->addCmd(c); c = new cmd; } else if (val->type == blocktype::bt_method) { c->opcode = codes::RETN; - c->args.push(buildNil()); + c->args.push(value()); val->addCmd(c); c = new cmd; } @@ -27,31 +24,31 @@ namespace dms { c->opcode = codes::JUMP; if (entry != "$undefined") - c->args.push(buildValue(entry)); + c->args.push(value(entry)); else - c->args.push(buildValue(chunks.begin()->first)); + c->args.push(value(chunks.begin()->first)); chunks["$INIT"]->addCmd(c); if (!handler->OnStateInit(this)) stop = true; } - std::unordered_map* dms_state::getMem() { - return mem_stack.top(); + memory* dms_state::getMem() { + return &mem_stack.top(); } void dms_state::pushMem() { - mem_stack.push(new std::unordered_map); + mem_stack.push(memory()); } void dms_state::popMem() { mem_stack.pop(); } - value* dms::blockInvoke(void* self, dms_state* state, dms_args* args) { + 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; + value ret; state->pushMem(); - std::unordered_map* Fmem = state->getMem(); + memory* 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()); + (*Fmem)[state->chunks[func]->params.args[i].getPrintable()] = args->args[i].resolve(state); } state->run(func, Fmem); ret = state->return_stack.top(); @@ -59,14 +56,11 @@ namespace dms { state->popMem(); return ret; } - return buildNil(); - } - void dms_state::pushMem(std::unordered_map* m) { - mem_stack.push(m); + return value(); } dms_state::dms_state() { // We should define the defaults for the enables - pushMem(&memory); + pushMem(); // Main memory enables.insert_or_assign("leaking", false); enables.insert_or_assign("debugging", false); enables.insert_or_assign("warnings", false); // @@ -78,15 +72,15 @@ namespace dms { c->type = blocktype::bt_block; cmd* cc = new cmd; cc->opcode = codes::EXIT; - cc->args.push(buildValue(0)); + cc->args.push(value(0)); 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) { - push_error(errors::error{ errors::invalid_type ,utils::concat("Expected a ",datatype[type]," got a ",datatype[val->type],"!") }); + bool dms_state::typeAssert(value val, datatypes type) { + if (val.type != type) { + push_error(errors::error{ errors::invalid_type ,utils::concat("Expected a ",datatype[type]," got a ",datatype[val.type],"!") }); return false; } return true; @@ -136,22 +130,9 @@ namespace dms { return false; } - bool dms_state::assign(std::unordered_map* mem, value* var, value* val) { - if (mem->count(var->s->getValue()) == 0) { - mem->insert_or_assign(var->s->getValue(), val); - return true; - } - else { - value* temp = (*mem)[var->s->getValue()]; - if (temp->type != datatypes::variable) { - temp->set(); // Set the removed value to nil - garbage.push_back((*mem)[var->s->getValue()]); - } - else - utils::print("> so we have a variable"); // This print should be a reminder for me to do something about this. - (*mem)[var->s->getValue()] = val; - return true; - } + bool dms_state::assign(value var, value val) { + (*getMem())[var.getPrintable()] = val; + return true; } void dms_state::dump(bool print) { if (print) diff --git a/DMS/dms_state.h b/DMS/dms_state.h index 62efee5..3be610a 100644 --- a/DMS/dms_state.h +++ b/DMS/dms_state.h @@ -9,18 +9,20 @@ #include "dms_exceptions.h" #include "Character.h" #include "enviroment.h" +#include "memory.h" #include +#include "dms_list.h" namespace dms { struct Handler; - value* blockInvoke(void*, dms_state*, dms_args*); + value blockInvoke(void*, dms_state*, dms_args*); struct dms_state { Handler* handler = nullptr; bool hasFirst = false; Invoker invoker; std::stack call_stack; - std::stack return_stack; - std::stack*> mem_stack; + std::stack return_stack; + std::stack mem_stack; std::vector garbage; std::unordered_map chunks; std::unordered_map characters; @@ -53,19 +55,18 @@ namespace dms { character* getCharacter(std::string c); enviroment* getEnvironment(std::string c); - bool assign(std::unordered_map* mem,value* var, value* val); + bool assign(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 functionExists(std::string bk_name); bool blockExists(std::string bk_name); - bool typeAssert(value* val, datatypes type); - std::unordered_map* getMem(); + bool typeAssert(value val, datatypes type); + memory* getMem(); void pushMem(); void popMem(); - value* func(); bool run(); - bool run(std::string ent,std::unordered_map* mem); + bool run(std::string ent,memory* mem); bool run(std::string instance); // This is called once and once only. Dynamically loading code is not a thing! void init(); @@ -73,8 +74,6 @@ namespace dms { 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 4e4ed39..d5be57d 100644 --- a/DMS/dms_state_interpret.cpp +++ b/DMS/dms_state_interpret.cpp @@ -12,17 +12,16 @@ namespace dms { this->handler = hand; } void checkCharacter(character* cc,std::string index, datatypes type) { - value* val = cc->get(index); - if (val==nullptr) { + value val = cc->get(index); + // If a type mismatch is present, overwrite them with the defaults + if (val.type!=type) { if (type == datatypes::string) - cc->values[index] = buildValue(""); + cc->values[index] = value(""); else if (type == datatypes::boolean) { - cc->values[index] = buildValue(false); + cc->values[index] = value(false); } - } - else if (val != nullptr) { - if (val->type != type) { - cc->values.erase(index); + else if (type == datatypes::number) { + cc->values[index] = value(0); } } } @@ -56,10 +55,10 @@ namespace dms { if (blockExists(cha)) { character* cc = new character; cc->fullname = isEnabled("fullname"); - cc->set("fname", buildValue(cha)); - cc->set("lname", buildValue("")); - cc->set("unknown", buildValue("Unknown")); - cc->set("known", buildValue(false)); + cc->set("fname", cha); + cc->set("lname", ""); + cc->set("unknown", "Unknown"); + cc->set("known", false); if (isEnabled("omniscient")) { cc->seen = true; } @@ -71,7 +70,7 @@ namespace dms { checkCharacter(cc, "lname", datatypes::string); checkCharacter(cc, "unknown", datatypes::string); checkCharacter(cc, "known", datatypes::boolean); - if (cc->get("known")->b->getValue() == true) { + if (cc->get("known").b == true) { cc->seen = true; } } @@ -92,7 +91,7 @@ namespace dms { } size_t dms_state::seek(std::string label, std::vector cmds, codes::op code, size_t pos) { for (size_t i = pos; i < cmds.size(); i++) { - if (cmds[i]->opcode == code && cmds[i]->args.args[0]->s->getValue() == label) + if (cmds[i]->opcode == code && cmds[i]->args.args[0].getPrintable() == label) return i; } return 0; @@ -113,9 +112,9 @@ namespace dms { push_error(errors::error{ errors::non_existing_block ,utils::concat("Attempted to Jump to a non existing block [",entry,"]") }); return false; } - return run("$INIT",&memory); + return run("$INIT",getMem()); } - bool dms_state::run(std::string ent, std::unordered_map* mem) { + bool dms_state::run(std::string ent, memory* mem) { if (stop) { exitcode = 1; return false; @@ -143,19 +142,19 @@ namespace dms { // Handle flags here case ENTR: // When reading code from a file the flags are compiled and we need to load them - entry = c->args.args[0]->s->getValue(); + entry = c->args.args[0].getPrintable(); break; case ENAB: - enable(c->args.args[0]->s->getValue()); + enable(c->args.args[0].getPrintable()); break; case DISA: - disable(c->args.args[0]->s->getValue()); + disable(c->args.args[0].getPrintable()); break; case LOAD: // Nothing needs to be done here break; case VERN: - Sversion = c->args.args[0]->n->getValue(); + Sversion = c->args.args[0].n; // Version X.xx // X: Will not guarantee compatibality. Code breaking changes should be expected especially on lower versions // xx: Will not break compatibality. They may add features as it goes up the ranks, but those changes do not break older code. If they do they will increase the X part and not the xx part @@ -173,13 +172,26 @@ namespace dms { // Flags handled case EXIT: if (c->args.args.size()) { - exitcode = c->args.args[0]->n->getValue(); + exitcode = c->args.args[0].n; } return true; break; + case GOTO: + { + value labl = c->args.args[0]; + size_t nnpos = seek(labl.getPrintable(),cmds, LABL, 0); + if (!nnpos) { + push_error(errors::error{ errors::choice_unknown ,utils::concat("Unknown choice!") }); + return false; + } + else { + pos = nnpos; + } + } + break; case RETN: { - value* ret = c->args.args[0]->resolve(this)->copy(); + value ret = c->args.args[0].resolve(this); //c->args.args[0]->nuke(); // Lets clean this up return_stack.push(ret); return true; // We did it, let's return this @@ -187,35 +199,32 @@ namespace dms { 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]; + 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; + value ret; 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); + if (assn.type != datatypes::nil) { + assign(assn, ret); } } break; case FUNC: { - std::string funcname = c->args.args[0]->getPrintable(); - value* assn = c->args.args[1]; + std::string funcname = c->args.args[0].getPrintable(); + value assn = c->args.args[1]; dms_args args; - value* ret = nullptr; + value ret; for (int i = 2; i < c->args.args.size(); i++) { args.push(c->args.args[i]); } @@ -225,126 +234,124 @@ namespace dms { ret = invoker.Invoke("$BlockInvoke$", this, &args); } else { - value* ret = invoker.Invoke(funcname, this, &args); + ret = invoker.Invoke(funcname, this, &args); } - if (ret == nullptr) - return false; - if (assn->type != datatypes::nil) { - assign(getMem(), assn, ret); + if (assn.type != datatypes::nil) { + assign(assn, ret); } } break; case ASID: { - value* env = c->args.args[1]; - 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 + value env = c->args.args[1]; + 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())) { - e = environments[env->getPrintable()]; + if (environments.count(env.getPrintable())) { + e = environments[env.getPrintable()]; } - else if (characters.count(env->getPrintable())) { - e = characters[env->getPrintable()]; + else if (characters.count(env.getPrintable())) { + e = characters[env.getPrintable()]; } - e->values[indx->getPrintable()] = assn; + e->values[indx.getPrintable()] = assn; } - else if (env->type == datatypes::env) { - if (indx->type == datatypes::number) { - env->e->pushValue(assn); + else if (env.type == datatypes::env) { + if (indx.type == datatypes::number) { + env.e->pushValue(assn); } else { - push_error(errors::error{ errors::invalid_type ,concat("Expected a number value got ",datatype[indx->type]) }); + push_error(errors::error{ errors::invalid_type ,concat("Expected a number value got ",datatype[indx.type]) }); return false; } } - else if (env->type == datatypes::custom) { - env->c->NewIndex(indx, assn); - //assign(mem, assn, env->c->Index(indx)); + else if (env.type == datatypes::custom) { + env.c->NewIndex(indx, assn); + //assign( assn, env->c->Index(indx)); // Call the method within the custom data } 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); + value assn = c->args.args[0]; + value o1 = c->args.args[1]; + value o2 = c->args.args[2]; + value ret = value(o1.resolve(this).n+o2.resolve(this).n); + assign(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); + value assn = c->args.args[0]; + value o1 = c->args.args[1]; + value o2 = c->args.args[2]; + value ret = value(o1.resolve(this).n - o2.resolve(this).n); + assign(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); + value assn = c->args.args[0]; + value o1 = c->args.args[1]; + value o2 = c->args.args[2]; + value ret = value(o1.resolve(this).n * o2.resolve(this).n); + assign(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); + value assn = c->args.args[0]; + value o1 = c->args.args[1]; + value o2 = c->args.args[2]; + value ret = value(o1.resolve(this).n / o2.resolve(this).n); + assign(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); + value assn = c->args.args[0]; + value o1 = c->args.args[1]; + value o2 = c->args.args[2]; + value ret = value(pow(o1.resolve(this).n, o2.resolve(this).n)); + assign(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); + value assn = c->args.args[0]; + value o1 = c->args.args[1]; + value o2 = c->args.args[2]; + value ret = value(std::fmod(o1.resolve(this).n,o2.resolve(this).n)); + assign(assn, ret); } break; case INDX: { - value* assn = c->args.args[0]; - value* env = c->args.args[1]; - 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 + value assn = c->args.args[0]; + value env = c->args.args[1]; + 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())) { - e = environments[env->getPrintable()]; + if (environments.count(env.getPrintable())) { + e = environments[env.getPrintable()]; } - else if (characters.count(env->getPrintable())) { - e = characters[env->getPrintable()]; + else if (characters.count(env.getPrintable())) { + e = characters[env.getPrintable()]; } - assign(mem, assn, e->values[indx->getPrintable()]); + assign( assn, e->values[indx.getPrintable()]); } - else if (env->type == datatypes::env) { - if (indx->type == datatypes::number) { - assign(mem, assn, env->e->getValue(indx)); + else if (env.type == datatypes::env) { + if (indx.type == datatypes::number) { + assign( assn, env.e->getValue(indx)); } else { - push_error(errors::error{ errors::invalid_type ,concat("Expected a number value got ",datatype[indx->type]) }); + push_error(errors::error{ errors::invalid_type ,concat("Expected a number value got ",datatype[indx.type]) }); return false; } } - else if (env->type == datatypes::custom) { - assign(mem, assn, env->c->Index(indx)); + else if (env.type == datatypes::custom) { + assign( assn, env.c->Index(indx)); // Call the method within the custom data } } @@ -352,17 +359,18 @@ namespace dms { case LIST: //We need to create an enviroment value then set that { - dms_env* env = new dms_env; - env->hpart.insert_or_assign("$size", c->args.args[1]); - value* val = new value; - val->set(env); - assign(mem,c->args.args[0], val); + dms_list* env = new dms_list; + // Inject the size of the list + env->hpart["$size"] = c->args.args[1]; + value val = new value; + val.set(env); + assign(c->args.args[0], val); } break; case INST: { - value* list = (*mem)[c->args.args[0]->s->getValue()]; - list->e->pushValue(c->args.args[1]); + value list = (*mem)[c->args.args[0].getPrintable()]; + list.e->pushValue(c->args.args[1]); } break; case HALT: @@ -371,7 +379,7 @@ namespace dms { std::cout << std::endl; break; case WAIT: - sleep((int)(c->args.args[0]->n->getValue()*1000)); + sleep((int)(c->args.args[0].n*1000)); break; case DSPD: if (speaker == nullptr) { @@ -379,34 +387,34 @@ namespace dms { return false; } else { - speaker->spd = c->args.args[0]->n->getValue(); + speaker->spd = c->args.args[0].n; } break; case SSPK: //Because we are using void* we must cast our pointers - if (characterExists(c->args.args[0]->s->getValue())){ - speaker = getCharacter(c->args.args[0]->s->getValue()); + if (characterExists(c->args.args[0].s->getValue())){ + speaker = getCharacter(c->args.args[0].s->getValue()); if (!handler->handleSpeaker(this, speaker)) return false; } else { - push_error(errors::error{ errors::disp_unknown,concat("Unknown character '",c->args.args[0]->s->getValue(),"'!")}); + push_error(errors::error{ errors::disp_unknown,concat("Unknown character '",c->args.args[0].s->getValue(),"'!")}); return false; } break; case APND: - if (!handler->handleMessageAppend(this, c->args.args[0]->s->getValue(this))) + if (!handler->handleMessageAppend(this, c->args.args[0].s->getValue(this))) return false; break; case DISP: - if (!handler->handleMessageDisplay(this, c->args.args[0]->s->getValue(this))) + if (!handler->handleMessageDisplay(this, c->args.args[0].s->getValue(this))) return false; break; case ASGN: - assign(mem,c->args.args[0], c->args.args[1]); + assign(c->args.args[0], c->args.args[1]); break; case LINE: - cur_line = c->args.args[0]->n->getValue(); + cur_line = c->args.args[0].n; break; case NOOP: break; @@ -414,12 +422,12 @@ namespace dms { //Because we are using void* we must cast our pointers { std::vector args; - std::string prompt = c->args.args[0]->s->getValue(); - std::string fn = c->args.args[1]->s->getValue(); + 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(this)->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); + size_t nnpos = seek(concat("CHOI_", fn, "_", npos),cmds,LABL,pos); if (!nnpos) { push_error(errors::error{ errors::choice_unknown ,utils::concat("Unknown choice!") }); return false; @@ -432,7 +440,7 @@ namespace dms { case JUMP: // Value assert resolves the data so a variable must eventually equal a string if (utils::valueassert(c->args, this, datatypes::string)) { - std::string block = c->args.args[0]->resolve(this)->s->getValue(); + 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; @@ -446,7 +454,9 @@ namespace dms { } } else { - datatypes set = c->args.args[0]->resolve(this)->type; + //utils::print(c->args.args[0].type); + datatypes set = c->args.args[0].resolve(this).type; + //utils::print("> ",set); 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 cb4c77283d2649f59c1be5d81286390c57412fdb..eac70633b9c6822e8f8c052f42b5610058927670 100644 GIT binary patch literal 2038 zcma)7+iu!G5KXBpqDc9NX@%66ieM6QsnS+Xp$Sb&B5*HnVPh{~#omqVbyEJmGaj!E zh)R8d-LrG%KI3b-`~ZoF)cHfKgU3(%dy~oCH8jUdpcr18)g=OOBL{!}emVSM9b9f}4<8!mP5m4wmKh``9i$m-`8I zb6d1}9fmC+=t|ATiUoXxsaS1{b!YbXu4zcHC(osN#tC7yS*(o<&ZH=44RsMJ3QC>(B{8C+pBDLZ<|kj<&F8s%akl9{SLrVD0O0H1zA| zkv|59=ART`K0I)AqM|H_q$)aSF!CG8PXq#A=b*g(SI>{#+Fk7Fg0 z0{J-@kI;6zi?19f<`8!2#{!|8i99y2YY+CJ*gw1F7Gg4Om0eyf-+p|@wPf8cBP&&$ z2Mdvk0QW>ysszV-$ys1kG_LKSm~gW*;Vm#WHb#oCI1!TBZ9kP^Y*qtY)5 zc&>3T`koKXK*R|+?Sm&_76(Qj%%ZqR6u-(pL1bjOO`!BKGxF&?k!GPojE%e3$53!H z;({aFfs-w!Sx+Vy1 z)H#DF_u)1=}Vn!IW(U3}$r^QIF6|{FutBvc)yN=35=t>29J;JDHocLPV()M?Nu(rJy38uS9`1<|qq{iU}!>9hQ^@}WhkRCML7e1koI4HhX% z0Z`02SV=6SEQq*NG`IBTU%}cXX~wx=TP`v)o3R55&J;JBcexOf#l?)?8uD$v-$!y! zi*(VcZda?@C0HV1A(>_n#zoxHA*b&Ws{tyDPV$ipk(h`!o$!9S_VBC&T2%%zRYqGt zhaQ!!LcU|UP|&Fc6<8mcgii6SroJXy=+L9r{c-mb4PRBPENU5I7Cf?)1&XI9_mS7N zjpIb}qn1J^XM9;)o6_@TMEd+2;f&+hp5tYq^OZ+6b}PSR4~I1OUnL5C!1~S7uvS3h zxF?ysNH|kz&T;$3pZn0ps~m$hIDcm9@mwY6yGRrgYs&uyk>cT73(DhUia*a{t{#)n zG!4`iZ7~=OD2--|D9*W9;JtUp*cR|0Z7P0w7E^`3JJM?!Y_Ynh*$F+62e?yf(03gT zs)>+ZjbE?_RfL0;B{8O$HmqAzTnFP-o6=c1rhzSg&tujx)15@dh1poj5 diff --git a/DMS/dump.txt b/DMS/dump.txt index 4c66014..6d52b81 100644 --- a/DMS/dump.txt +++ b/DMS/dump.txt @@ -22,9 +22,6 @@ 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 @@ -45,250 +42,336 @@ 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 val -Line <15> equal = -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> parac ) -Line <15> newline -Line <15> newline -Line <16> string val = `val` -Line <16> newline -Line <16> newline -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> newline -Line <20> 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 excited -Line <25> colon : -Line <25> string path/to/file -Line <25> newline -Line <25> newline -Line <26> newline -Line <26> newline -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> 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 <30> eof -Line <1> newline -Line <1> newline -Line <1> flag -Line <1> name tests -Line <1> newline -Line <1> newline -Line <2> flag -Line <2> name hello -Line <2> newline -Line <2> newline -Line <3> bracketo [ -Line <3> name default -Line <3> colon : -Line <3> name char -Line <3> bracketc ] -Line <3> newline -Line <3> newline -Line <4> newline -Line <5> name money -Line <5> equal = -Line <5> number 0 -Line <5> newline -Line <5> newline -Line <6> name test -Line <6> equal = -Line <6> nil nil -Line <6> newline -Line <6> newline -Line <7> newline -Line <7> newline -Line <8> bracketo [ -Line <8> name Ryan -Line <8> colon : -Line <8> name char -Line <8> bracketc ] -Line <8> newline -Line <8> newline -Line <9> name age -Line <9> equal = -Line <9> number 21 -Line <9> newline -Line <9> newline -Line <10> name money -Line <10> equal = -Line <10> number 1000 -Line <10> newline -Line <10> newline -Line <11> name lname -Line <11> equal = -Line <11> string Ward -Line <11> newline -Line <11> newline -Line <12> name known -Line <12> equal = -Line <12> true true -Line <12> newline -Line <12> newline -Line <13> newline -Line <14> name calm +Line <14> name Ryan Line <14> colon : -Line <14> string ./path/to/file +Line <14> string Hello `Bob`, how are you doing? Line <14> newline Line <14> newline -Line <15> name excited +Line <15> name Bob Line <15> colon : -Line <15> string ./path/to/file +Line <15> string Hi `Ryan`, I'm good. Line <15> newline Line <15> newline +Line <16> name a +Line <16> equal = +Line <16> number 1000 Line <16> newline Line <16> newline -Line <17> bracketo [ -Line <17> name step -Line <17> colon : -Line <17> name function +Line <17> name test +Line <17> equal = +Line <17> name invokeTest Line <17> parao ( -Line <17> name a -Line <17> seperator , -Line <17> name b -Line <17> seperator , -Line <17> name c +Line <17> string Running external code! Line <17> parac ) -Line <17> bracketc ] Line <17> newline Line <17> newline -Line <18> string Testing... +Line <17> newline +Line <18> string Loop Test... `test` Line <18> newline -Line <19> name d -Line <19> equal = -Line <19> parao ( -Line <19> number 100 -Line <19> plus + -Line <19> name b -Line <19> parac ) -Line <19> divide / -Line <19> name c +Line <18> newline +Line <19> control +Line <19> string Pick one +Line <19> cbracketo { Line <19> newline Line <19> newline -Line <20> name e -Line <20> equal = -Line <20> string somestring +Line <20> string this +Line <20> gotoo +Line <20> string this Line <20> newline Line <20> newline -Line <21> name e -Line <21> equal = -Line <21> nil nil +Line <21> string test2 +Line <21> name tryme +Line <21> parao ( +Line <21> true true +Line <21> parac ) Line <21> newline Line <21> newline -Line <22> name g -Line <22> equal = -Line <22> false false +Line <22> string that +Line <22> gotoo +Line <22> string that Line <22> newline Line <22> newline -Line <23> ret -Line <23> name d +Line <23> string test +Line <23> name test +Line <23> parao ( +Line <23> number 1 +Line <23> seperator , +Line <23> number 2 +Line <23> seperator , +Line <23> number 3 +Line <23> parac ) Line <23> newline Line <23> newline +Line <24> cbracketc } Line <24> newline Line <24> newline -Line <25> bracketo [ -Line <25> name inv -Line <25> colon : -Line <25> name env -Line <25> bracketc ] +Line <25> label this Line <25> newline Line <25> newline -Line <26> name slot1 -Line <26> equal = -Line <26> string S1 +Line <26> string At "this" Line <26> newline Line <26> newline -Line <27> name slot2 -Line <27> equal = -Line <27> string S2 +Line <27> gotoo +Line <27> string loop Line <27> newline Line <27> newline -Line <28> name slot3 -Line <28> equal = -Line <28> string S3 +Line <28> label that Line <28> newline Line <28> newline -Line <29> name slot4 -Line <29> equal = -Line <29> string S4 +Line <29> string At "that" Line <29> newline Line <29> newline -Line <30> name slot5 -Line <30> equal = -Line <30> string S5 +Line <30> label loop Line <30> newline Line <30> newline -Line <31> name slot6 +Line <31> name a Line <31> equal = -Line <31> string S6 +Line <31> name a +Line <31> plus + +Line <31> number 1 Line <31> newline Line <31> newline -Line <32> name slot7 -Line <32> equal = -Line <32> string S7 +Line <32> string a = `a` Line <32> newline Line <32> newline -Line <33> name slot8 -Line <33> equal = -Line <33> string S8 +Line <33> gotoo +Line <33> string loop Line <33> newline Line <33> newline -Line <33> eof +Line <34> newline +Line <34> newline +Line <35> bracketo [ +Line <35> name Bob +Line <35> colon : +Line <35> name char +Line <35> bracketc ] +Line <35> newline +Line <35> newline +Line <36> newline +Line <37> newline +Line <38> newline +Line <39> name unknown +Line <39> equal = +Line <39> string Some Random Guy +Line <39> newline +Line <39> newline +Line <40> name age +Line <40> equal = +Line <40> number 0.24 +Line <40> newline +Line <40> newline +Line <41> name money +Line <41> equal = +Line <41> number 100 +Line <41> newline +Line <41> newline +Line <42> name excited +Line <42> colon : +Line <42> string path/to/file +Line <42> newline +Line <42> newline +Line <43> newline +Line <43> newline +Line <44> bracketo [ +Line <44> name test1 +Line <44> colon : +Line <44> name function +Line <44> parao ( +Line <44> parac ) +Line <44> bracketc ] +Line <44> newline +Line <44> newline +Line <45> string Inside a function! +Line <45> newline +Line <45> newline +Line <46> newline +Line <47> newline +Line <48> newline +Line <48> newline +Line <49> bracketo [ +Line <49> name newblock +Line <49> colon : +Line <49> name function +Line <49> parao ( +Line <49> name a +Line <49> seperator , +Line <49> name b +Line <49> seperator , +Line <49> name c +Line <49> parac ) +Line <49> bracketc ] +Line <49> newline +Line <49> newline +Line <50> string Func Arguments: a = `a`, b = `b`, c = `c` +Line <50> newline +Line <50> newline +Line <51> string Time to return +Line <51> newline +Line <51> newline +Line <52> ret +Line <52> name a +Line <52> plus + +Line <52> name b +Line <52> plus + +Line <52> name c +Line <52> newline +Line <52> newline +Line <52> eof +Line <1> newline +Line <1> newline +Line <1> bracketo [ +Line <1> name default +Line <1> colon : +Line <1> name char +Line <1> bracketc ] +Line <1> newline +Line <1> newline +Line <2> newline +Line <3> name money +Line <3> equal = +Line <3> number 0 +Line <3> newline +Line <3> newline +Line <4> name test +Line <4> equal = +Line <4> nil nil +Line <4> newline +Line <4> newline +Line <5> newline +Line <5> newline +Line <6> bracketo [ +Line <6> name Ryan +Line <6> colon : +Line <6> name char +Line <6> bracketc ] +Line <6> newline +Line <6> newline +Line <7> name age +Line <7> equal = +Line <7> number 21 +Line <7> newline +Line <7> newline +Line <8> name money +Line <8> equal = +Line <8> number 1000 +Line <8> newline +Line <8> newline +Line <9> name lname +Line <9> equal = +Line <9> string Ward +Line <9> newline +Line <9> newline +Line <10> name known +Line <10> equal = +Line <10> true true +Line <10> newline +Line <10> newline +Line <11> newline +Line <12> name calm +Line <12> colon : +Line <12> string ./path/to/file +Line <12> newline +Line <12> newline +Line <13> name excited +Line <13> colon : +Line <13> string ./path/to/file +Line <13> newline +Line <13> newline +Line <14> newline +Line <14> newline +Line <15> bracketo [ +Line <15> name step +Line <15> colon : +Line <15> name function +Line <15> parao ( +Line <15> name a +Line <15> seperator , +Line <15> name b +Line <15> seperator , +Line <15> name c +Line <15> parac ) +Line <15> bracketc ] +Line <15> newline +Line <15> newline +Line <16> string Testing... +Line <16> newline +Line <17> name d +Line <17> equal = +Line <17> parao ( +Line <17> number 100 +Line <17> plus + +Line <17> name b +Line <17> parac ) +Line <17> divide / +Line <17> name c +Line <17> newline +Line <17> newline +Line <18> name e +Line <18> equal = +Line <18> string somestring +Line <18> newline +Line <18> newline +Line <19> name e +Line <19> equal = +Line <19> nil nil +Line <19> newline +Line <19> newline +Line <20> name g +Line <20> equal = +Line <20> false false +Line <20> newline +Line <20> newline +Line <21> ret +Line <21> name d +Line <21> newline +Line <21> newline +Line <22> newline +Line <22> newline +Line <23> bracketo [ +Line <23> name inv +Line <23> colon : +Line <23> name env +Line <23> bracketc ] +Line <23> newline +Line <23> newline +Line <24> name slot1 +Line <24> equal = +Line <24> string S1 +Line <24> newline +Line <24> newline +Line <25> name slot2 +Line <25> equal = +Line <25> string S2 +Line <25> newline +Line <25> newline +Line <26> name slot3 +Line <26> equal = +Line <26> string S3 +Line <26> newline +Line <26> newline +Line <27> name slot4 +Line <27> equal = +Line <27> string S4 +Line <27> newline +Line <27> newline +Line <28> name slot5 +Line <28> equal = +Line <28> string S5 +Line <28> newline +Line <28> newline +Line <29> name slot6 +Line <29> equal = +Line <29> string S6 +Line <29> newline +Line <29> newline +Line <30> name slot7 +Line <30> equal = +Line <30> string S7 +Line <30> newline +Line <30> newline +Line <31> name slot8 +Line <31> equal = +Line <31> string S8 +Line <31> newline +Line <31> newline +Line <31> eof diff --git a/DMS/enviroment.cpp b/DMS/enviroment.cpp index b2b03b0..72ae945 100644 --- a/DMS/enviroment.cpp +++ b/DMS/enviroment.cpp @@ -3,10 +3,10 @@ namespace dms { bool enviroment::has(std::string index) { return values.count(index); } - void enviroment::set(std::string index, value* val) { - values.insert_or_assign(index,val); + void enviroment::set(std::string index, value val) { + values[index] = val; } - value* enviroment::get(std::string index) { + value enviroment::get(std::string index) { return values[index]; } } \ No newline at end of file diff --git a/DMS/enviroment.h b/DMS/enviroment.h index 1ca61b3..325460a 100644 --- a/DMS/enviroment.h +++ b/DMS/enviroment.h @@ -2,6 +2,7 @@ #include #include #include "value.h" +#include "memory.h" #include "Invoker.h" namespace dms { enum class env_type { @@ -11,10 +12,10 @@ namespace dms { }; struct enviroment : Invoker { std::string name = ""; - std::unordered_map values; + memory values; env_type type = env_type::env; bool has(std::string index); - void set(std::string index, value* val); - value* get(std::string index); + void set(std::string index, value val); + value get(std::string index); }; } \ No newline at end of file diff --git a/DMS/loadtest.dms b/DMS/loadtest.dms index 49039b6..ee34156 100644 --- a/DMS/loadtest.dms +++ b/DMS/loadtest.dms @@ -1,5 +1,3 @@ -enable tests -disable hello [default:char] // The default stats for all characters. money = 0 diff --git a/DMS/memory.cpp b/DMS/memory.cpp new file mode 100644 index 0000000..74bedb7 --- /dev/null +++ b/DMS/memory.cpp @@ -0,0 +1,13 @@ +#include "memory.h" +#include +namespace dms { + value& memory::operator[](std::string str) { + return mem[str]; + } + size_t memory::count(std::string str) { + return mem.count(str); + } + void memory::erase(std::string str) { + mem.erase(str); + } +} \ No newline at end of file diff --git a/DMS/memory.h b/DMS/memory.h new file mode 100644 index 0000000..570a71a --- /dev/null +++ b/DMS/memory.h @@ -0,0 +1,14 @@ +#pragma once +#include +#include +#include "value.h" +namespace dms { + struct memory + { + size_t count(std::string); + void erase(std::string); + value& operator[](std::string); + private: + std::unordered_map mem; + }; +} diff --git a/DMS/number_utils.cpp b/DMS/number_utils.cpp index 2da5416..e69de29 100644 --- a/DMS/number_utils.cpp +++ b/DMS/number_utils.cpp @@ -1,35 +0,0 @@ -#include "number_utils.h" -namespace dms::number_utils { - dms_number* huge(dms_state* state) { - return buildNumber(std::numeric_limits::max()); - } - dms_number* tiny(dms_state* state) { - return buildNumber(std::numeric_limits::min()); - } - dms_number* abs(dms_state* state, dms_args args) { - if (args.args.size() == 0) - return buildNumber(-1); // ABS cannot be -1, this is an error - if (utils::typeassert(args, number)) { - double temp = args.args[0]->n->val; - return buildNumber(temp*temp / 2); - } - return buildNumber(-1); - } - dms_number* max(dms_state* state, dms_args args) { - size_t size = args.args.size(); - double max = std::numeric_limits::min(); - for (int i = 0; i < size; i++) { - if (args.args[i]->n->val > max) - max = args.args[i]->n->val; - } - return buildNumber(max); - } - dms_number* pow(dms_state* state, dms_args args) { - if (args.args.size() != 2) - return buildNumber(-1); // Pow requires 2 arguments - if (utils::typeassert(args, number,number)) { - - } - return buildNumber(-1); - } -} \ No newline at end of file diff --git a/DMS/string_utils.cpp b/DMS/string_utils.cpp deleted file mode 100644 index 6650db3..0000000 --- a/DMS/string_utils.cpp +++ /dev/null @@ -1,189 +0,0 @@ -#include "string_utils.h" - -uint8_t* copyStr(dms::dms_string str, size_t start, size_t size) { - uint8_t* newptr = new uint8_t[size]; - std::copy(str.val + start, str.val + start + size, newptr); - return newptr; -} -uint8_t* copyStr(dms::dms_string str, dms::dms_number start, dms::dms_number size) { - uint8_t* newptr = new uint8_t[size.getValue()]; - std::copy(str.val + (size_t)start.getValue(), str.val + (size_t)start.getValue() + (size_t)size.getValue(), newptr); - return newptr; -} -namespace dms::string_utils { - // string - dms_string* reverse(dms_state* state, dms_args args) { - if (args.args.size() == 0) { - state->push_error(errors::error{ errors::invalid_arguments,"Expected a string object, got nil."}); - return buildString(""); - } - if (utils::typeassert(state, args, string)) { - size_t size = args.args[0]->s->length; - uint8_t* newptr = copyStr(*args.args[0]->s, 0, size); - std::reverse(newptr, newptr + size); - dms_string* newstr = new dms_string{ size, newptr }; - return newstr; - } - return buildString(""); - } - //string number number - dms_string* sub(dms_state* state, dms_args args) { - if (args.args.size() == 0) { - state->push_error(errors::error{ errors::invalid_arguments,"Expected a string object, got nil."}); - return buildString(""); - } - if (utils::typeassert(state, args, string, number, number)) { - size_t start = args.args[1]->n->val; - size_t size = args.args[2]->n->val; - dms_string str = *args.args[0]->s; - if (start + size > str.length) { - state->push_error(errors::error{ errors::invalid_arguments,"Expected a string object, got nil." }); - return buildString(""); - } - else - { - uint8_t* newptr = copyStr(str, start, size); - dms_string* newstr = new dms_string{ size,newptr }; - return newstr; - } - } - return buildString(""); - } - //string - dms_string* upper(dms_state* state, dms_args args) { - if (args.args.size() == 0) { - state->push_error(errors::error{ errors::invalid_arguments,"Expected a string object, got nil." }); - return buildString(""); - } - if (utils::typeassert(state, args, string)) { - dms_string str = *args.args[0]->s; - uint8_t* newptr = copyStr(str, 0, str.length); - std::transform(newptr, newptr + str.length, newptr, toupper); - dms_string* newstr = new dms_string{ str.length, newptr }; - return newstr; - } - return buildString(""); - } - //string - dms_string* lower(dms_state* state, dms_args args) { - if (args.args.size() == 0) { - state->push_error(errors::error{ errors::invalid_arguments,"Expected a string object, got nil." }); - return buildString(""); - } - if (utils::typeassert(state, args, string)) { - dms_string str = *args.args[0]->s; - uint8_t* newptr = copyStr(str, 0, str.length); - std::transform(newptr, newptr + str.length, newptr, tolower); - dms_string* newstr = new dms_string{ str.length, newptr }; - return newstr; - } - return buildString(""); - } - //string string - dms_boolean* startsWith(dms_state* state, dms_args args) { - if (args.args.size() == 0) { - state->push_error(errors::error{ errors::invalid_arguments,"Expected a string object, got nil." }); - return buildBool(false); - } - if (utils::typeassert(state, args, string, string)) { - dms_string str = *args.args[0]->s; - dms_string starts = *args.args[1]->s; - if (starts.length > str.length) - return buildBool(false); - for (int i = 0; i < starts.length; i++) { - if (str.val[i] != starts.val[i]) { - return buildBool(false); - } - } - return buildBool(true); - } - return buildBool(false); - } - //string string - dms_boolean* endsWith(dms_state* state, dms_args args) { - if (args.args.size() == 0) { - state->push_error(errors::error{ errors::invalid_arguments,"Expected a string object, got nil." }); - return buildBool(false); - } - if (utils::typeassert(state, args, string, string)) { - dms_string str = *args.args[0]->s; - dms_string ends = *args.args[1]->s; - if (ends.length > str.length) - return buildBool(false); - for (int i = ends.length - 1; i >= 0; i--) { - //std::cout << str.val[i +(str.length - ends.length)] << " | " << ends.val[i] << " : " << i << std::endl; - if (str.val[i + (str.length - ends.length)] != ends.val[i]) { - return buildBool(false); - } - } - return buildBool(true); - } - return buildBool(false); - } - //string string - dms_number* indexOf(dms_state* state, dms_args args) { - if (args.args.size() == 0) { - state->push_error(errors::error{ errors::invalid_arguments,"Expected a string object, got nil." }); - return buildNumber(-1); - } - if (utils::typeassert(state, args, string, string)) { - bool check = false; - int ind; - dms_string str = *args.args[0]->s; - dms_string find = *args.args[1]->s; - for (int i = 0; i < str.length; i++) { - for (int ii = 0; ii < find.length; ii++) { - if (find.val[ii] == str.val[i + ii]) { - check = true; - ind = i; - } - else { - check = false; - break; - } - } - if (check) { - dms_number* newnum = new dms_number{ (double)ind }; - return newnum; - } - } - if (check) { - dms_number* newnum = new dms_number{ (double)ind }; - return newnum; - } - else { - dms_number* newnum = new dms_number{ -1 }; - return newnum; - } - } - return buildNumber(-1); - } - //string string - dms_boolean* includes(dms_state* state, dms_args args) { - if (args.args.size() == 0) { - state->push_error(errors::error{ errors::invalid_arguments,"Expected a string object, got nil." }); - return buildBool(false); - } - if (utils::typeassert(state, args, string, string)) { - return buildBool(indexOf(state, args)->val != -1); - } - return buildBool(false); - } - //string number - dms_string* repeat(dms_state* state, dms_args args) { - if (args.args.size() == 0) { - state->push_error(errors::error{ errors::invalid_arguments,"Expected a string object, got nil." }); - return buildString(""); - } - if (utils::typeassert(state, args, string, number)) { - dms_string str = *args.args[0]->s; - dms_number num = *args.args[1]->n; - std::string newstr = str.getValue(); - std::stringstream temp; - for (int i = 0; i < num.getValue(); i++) - temp << newstr; - return buildString(temp.str()); - } - return buildString(""); - } -} \ No newline at end of file diff --git a/DMS/test.dms b/DMS/test.dms index 0c249c0..d5bd735 100644 --- a/DMS/test.dms +++ b/DMS/test.dms @@ -5,15 +5,32 @@ enable forseelabels enable savestate disable fullname //enable leaking -enable debugging +//enable debugging loadfile "loadtest.dms" version 0.2 using extendedDefine [main] - "Time to test function calls!" - val = newblock(1,2,3) - "val = `val`" + Ryan: "Hello `Bob`, how are you doing?" + Bob: "Hi `Ryan`, I'm good." + a = 1000 + test = invokeTest("Running external code!"); + "Loop Test... `test`" + choice "Pick one" { + "this" goto "this" + "test2" tryme(true) + "that" goto "that" + "test" test(1,2,3) + } + ::this:: + "At \"this\"" + goto "loop" + ::that:: + "At \"that\"" + ::loop:: + a = a + 1 + "a = `a`" + goto "loop" [Bob:char] //fname = "Bob" @@ -24,6 +41,11 @@ using extendedDefine money = 100 excited: "path/to/file" +[test1:function()] + "Inside a function!" + //val = newblock(1,2,3) + //"val = `val`" + [newblock:function(a,b,c)] "Func Arguments: a = `a`, b = `b`, c = `c`" "Time to return" diff --git a/DMS/utils.cpp b/DMS/utils.cpp index c36817d..1a0f120 100644 --- a/DMS/utils.cpp +++ b/DMS/utils.cpp @@ -46,12 +46,12 @@ namespace dms::utils { 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(state)->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(state)->type != types[i]) + if (args.args[i].resolve(state).type != types[i]) return false; } return true; @@ -60,12 +60,12 @@ namespace dms::utils { size_t size = args.args.size(); if (size >= 4) for (size_t i = 0; i < 4; i++) { - if (args.args[i]->resolve(state)->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(state)->type != t1) + if (args.args[i].resolve(state).type != t1) return false; } return true; @@ -75,12 +75,12 @@ namespace dms::utils { 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]->type != types[i]) + if (args.args[i].type != types[i]) return false; } else for (size_t i = 0; i < size; i++) { - if (args.args[i]->type != types[i]) + if (args.args[i].type != types[i]) return false; } return true; @@ -90,15 +90,15 @@ namespace dms::utils { 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]->type != types[i]) { - state->push_error(dms::errors::error{ errors::invalid_arguments, "Invalid arguments! Expected (" + resolveTypes(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12) + ") Got: " + resolveTypes(args.args[i]->type)}); + if (args.args[i].type != types[i]) { + state->push_error(dms::errors::error{ errors::invalid_arguments, "Invalid arguments! Expected (" + resolveTypes(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12) + ") Got: " + resolveTypes(args.args[i].type)}); return false; } } else for (size_t i = 0; i < size; i++) { - if (args.args[i]->type != types[i]) { - state->push_error(dms::errors::error{ errors::invalid_arguments, "Invalid arguments! Expected (" + resolveTypes(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12) + ") Got: " + resolveTypes(args.args[i]->type)}); + if (args.args[i].type != types[i]) { + state->push_error(dms::errors::error{ errors::invalid_arguments, "Invalid arguments! Expected (" + resolveTypes(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12) + ") Got: " + resolveTypes(args.args[i].type)}); return false; } } diff --git a/DMS/utils.h b/DMS/utils.h index f63a986..39c4069 100644 --- a/DMS/utils.h +++ b/DMS/utils.h @@ -10,11 +10,11 @@ #include namespace dms::utils { template - void print(Args... args) { + void print(const Args... args) { (std::cout << ... << args) << std::endl; } template - void write(Args... args) { + void write(const Args... args) { (std::cout << ... << args); } template diff --git a/DMS/value.cpp b/DMS/value.cpp index d5b998c..5d08976 100644 --- a/DMS/value.cpp +++ b/DMS/value.cpp @@ -2,42 +2,211 @@ #include "dms_state.h" #include "utils.h" namespace dms { - const std::string datatype[] = { "escape","nil", "number", "boolean", "env", "string", "custom", "variable", "block" }; - std::vector _VALUES; + const std::string datatype[] = { "escape", "nil", "number", "boolean", "env", "string", "custom", "variable", "block" }; value::value() { - _VALUES.push_back(this); // Used for the interperter! In the end everything is a value - // We need to clean up this stuff when it all comes crashing. - // We also might clean things while the code is running. - // Values at runtime aren't "Deleted, they are set to nil" - // At the end we actually delete them! + // Nothing to do here yet! } - 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(char const* str, datatypes t) { + type = t; + s = buildString(str); } - 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; + value::value(char const* str) { + type = datatypes::string; + s = buildString(str); } - void dms_args::push(value* val) { + value::value(std::string str) { + type = datatypes::string; + s = buildString(str); + } + value::value(std::string str,datatypes t) { + type = t; + s = buildString(str); + } + value::value(double d) { + type = datatypes::number; + n = d; + } + value::value(int d) { + type = datatypes::number; + n = d; + } + value::value(bool bo) { + type = datatypes::boolean; + b = bo; + } + value::~value() { + nuke(); + } + size_t count = 0; + value::value(datatypes t) : value() { + if (t == datatypes::variable) { + set(buildString(utils::concat("$",++count))); + } + type = t; + } + value::value(const value& other) { + if (this != &other) { + type = other.type; + switch (other.type) { + case datatypes::block: + s = buildString(other.s->val); + break; + case datatypes::boolean: + b = buildBool(other.b); + break; + case datatypes::custom: + // Handle this later + break; + case datatypes::env: + // Handle this later + break; + case datatypes::escape: + s = buildString(other.s->val); + break; + case datatypes::nil: + // No need to do anything + break; + case datatypes::number: + n = other.n; + break; + case datatypes::string: + s = buildString(other.s->val); + break; + case datatypes::variable: + s = buildString(other.s->val); + break; + default: + break; + } + } + } + value& value::operator=(value& other) { + if (this != &other) { + nuke(); // Delete it all + type = other.type; + switch (other.type) { + case datatypes::block: + s = buildString(other.s->val); + break; + case datatypes::boolean: + b = other.b; + break; + case datatypes::custom: + // Handle this later + break; + case datatypes::env: + // Handle this later + break; + case datatypes::escape: + s = buildString(other.s->val); + break; + case datatypes::nil: + // No need to do anything + break; + case datatypes::number: + n = other.n; + break; + case datatypes::string: + s = buildString(other.s->val); + break; + case datatypes::variable: + s = buildString(other.s->val); + break; + default: + break; + } + //other.nuke(); + } + // by convention, always return *this + return *this; + } + bool value::isNil() { + return type == datatypes::nil; + } + value& value::operator=(const value& other) { + if (this != &other) { + nuke(); + type = other.type; + switch (other.type) { + case datatypes::block: + s = buildString(other.s->val); + break; + case datatypes::boolean: + b = other.b; + break; + case datatypes::custom: + // Handle this later + break; + case datatypes::env: + // Handle this later + break; + case datatypes::escape: + s = buildString(other.s->val); + break; + case datatypes::nil: + // No need to do anything + break; + case datatypes::number: + n = other.n; + break; + case datatypes::string: + s = buildString(other.s->val); + break; + case datatypes::variable: + s = buildString(other.s->val); + break; + default: + break; + } + } + // by convention, always return *this + return *this; + } + bool operator==(const value& lhs, const value& rhs) { + return lhs.getPrintable() == rhs.getPrintable(); + } + value operator+(const value& lhs, const value& rhs) { + if (lhs.type == datatypes::number && rhs.type == datatypes::number) { + return value(lhs.n + rhs.n); + } + else { + return lhs.getPrintable() + rhs.getPrintable(); + } + } + value operator-(const value& lhs, const value& rhs) { + if (lhs.type == datatypes::number && rhs.type == datatypes::number) { + return value(lhs.n - rhs.n); + } + else { + return value(datatypes::error); + } + } + value operator/(const value& lhs, const value& rhs) { + if (lhs.type == datatypes::number && rhs.type == datatypes::number) { + return value(lhs.n / rhs.n); + } + else { + return value(datatypes::error); + } + } + value operator*(const value& lhs, const value& rhs) { + if (lhs.type == datatypes::number && rhs.type == datatypes::number) { + return value(lhs.n * rhs.n); + } + else { + return value(datatypes::error); + } + } + bool operator!=(const value& lhs, const value& rhs) { + return !(lhs.getPrintable() == rhs.getPrintable()); + } + value value::resolve(dms_state* state) { + if (type == datatypes::variable && (*this)!=(*state->getMem())[getPrintable()]) { + return (*state->getMem())[getPrintable()].resolve(state); + } + return *this; + } + void dms_args::push(value val) { args.push_back(val); } size_t dms_args::size() { @@ -49,7 +218,7 @@ namespace dms { std::stringstream ind; bool varStart = false; bool indStart = false; - for (size_t i = 0; i < length; i++) { + for (size_t i = 0; i < val.size(); i++) { if (indStart && val[i] == '`') { std::string lookup = var.str(); std::string index = ind.str(); @@ -60,21 +229,21 @@ namespace dms { varStart = false; indStart = false; 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()); + value v = (*state->getMem())[lookup]; + if (v.type == datatypes::block) { + if (state->getCharacter(v.getPrintable()) != nullptr) { + character* cha = state->getCharacter(v.getPrintable()); if (cha->values.count(index)) { - temp << cha->values[index]->getPrintable(); + temp << cha->values[index].getPrintable(); } else { temp << cha->getName(); } } - 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()); + else if (state->getEnvironment(v.getPrintable())!=nullptr) { + enviroment* env = state->getEnvironment(v.getPrintable()); if (env->values.count(index)) { - temp << env->values[index]->getPrintable(); + temp << env->values[index].getPrintable(); } else { temp << env; @@ -84,14 +253,14 @@ namespace dms { temp << "nil"; } } - 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 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)-(int64_t)1].getPrintable(); else temp << "nil"; } else { - temp << v->resolve(state)->getPrintable(); + temp << v.resolve(state).getPrintable(); } } else { @@ -121,17 +290,17 @@ namespace dms { var.clear(); varStart = false; 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(); + value v = (*state->getMem())[lookup]; + if (v.type == datatypes::block) { + if (state->getCharacter(v.s->getValue())) { + temp << state->characters[v.s->getValue()]->getName(); } else { temp << "nil"; } } else { - temp << v->resolve(state)->getPrintable(); + temp << v.resolve(state).getPrintable(); } } else { @@ -163,13 +332,13 @@ namespace dms { out << s->getValue(); } else if (type == number) { - out << n->getValue(); + out << n; } else if (type == nil) { out << "nil"; } else if (type == boolean) { - if (b->getValue()) + if (b) out << "true"; else out << "false"; @@ -189,112 +358,94 @@ namespace dms { return out.str(); } dms_string* buildString(std::string str) { - size_t len = str.length(); - uint8_t* arr = new uint8_t[len]; - for (size_t i = 0; i < len; i++) { - arr[i] = str.at(i); - } - dms_string* dms_str = new dms_string{ str.length(), arr }; + std::stringstream newstr; + for (int i = 0; i < str.size(); i++) + newstr << str[i]; + dms_string* dms_str = new dms_string{ newstr.str() }; return dms_str; } dms_boolean* buildBool(bool b) { - dms_boolean* dms_bool = new dms_boolean{b}; - return dms_bool; - } - dms_number* buildNumber(double num) { - dms_number* dms_num = new dms_number{ num }; - return dms_num; + return new dms_boolean{b}; } std::string value::toString() const { std::stringstream temp; temp << this; return temp.str(); } - value* buildValue() { - return new value; - } - value* buildNil() { - return new value; - } - size_t count = 0; - value* buildVariable() { - count++; - std::stringstream str; - str << "$" << count; - std::string val = str.str(); - return buildVariable(val); - } - value* buildBlock(std::string str) { - value* val = new value{}; - val->set(buildString(str)); - val->type = block; - return val; - } - value* buildVariable(std::string str) { - value* val = new value{}; - val->set(buildString(str)); - val->type = variable; - return val; - } - value* buildValue(char const* s) { - value* val = new value{}; - val->set(buildString(s)); - return val; - } - value* buildValue(std::string str) { - value* val = new value{}; - val->set(buildString(str)); - return val; - } - value* buildValue(double dbl) { - value* val = new value{}; - val->set(buildNumber(dbl)); - return val; - } - value* buildValue(int i) { - value* val = new value{}; - val->set(buildNumber((double)i)); - return val; - } - value* buildValue(bool b) { - value* val = new value{}; - val->set(buildBool(b)); - return val; - } + // Compile time void value::nuke() { - if (type == datatypes::custom) - c->_del(); - delete[] s; - delete[] b; - delete[] n; - delete[] e; - delete[] c; + delete s; + delete e; + delete c; s = nullptr; - b = nullptr; - n = nullptr; e = nullptr; c = nullptr; } + std::ostream& operator << (std::ostream& out, const value& c) { + if (c.type == string) { + out << (char)c.type << c.s->getValue() << (char)0; + } + else if (c.type == number) { + out << (char)c.type << c.n; + } + else if (c.type == nil) { + out << (char)c.type << "nil"; + } + else if (c.type == boolean) { + if(c.b) + out << (char)c.type << "true"; + else + out << (char)c.type << "false"; + } + else if (c.type == env) { + out << (char)c.type << "Env: " << c; + } + else if (c.type == custom) { + out << (char)c.type << "Custom Data: " << c; + } + else if (c.type == block) { + out << (char)c.type << c.s->getValue(); + } + else if (c.type == datatypes::variable) { + out << (char)c.type << c.s->getValue(); // Do the lookup + } + return out; + }; // Fixed issue with memory not properly being cleaned up bool value::typeMatch(const value* o) const { return type == o->type; } + void value::set(value* val) { + if (type == datatypes::number) { + n = val->n; + } + else if (type == datatypes::string || type == datatypes::block || type == datatypes::variable) { + s->val = val->s->val; + } + else if (type == datatypes::boolean) { + b = val->b; + } + else { // Handle custom and env + return; + } + type = val->type; + } void value::set(dms_string* str) { nuke(); s = str; type = string; } - void value::set(dms_boolean* bo) { + void value::set(bool bo) { nuke(); b = bo; type = boolean; } - void value::set(dms_number* num) { + void value::set(double num) { nuke(); n = num; type = number; } - void dms::value::set(dms_env* en) { + void dms::value::set(dms_list* en) { nuke(); e = en; type = env; @@ -310,35 +461,45 @@ namespace dms { type = nil; } std::string dms_string::getValue() { - std::stringstream temp; - for (size_t i = 0; i < length; i++) { - temp << val[i]; - } - return temp.str(); + return val; } - void dms_env::pushValue(value* val) { + void dms_list::pushValue(value val) { ipart.push_back(val); } - void dms_env::pushValue(value* ind, value* val) { - if (val->type == nil) { - hpart[ind->toString()]->nuke(); - hpart.erase(ind->toString()); - count--; + value dms_list::getValue(value ind) { + if (ind.type == number) { + return ipart.at((int)ind.n); } else { - hpart.insert_or_assign(ind->toString(), val); - count++; + return new value(); } } - value* dms_env::getValue(value* ind) { - if (ind->type == number) { - return ipart.at((int)ind->n->getValue()); + std::ostream& operator << (std::ostream& out, const dms_args& c) { + for (size_t i = 0; i < c.args.size(); i++) { + if (i == c.args.size() - 1) + out << c.args[i]; + else + out << c.args[i] << ", "; } - else if (ind->type == number) { - return new value{}; // Return a nil value - } - else { - return hpart.at(ind->toString()); + return out; + } + std::string dms_args::toString() { + std::stringstream str; + for (size_t i = 0; i < args.size(); i++) { + str << args[i]; } + return str.str(); + } + std::ostream& operator << (std::ostream& out, const dms_string& c) { + out << c.val; + return out; + } + std::ostream& operator << (std::ostream& out, const dms_boolean& c) { + out << c.val; + return out; + } + std::ostream& operator << (std::ostream& out, const dms_number& c) { + out << c.val; + return out; } } \ No newline at end of file diff --git a/DMS/value.h b/DMS/value.h index 06dccdb..8f9db2b 100644 --- a/DMS/value.h +++ b/DMS/value.h @@ -6,157 +6,100 @@ #include namespace dms { - struct dms_env; + struct dms_list; struct value; struct dms_args; + struct dms_state; extern const std::string datatype[]; enum datatypes { escape, nil, number, boolean, env, string, custom, variable, block, error }; struct dms_number { double val; double getValue() { return val; } - friend std::ostream& operator << (std::ostream& out, const dms_number& c) { - out << c.val; - return out; - }; + friend std::ostream& operator << (std::ostream& out, const dms_number& c); }; struct dms_boolean { bool val; bool getValue() { return val; } - friend std::ostream& operator << (std::ostream& out, const dms_boolean& c) { - out << c.val; - return out; - }; + friend std::ostream& operator << (std::ostream& out, const dms_boolean& c); }; - struct dms_state; + struct dms_string { - size_t length = 0; - uint8_t* val = nullptr; + std::string val; std::string getValue(); std::string getValue(dms_state* state); - friend std::ostream& operator << (std::ostream& out, const dms_string& c) { - for (size_t i = 0; i < c.length; i++) { - std::cout << c.val[i]; - } - return out; - }; + friend std::ostream& operator << (std::ostream& out, const dms_string& c); }; // Custom data that you can work with by overriding this code struct dms_custom { void Init(dms_state* state); void _set(value* v); void _del(); - - virtual value* Index(value* data); - virtual bool NewIndex(value* var, value* val); - virtual value* Call(dms_args* args); - virtual value* ToString(); - virtual value* ADD(value* left, value* right); - virtual value* SUB(value* left, value* right); - virtual value* MUL(value* left, value* right); - virtual value* DIV(value* left, value* right); - virtual value* POW(value* left, value* right); - virtual value* EQUAL(value* left, value* right); - virtual value* LESS_THAN(value* left, value* right); - virtual value* LESS_THAN_EQUAL(value* left, value* right); + virtual value Index(value data); + virtual bool NewIndex(value var, value val); + virtual value Call(dms_args* args); + virtual value ToString(); + virtual value ADD(value left, value right); + virtual value SUB(value left, value right); + virtual value MUL(value left, value right); + virtual value DIV(value left, value right); + virtual value POW(value left, value right); + virtual value EQUAL(value left, value right); + virtual value LESS_THAN(value left, value right); + virtual value LESS_THAN_EQUAL(value left, value right); private: dms_state* state=nullptr; value* self; }; dms_string* buildString(std::string str); dms_boolean* buildBool(bool b); - dms_number* buildNumber(double num); struct value { public: - datatypes type = nil; - dms_boolean* b = nullptr; - dms_number* n = nullptr; + datatypes type = datatypes::nil; + bool b=false; + double n=0; dms_string* s = nullptr; - dms_env* e = nullptr; + dms_list* e = nullptr; dms_custom* c = nullptr; value(); - value* resolve(dms_state*); - value* copy(); + value(datatypes); + value(char const*,datatypes); + value(std::string, datatypes); + value(std::string); + value(char const*); + value(double); + value(int); + value(bool); + ~value(); + value(const value& other); + bool isNil(); + value& operator=(value& other); + value& operator=(const value& other); + friend bool operator==(const value& lhs, const value& rhs); + friend value operator+(const value& lhs, const value& rhs); + friend value operator-(const value& lhs, const value& rhs); + friend value operator/(const value& lhs, const value& rhs); + friend value operator*(const value& lhs, const value& rhs); + friend bool operator!=(const value& lhs, const value& rhs); + value resolve(dms_state*); void nuke(); + void set(value*); void set(dms_string* str); - void set(dms_boolean* bo); - void set(dms_number* num); - void set(dms_env* en); + void set(bool bo); + void set(double num); + void set(dms_list* en); void set(dms_custom* cus); void set(); bool typeMatch(const value* o) const; std::string getPrintable() const; std::string toString() const; - friend std::ostream& operator << (std::ostream& out, const value& c) { - if (c.type == string) { - out << (char)c.type << c.s->getValue() << (char)0; - } - else if (c.type == number) { - out << (char)c.type << c.n->getValue(); - } - else if (c.type == nil) { - out << (char)c.type << "nil"; - } - else if (c.type == boolean) { - if(c.b->getValue()) - out << (char)c.type << "true"; - else - out << (char)c.type << "false"; - } - else if (c.type == env) { - out << (char)c.type << "Env: " << c; - } - else if (c.type == custom) { - out << (char)c.type << "Custom Data: " << c; - } - else if (c.type == block) { - out << (char)c.type << c.s->getValue(); - } - else if (c.type == datatypes::variable) { - out << (char)c.type << c.s->getValue(); // Do the lookup - } - return out; - }; + friend std::ostream& operator << (std::ostream& out, const value& c); }; - value* buildValue(); - value* buildValue(char const* s); - value* buildNil(); - value* buildVariable(std::string str); - value* buildVariable(); - value* buildValue(std::string str); - value* buildValue(double dbl); - value* buildValue(int i); - value* buildValue(bool b); - value* buildBlock(std::string str); struct dms_args { - std::vector args; - void push(value* val); + std::vector args; + void push(value val); size_t size(); - friend std::ostream& operator << (std::ostream& out, const dms_args& c) { - for (size_t i=0; i < c.args.size(); i++) { - if(i==c.args.size()-1) - out << c.args[i]; - else - out << c.args[i] << ", "; - } - return out; - } - std::string toString() { - std::stringstream str; - for (size_t i = 0; i < args.size(); i++) { - str << *args[i]; - } - return str.str(); - } - }; - struct dms_env - { - std::unordered_map hpart; - std::vector ipart; - void pushValue(value* val); - void pushValue(value* ind, value* val); - value* getValue(value* val); - private: - size_t count = 0; + friend std::ostream& operator << (std::ostream& out, const dms_args& c); + std::string toString(); }; }