Better error handling

This commit is contained in:
Ryan Ward 2020-12-06 23:45:16 -05:00
parent 0bbb14dc06
commit 31da0b35eb
11 changed files with 293 additions and 181 deletions

View File

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

View File

@ -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,6 +491,7 @@ namespace dms {
}
}
// Control Handle all controls here
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);
@ -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) {

View File

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

View File

@ -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));
}
else {
assign(cmp, value(false));
if(!assign(cmp, value(true))) {
return false;
}
}
else {
assign(cmp, value(false));
if(!assign(cmp, value(false))) {
return false;
}
}
}
else {
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;

Binary file not shown.

View File

@ -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

View File

@ -1,9 +1,22 @@
#include "memory.h"
#include <vector>
#include <iostream>
#include "utils.h"
namespace dms {
value& memory::operator[](std::string str) {
return mem[str];
}
std::vector<value> memory::examine(datatypes dt)
{
std::vector<value> 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);
}

View File

@ -1,6 +1,7 @@
#pragma once
#include <unordered_map>
#include <string>
#include <vector>
#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<value> examine(datatypes dt);
private:
std::unordered_map<std::string, value> mem;
};

View File

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

View File

@ -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) {

View File

@ -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