From 31da0b35ebb7f686d94042b219ca68deb2976dd9 Mon Sep 17 00:00:00 2001 From: Ryan Ward Date: Sun, 6 Dec 2020 23:45:16 -0500 Subject: [PATCH] Better error handling --- DMS/LineParserMatchProcess.cpp | 36 +++--- DMS/LineParserParse.cpp | 13 ++- DMS/dms_state.cpp | 56 ++++++--- DMS/dms_state_interpret.cpp | 102 ++++++++++++----- DMS/dump.bin | Bin 1011 -> 1157 bytes DMS/dump.txt | 204 ++++++++++++++++----------------- DMS/memory.cpp | 13 +++ DMS/memory.h | 2 + DMS/test.dms | 16 ++- DMS/value.cpp | 28 ++++- README.md | 4 +- 11 files changed, 293 insertions(+), 181 deletions(-) diff --git a/DMS/LineParserMatchProcess.cpp b/DMS/LineParserMatchProcess.cpp index 96c9bae..40fff82 100644 --- a/DMS/LineParserMatchProcess.cpp +++ b/DMS/LineParserMatchProcess.cpp @@ -5,7 +5,7 @@ using namespace dms::utils; namespace dms { bool LineParser::match_process_standard(tokenstream* stream, value& v) { stream->chomp(newline); - utils::debug(stream->peek()); + //utils::debug(stream->peek()); if (stream->peek().type == tokens::none) { return false; } @@ -593,16 +593,22 @@ namespace dms { else if (stream->match(tokens::string)) { std::string name = stream->next().name; c->args.push(value(name)); // We append the choice to the first part of the CHOI cmd - - 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); - } - else if (match_process_goto(stream)) {} + if (match_process_goto(stream)) {} else if (match_process_jump(stream)) {} else if (match_process_exit(stream)) {} + else if (match_process_scope(stream)) { + buildGoto(choicelabel); + } + else { + badSymbol(stream); + } + //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; + // + //} + } // Last Match else if (stream->match(tokens::newline)) { @@ -612,12 +618,11 @@ namespace dms { badSymbol(stream); } } - buildGoto(choicelabel); cmd* cc = current_chunk->cmds.back(); // Delete last element current_chunk->cmds.pop_back(); delete cc; - if (hasfunc) - buildLabel(choicelabel); + buildLabel(choicelabel); + stream->next(); // Remove the last bracket! return true; } return false; @@ -919,10 +924,7 @@ namespace dms { } return false; } - /* - We need to match {...} - This doesn't pass any varaible. It should be used to match and process program flow - */ + bool LineParser::match_process_scope(tokenstream* stream) { if (stream->match(cbracketo)) { size_t last_line = stream->last().line_num; @@ -1095,7 +1097,7 @@ namespace dms { std::vector temp; codes::op o; while (ts.can()) { - utils::debug(ts.peek()); + //utils::debug(ts.peek()); if (ts.match(tokens::string)) { temp.push_back(value(ts.next().name)); } diff --git a/DMS/LineParserParse.cpp b/DMS/LineParserParse.cpp index 0cee25e..10846df 100644 --- a/DMS/LineParserParse.cpp +++ b/DMS/LineParserParse.cpp @@ -348,6 +348,7 @@ namespace dms { token current = token{tokentype::newline,codes::NOOP}; cmd* flagcmd = new cmd; value nil; + size_t last_pos = SIZE_MAX; while (stream->peek().type != tokens::none) { if (stop) return false; debugInvoker(stream); @@ -490,7 +491,8 @@ namespace dms { } } // Control Handle all controls here - manageCount(match_process_while(stream),count,current_count); + manageCount(match_process_choice(stream), count, current_count); + manageCount(match_process_while(stream), count, current_count); manageCount(match_process_for(stream), count, current_count); manageCount(match_process_IFFF(stream), count, current_count); // Let's handle function stuff! @@ -521,9 +523,14 @@ namespace dms { if (count != 0 && current_count == count) { return true; // We got what we came for, we exit and consume no more! } - if(stream->match(newline) || stream->match(eof)) + if (last_pos == stream->pos) { + badSymbol(stream); + } + last_pos = stream->pos; + if (stream->match(newline) || stream->match(eof)) { current = stream->next(); - utils::debug(stream->peek()); + } + } } void LineParser::_Parse(tokenstream* stream) { diff --git a/DMS/dms_state.cpp b/DMS/dms_state.cpp index 6ddc9b8..e0acd86 100644 --- a/DMS/dms_state.cpp +++ b/DMS/dms_state.cpp @@ -1,6 +1,37 @@ #include "dms_state.h" #include "Handlers.h" namespace dms { + 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; + state->pushMem(); + memory* Fmem = state->getMem(); + // Only the nil argument + if (args->args.size()) + for (int i = 0; i < state->chunks[func]->params.args.size(); i++) + (*Fmem)[state->chunks[func]->params.args.at(i).getPrintable()] = args->args.at(i).resolve(state); + + if (!state->run(func, Fmem)) { + std::vector err = Fmem->examine(datatypes::error); + if (err.size() > 0) + state->push_error(errors::error{ errors::unknown ,err[0].s }); + else + state->push_error(errors::error{ errors::unknown ,"Function Returned an error!" }); + state->popMem();// We need to restore the stack + return value("Function returned an error", datatypes::error); + } + ret = state->return_stack.top(); + state->return_stack.pop(); + state->popMem(); + return ret; + } + return value(); + } + + + void dms_state::init() { if (init_init || stop) return; @@ -43,24 +74,6 @@ namespace dms { void dms_state::popMem() { mem_stack.pop(); } - value dms::blockInvoke(void* self, dms_state* state, dms_args* args) { - std::string func = state->call_stack.top(); - if (state->functionExists(func)) { - state->call_stack.pop(); - value ret; - state->pushMem(); - memory* Fmem = state->getMem(); - for (int i = 0; i < state->chunks[func]->params.args.size(); i++) { - (*Fmem)[state->chunks[func]->params.args[i].getPrintable()] = args->args[i].resolve(state); - } - state->run(func, Fmem); - ret = state->return_stack.top(); - state->return_stack.pop(); - state->popMem(); - return ret; - } - return value(); - } dms_state::dms_state() { // We should define the defaults for the enables pushMem(); // Main memory @@ -127,6 +140,11 @@ namespace dms { } bool dms_state::assign(value var, value val) { + if (val.type == datatypes::error) { + (*getMem())[var.getPrintable()] = val; + push_error(errors::error{ errors::unknown ,val.s }); + return false; + } (*getMem())[var.getPrintable()] = val; return true; } @@ -141,6 +159,8 @@ namespace dms { chunks.insert_or_assign(s, c); } void dms_state::push_error(errors::error err) { + if (stop) + return; if (err.linenum != 0) { std::cout << err.err_msg << " On Line <" << err.linenum << ">" << std::endl; } diff --git a/DMS/dms_state_interpret.cpp b/DMS/dms_state_interpret.cpp index b6e865d..96c857c 100644 --- a/DMS/dms_state_interpret.cpp +++ b/DMS/dms_state_interpret.cpp @@ -191,14 +191,20 @@ namespace dms { value cmp = c->args.args[0]; if (cmp.resolve(this).type == datatypes::boolean || cmp.resolve(this).isNil()) { if (!cmp.resolve(this).b || cmp.resolve(this).isNil()) { - assign(cmp, value(true)); + if(!assign(cmp, value(true))) { + return false; + } } else { - assign(cmp, value(false)); + if(!assign(cmp, value(false))) { + return false; + } } } else { - assign(cmp, value(false)); + if(!assign(cmp, value(false))) { + return false; + } } break; } @@ -266,7 +272,9 @@ namespace dms { if (ret.type == datatypes::error) return false; if (assn.type != datatypes::nil) { - assign(assn, ret); + if(!assign(assn, ret)) { + return false; + } } } break; @@ -290,7 +298,9 @@ namespace dms { if (ret.type == datatypes::error) return false; if (assn.type != datatypes::nil) { - assign(assn, ret); + if(!assign(assn, ret)) { + return false; + } } } break; @@ -320,7 +330,7 @@ namespace dms { } else if (env.type == datatypes::custom) { env.c->NewIndex(indx, assn); - //assign( assn, env->c->Index(indx)); + //if(!assign( assn, env->c->Index(indx)); // Call the method within the custom data } break; @@ -330,8 +340,10 @@ namespace dms { value assn = c->args.args[0]; value o1 = c->args.args[1]; value o2 = c->args.args[2]; - value ret = value(o1.resolve(this)+o2.resolve(this)); - assign(assn, ret); + value ret = o1.resolve(this)+o2.resolve(this); + if(!assign(assn, ret)) { + return false; + } } break; case SUB: @@ -339,8 +351,10 @@ namespace dms { value assn = c->args.args[0]; value o1 = c->args.args[1]; value o2 = c->args.args[2]; - value ret = value(o1.resolve(this) - o2.resolve(this)); - assign(assn, ret); + value ret = o1.resolve(this) - o2.resolve(this); + if(!assign(assn, ret)) { + return false; + } } break; case MUL: @@ -348,8 +362,10 @@ namespace dms { value assn = c->args.args[0]; value o1 = c->args.args[1]; value o2 = c->args.args[2]; - value ret = value(o1.resolve(this) * o2.resolve(this)); - assign(assn, ret); + value ret = o1.resolve(this) * o2.resolve(this); + if(!assign(assn, ret)) { + return false; + } } break; case DIV: @@ -357,8 +373,10 @@ namespace dms { value assn = c->args.args[0]; value o1 = c->args.args[1]; value o2 = c->args.args[2]; - value ret = value(o1.resolve(this) / o2.resolve(this)); - assign(assn, ret); + value ret = o1.resolve(this) / o2.resolve(this); + if(!assign(assn, ret)) { + return false; + } } break; case POW: @@ -366,8 +384,10 @@ namespace dms { 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); + value ret = pow(o1.resolve(this).n, o2.resolve(this).n); + if(!assign(assn, ret)) { + return false; + } } break; case MOD: @@ -375,8 +395,10 @@ namespace dms { 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); + value ret = std::fmod(o1.resolve(this).n,o2.resolve(this).n); + if(!assign(assn, ret)) { + return false; + } } break; case INDX: @@ -392,11 +414,15 @@ namespace dms { else if (characters.count(env.getPrintable())) { e = characters[env.getPrintable()]; } - assign( assn, e->values[indx.getPrintable()]); + if(!assign( assn, e->values[indx.getPrintable()])) { + return false; + } } else if (env.type == datatypes::env) { if (indx.type == datatypes::number) { - assign( assn, env.e->getValue(indx)); + if(!assign( assn, env.e->getValue(indx))) { + return false; + } } else { push_error(errors::error{ errors::invalid_type ,concat("Expected a number value got ",datatype[indx.type]) }); @@ -404,7 +430,9 @@ namespace dms { } } else if (env.type == datatypes::custom) { - assign( assn, env.c->Index(indx)); + if(!assign( assn, env.c->Index(indx))) { + return false; + } // Call the method within the custom data } } @@ -417,7 +445,9 @@ namespace dms { env->hpart["$size"] = c->args.args[1]; value val = new value; val.set(env); - assign(c->args.args[0], val); + if(!assign(c->args.args[0], val)) { + return false; + } } break; case INST: @@ -434,31 +464,43 @@ namespace dms { value right = c->args.args[3].resolve(this); switch (cmp) { case comp::eq: { - assign(assn, value(left == right)); + if(!assign(assn, value(left == right))) { + return false; + } break; } case comp::gt: { if (left.isNil() || right.isNil()) {push_error(errors::error{ errors::unknown ,"Attempt to compare a nil value!" });return false;} - assign(assn, value(left > right)); + if(!assign(assn, value(left > right))) { + return false; + } break; } case comp::gteq: { if (left.isNil() || right.isNil()) { push_error(errors::error{ errors::unknown ,"Attempt to compare a nil value!" }); return false; } - assign(assn, value(left >= right)); + if(!assign(assn, value(left >= right))) { + return false; + } break; } case comp::lt: { if (left.isNil() || right.isNil()) { push_error(errors::error{ errors::unknown ,"Attempt to compare a nil value!" }); return false; } - assign(assn, value(left < right)); + if(!assign(assn, value(left < right))) { + return false; + } break; } case comp::lteq: { if (left.isNil() || right.isNil()) { push_error(errors::error{ errors::unknown ,"Attempt to compare a nil value!" }); return false; } - assign(assn, value(left <= right)); + if(!assign(assn, value(left <= right))) { + return false; + } break; } case comp::nteq: { - assign(assn, value(left != right)); + if(!assign(assn, value(left != right))) { + return false; + } break; } } @@ -504,7 +546,9 @@ namespace dms { return false; break; case ASGN: - assign(c->args.args[0], c->args.args[1]); + if(!assign(c->args.args[0], c->args.args[1])) { + return false; + } break; case LINE: cur_line = (size_t)c->args.args[0].n; diff --git a/DMS/dump.bin b/DMS/dump.bin index e1bedce80d097861b07f9cd3c2e9fdba308eb904..b3dcc70c577c11e0c932978e05d27a76289328df 100644 GIT binary patch literal 1157 zcmaKqOOM(x5P)eVD-{y|VJhXk3nW_Ytx6z3S~gT9RP70Q!4zu~8zrHXf8Vhk6IynA zNyhX1<`K?EUw{;piw?Z+L$5oUEn*-EJHco#`G!Hps=5QD#^2qxs8C!SYAyu~T5;Hl zUI&xRgK!Q+rCQs#bzd1Kt7HVuj&5pj+#!$||JZ@na45N`;ho^QHY>w)ku89@I#-m8 z*MBD+yjc$EY_LL5uh*!M+)`Z?CqGyP^`2L7lI2VF79$Bt24{JMJv|)GpG+sF%Kw2) zQ%r1IEDLESbj>njC2I&w?k29+4fXO|980sj=zE-*HC~Ky5@*($WJ|m2UUwX)0T5XT zUTruNdO}eWgg|!3JQuWJ3a-(}@7MaYu? zlFEX?l8UV?V0t{Octc8mGQB?kqA8?cXB=N&5vN&@fx~`pc+Ivz4z%9i*YbYHbG`i* Onc9`UhOCUY$bSGJnF-DS literal 1011 zcmZuw!E&206inJ-=rF@S=)gG%cGFCbU;`y}aK_-YH%7KaOaj8S<+|zD_dN-LTl)fN zpY(RM`|u~DZ^Wo+$uG!<8)92t8YRS}YBBNr2{FEZP4mM2^5+7|aTtc=quA~l;z9oM zwvG|^#$!B%2VGc(^JGNK&9>x%T=KHQf_&RnG|i^}_S7tWH;ttEb2&VmG}SNrlX#bAq+aK(O$@p+A6;d~xy#xIX+MZ@!Mojj5Sqioy#)gXZwP>!3vXbfd QlBtgLd7lrfMSO5S3 diff --git a/DMS/dump.txt b/DMS/dump.txt index 3588104..10386fc 100644 --- a/DMS/dump.txt +++ b/DMS/dump.txt @@ -36,172 +36,172 @@ Line <12> name main Line <12> bracketc ] Line <12> newline Line <12> newline -Line <13> name a -Line <13> equal = -Line <13> number 0 +Line <13> control +Line <13> string New Choice Test +Line <13> cbracketo { Line <13> newline Line <13> newline -Line <14> name while +Line <14> string Option 1 +Line <14> name print Line <14> parao ( -Line <14> true true +Line <14> name fact +Line <14> parao ( +Line <14> string Hi! +Line <14> parac ) Line <14> parac ) Line <14> newline Line <14> newline -Line <15> name asm -Line <15> cbracketo { +Line <15> string Option 2 +Line <15> gotoo +Line <15> string test Line <15> newline Line <15> newline -Line <16> name add -Line <16> mod % -Line <16> name a -Line <16> mod % -Line <16> name a -Line <16> number 1 +Line <16> string Option 3 +Line <16> cbracketo { Line <16> newline Line <16> newline -Line <17> name func -Line <17> mod % Line <17> name print -Line <17> nil -Line <17> mod % -Line <17> name a -Line <17> nil nil +Line <17> parao ( +Line <17> string Yes this works! +Line <17> parac ) Line <17> newline Line <17> newline -Line <18> cbracketc } +Line <18> name print +Line <18> parao ( +Line <18> string Are you happy? +Line <18> parac ) Line <18> newline Line <18> newline -Line <19> name while -Line <19> parao ( -Line <19> true true -Line <19> parac ) -Line <19> cbracketo { +Line <19> cbracketc } Line <19> newline Line <19> newline -Line <20> name a -Line <20> equal = -Line <20> name a -Line <20> plus + -Line <20> number 1 +Line <20> cbracketc } Line <20> newline Line <20> newline -Line <21> name print -Line <21> parao ( -Line <21> name a -Line <21> parac ) +Line <21> gotoo +Line <21> string end Line <21> newline Line <21> newline -Line <22> cbracketc } +Line <22> label test Line <22> newline Line <22> newline +Line <23> name print +Line <23> parao ( +Line <23> string Here! +Line <23> parac ) Line <23> newline Line <23> newline -Line <24> bracketo [ -Line <24> name fact -Line <24> colon : -Line <24> name function -Line <24> parao ( -Line <24> name n -Line <24> parac ) -Line <24> bracketc ] +Line <24> label end Line <24> newline Line <24> newline -Line <25> name if -Line <25> parao ( -Line <25> name n -Line <25> equal = -Line <25> equal = -Line <25> number 1 -Line <25> or -Line <25> name n -Line <25> equal = -Line <25> equal = -Line <25> number 0 -Line <25> parac ) Line <25> newline Line <25> newline -Line <26> ret -Line <26> number 1 +Line <26> bracketo [ +Line <26> name fact +Line <26> colon : +Line <26> name function +Line <26> parao ( +Line <26> name n +Line <26> parac ) +Line <26> bracketc ] Line <26> newline Line <26> newline -Line <27> name else +Line <27> name if +Line <27> parao ( +Line <27> name n +Line <27> equal = +Line <27> equal = +Line <27> number 1 +Line <27> or +Line <27> name n +Line <27> equal = +Line <27> equal = +Line <27> number 0 +Line <27> parac ) Line <27> newline Line <27> newline Line <28> ret -Line <28> name n -Line <28> multiply * -Line <28> name fact -Line <28> parao ( -Line <28> name n -Line <28> minus - Line <28> number 1 -Line <28> parac ) Line <28> newline Line <28> newline +Line <29> name else Line <29> newline Line <29> newline -Line <30> bracketo [ -Line <30> name this -Line <30> colon : -Line <30> name function +Line <30> ret +Line <30> name n +Line <30> multiply * +Line <30> name fact Line <30> parao ( +Line <30> name n +Line <30> minus - +Line <30> number 1 Line <30> parac ) -Line <30> bracketc ] Line <30> newline Line <30> newline -Line <31> name print -Line <31> parao ( -Line <31> string This -Line <31> parac ) Line <31> newline Line <31> newline +Line <32> bracketo [ +Line <32> name this +Line <32> colon : +Line <32> name function +Line <32> parao ( +Line <32> parac ) +Line <32> bracketc ] Line <32> newline Line <32> newline -Line <33> bracketo [ -Line <33> name that -Line <33> colon : -Line <33> name function +Line <33> name print Line <33> parao ( +Line <33> string This Line <33> parac ) -Line <33> bracketc ] Line <33> newline Line <33> newline -Line <34> name print -Line <34> parao ( -Line <34> string That -Line <34> parac ) Line <34> newline Line <34> newline +Line <35> bracketo [ +Line <35> name that +Line <35> colon : +Line <35> name function +Line <35> parao ( +Line <35> parac ) +Line <35> bracketc ] Line <35> newline Line <35> newline -Line <36> bracketo [ -Line <36> name Bob -Line <36> colon : -Line <36> name char -Line <36> bracketc ] +Line <36> name print +Line <36> parao ( +Line <36> string That +Line <36> parac ) Line <36> newline Line <36> newline Line <37> newline +Line <37> newline +Line <38> bracketo [ +Line <38> name Bob +Line <38> colon : +Line <38> name char +Line <38> bracketc ] +Line <38> newline Line <38> newline Line <39> newline -Line <40> name unknown -Line <40> equal = -Line <40> string Some Random Guy Line <40> newline -Line <40> newline -Line <41> name age -Line <41> equal = -Line <41> number 0.24 Line <41> newline -Line <41> newline -Line <42> name money +Line <42> name unknown Line <42> equal = -Line <42> number 100 +Line <42> string Some Random Guy Line <42> newline Line <42> newline -Line <43> name excited -Line <43> colon : -Line <43> string path/to/file +Line <43> name age +Line <43> equal = +Line <43> number 0.24 Line <43> newline Line <43> newline -Line <43> eof +Line <44> name money +Line <44> equal = +Line <44> number 100 +Line <44> newline +Line <44> newline +Line <45> name excited +Line <45> colon : +Line <45> string path/to/file +Line <45> newline +Line <45> newline +Line <45> eof diff --git a/DMS/memory.cpp b/DMS/memory.cpp index 74bedb7..d136427 100644 --- a/DMS/memory.cpp +++ b/DMS/memory.cpp @@ -1,9 +1,22 @@ #include "memory.h" +#include #include +#include "utils.h" namespace dms { value& memory::operator[](std::string str) { return mem[str]; } + std::vector memory::examine(datatypes dt) + { + std::vector arr; + for (const auto& p : mem) + { + if (p.second.type == dt) { + arr.push_back(p.second); + } + } + return arr; + } size_t memory::count(std::string str) { return mem.count(str); } diff --git a/DMS/memory.h b/DMS/memory.h index 570a71a..a02c1f1 100644 --- a/DMS/memory.h +++ b/DMS/memory.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include "value.h" namespace dms { struct memory @@ -8,6 +9,7 @@ namespace dms { size_t count(std::string); void erase(std::string); value& operator[](std::string); + std::vector examine(datatypes dt); private: std::unordered_map mem; }; diff --git a/DMS/test.dms b/DMS/test.dms index df8a568..8ab30d5 100644 --- a/DMS/test.dms +++ b/DMS/test.dms @@ -10,12 +10,18 @@ enable savestate version 0.2 using extendedDefine [main] - a=0 - while(true) - asm { - add %a %a 1 - func %print nil %a nil + choice "New Choice Test" { + "Option 1" print(fact("Hi!")) + "Option 2" goto "test" + "Option 3" { + print("Yes this works!") + print("Are you happy?") } + } + goto "end" + ::test:: + print("Here!") + ::end:: [fact:function(n)] if(n==1 or n==0) diff --git a/DMS/value.cpp b/DMS/value.cpp index 8ccdb51..a25edb0 100644 --- a/DMS/value.cpp +++ b/DMS/value.cpp @@ -79,6 +79,8 @@ namespace dms { case datatypes::variable: s = other.s; break; + case datatypes::error: + s = other.s; default: break; } @@ -116,6 +118,8 @@ namespace dms { case datatypes::variable: s = other.s; break; + case datatypes::error: + s = other.s; default: break; } @@ -159,6 +163,8 @@ namespace dms { case datatypes::variable: s = other.s; break; + case datatypes::error: + s = other.s; default: break; } @@ -170,7 +176,10 @@ namespace dms { return lhs.getPrintable() == rhs.getPrintable(); } value operator+(const value& lhs, const value& rhs) { - if (lhs.type == datatypes::number && rhs.type == datatypes::number) { + if (lhs.type == datatypes::nil || rhs.type == datatypes::nil) { + return value("Attempt to concat a nil value!",datatypes::error); + } + else if (lhs.type == datatypes::number && rhs.type == datatypes::number) { return value(lhs.n + rhs.n); } else if (lhs.type == datatypes::boolean && rhs.type == datatypes::boolean) { @@ -180,7 +189,7 @@ namespace dms { return lhs.getPrintable() + rhs.getPrintable(); } else { - return "Invalid use of '+'"; + return value("Invalid use of '+'!", datatypes::error); } } value operator-(const value& lhs, const value& rhs) { @@ -188,7 +197,10 @@ namespace dms { return value(lhs.n - rhs.n); } else { - return value(datatypes::error); + if(lhs.type!=datatypes::number) + return value(utils::concat("Attempted to perform arithmetic on a ", datatype[lhs.type] ," value!"),datatypes::error); + else + return value(utils::concat("Attempted to perform arithmetic on a ", datatype[rhs.type], " value!"), datatypes::error); } } value operator/(const value& lhs, const value& rhs) { @@ -196,7 +208,10 @@ namespace dms { return value(lhs.n / rhs.n); } else { - return value(datatypes::error); + if (lhs.type != datatypes::number) + return value(utils::concat("Attempted to perform arithmetic on a ", datatype[lhs.type], " value!"), datatypes::error); + else + return value(utils::concat("Attempted to perform arithmetic on a ", datatype[rhs.type], " value!"), datatypes::error); } } value operator*(const value& lhs, const value& rhs) { @@ -207,7 +222,10 @@ namespace dms { return value((bool)(lhs.b * rhs.b)); } else { - return value(datatypes::error); + if (lhs.type != datatypes::number) + return value(utils::concat("Attempted to perform arithmetic on a ", datatype[lhs.type], " value!"), datatypes::error); + else + return value(utils::concat("Attempted to perform arithmetic on a ", datatype[rhs.type], " value!"), datatypes::error); } } bool operator!=(const value& lhs, const value& rhs) { diff --git a/README.md b/README.md index 869730c..115d394 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,8 @@ The Dialogue Management Script's goal is to provide a nice and simple way to hav # Todo - [X] ~~Implement bytecode for if/else if/else statements~~ -- [ ] Implement bytecode for for/~~while~~ loops +- [X] ~~Implement bytecode for for/while loops~~ - [X] ~~Implement bytecode for concatenation~~ -- [ ] Interpert all the bytecode +- [X] ~~Interpert all the bytecode~~ - [ ] Finish implementing custom datatype - [ ] Speed up interperter \ No newline at end of file