Rewrote so much code

This commit is contained in:
Ryan Ward 2020-11-12 00:02:07 -05:00
parent d91ee2b662
commit 34208eacff
33 changed files with 1095 additions and 1071 deletions

View File

@ -1,22 +1,25 @@
#include "dms.h" #include "dms.h"
//#include "memory.h"
//#include <windows.h> //#include <windows.h>
//#include "utils.h"
#include <iostream> #include <iostream>
#include "value.h"
using namespace dms; using namespace dms;
using namespace utils;
//typedef void(*FNPTR)(); //typedef void(*FNPTR)();
value* invokeTest(void* self, dms_state* state, dms_args* args) { value invokeTest(void* self, dms_state* state, dms_args* args) {
utils::print(args->args[0]->getPrintable()); utils::print(args->args[0].getPrintable());
return buildValue("I work!"); return "I work!";
} }
int main() int main()
{ {
LineParser parser = LineParser("test.dms"); LineParser parser = LineParser("test.dms");
dms_state* state = parser.Parse(); dms_state* state = parser.Parse();
state->invoker.registerFunction("invokeTest", invokeTest); state->invoker.registerFunction("invokeTest", invokeTest);
state->dump(); state->dump();
state->run(); state->run();
utils::print("Exitcode: ",state->exitcode);
/*HINSTANCE hInst = LoadLibrary(L"C:\\Users\\rayam\\Desktop\\test.dll"); /*HINSTANCE hInst = LoadLibrary(L"C:\\Users\\rayam\\Desktop\\test.dll");
if (!hInst) { if (!hInst) {

View File

@ -160,7 +160,7 @@
<ClCompile Include="LineParserBuilds.cpp" /> <ClCompile Include="LineParserBuilds.cpp" />
<ClCompile Include="LineParserMatchProcess.cpp" /> <ClCompile Include="LineParserMatchProcess.cpp" />
<ClCompile Include="LineParserParse.cpp" /> <ClCompile Include="LineParserParse.cpp" />
<ClCompile Include="string_utils.cpp" /> <ClCompile Include="memory.cpp" />
<ClCompile Include="dms_exceptions.cpp" /> <ClCompile Include="dms_exceptions.cpp" />
<ClCompile Include="LineParserUtils.cpp" /> <ClCompile Include="LineParserUtils.cpp" />
<ClCompile Include="number_utils.cpp" /> <ClCompile Include="number_utils.cpp" />
@ -169,6 +169,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="character.h" /> <ClInclude Include="character.h" />
<ClInclude Include="dms_list.h" />
<ClInclude Include="enviroment.h" /> <ClInclude Include="enviroment.h" />
<ClInclude Include="Handlers.h" /> <ClInclude Include="Handlers.h" />
<ClInclude Include="chunk.h" /> <ClInclude Include="chunk.h" />
@ -176,6 +177,7 @@
<ClInclude Include="codes.h" /> <ClInclude Include="codes.h" />
<ClInclude Include="dms_state.h" /> <ClInclude Include="dms_state.h" />
<ClInclude Include="Invoker.h" /> <ClInclude Include="Invoker.h" />
<ClInclude Include="memory.h" />
<ClInclude Include="string_utils.h" /> <ClInclude Include="string_utils.h" />
<ClInclude Include="dms_exceptions.h" /> <ClInclude Include="dms_exceptions.h" />
<ClInclude Include="errors.h" /> <ClInclude Include="errors.h" />

View File

@ -48,9 +48,6 @@
<ClCompile Include="DMS.cpp"> <ClCompile Include="DMS.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="string_utils.cpp">
<Filter>Source Files\DMS</Filter>
</ClCompile>
<ClCompile Include="dms_state.cpp"> <ClCompile Include="dms_state.cpp">
<Filter>Source Files\DMS</Filter> <Filter>Source Files\DMS</Filter>
</ClCompile> </ClCompile>
@ -87,6 +84,9 @@
<ClCompile Include="Invoker.cpp"> <ClCompile Include="Invoker.cpp">
<Filter>Source Files\DMS</Filter> <Filter>Source Files\DMS</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="memory.cpp">
<Filter>Source Files\DMS</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="value.h"> <ClInclude Include="value.h">
@ -140,5 +140,11 @@
<ClInclude Include="Invoker.h"> <ClInclude Include="Invoker.h">
<Filter>Header Files\DMS</Filter> <Filter>Header Files\DMS</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="memory.h">
<Filter>Header Files\DMS</Filter>
</ClInclude>
<ClInclude Include="dms_list.h">
<Filter>Source Files\DMS</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -7,8 +7,8 @@ namespace dms {
std::cout << prompt << " "; std::cout << prompt << " ";
std::cin >> pos; std::cin >> pos;
try { try {
if (std::stoi(pos) > 0 && std::stoi(pos) < args.size()) if (std::stoi(pos)-1 >= 0 && std::stoi(pos)-1 < args.size())
return std::stoi(pos) - 1; return std::stoi(pos)-1;
else else
throw exceptions::InvalidChoice(); throw exceptions::InvalidChoice();
} }

View File

@ -2,34 +2,34 @@
#include "dms_state.h" #include "dms_state.h"
#include "utils.h" #include "utils.h"
namespace dms { 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)) { if (preventOverwriting && funcs.count(str)) {
return false; return false;
} }
funcs.insert_or_assign(str, f); funcs.insert_or_assign(str, f);
return true; 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)) { if (preventoverride && funcs.count(str)) {
return false; return false;
} }
funcs.insert_or_assign(str, f); funcs.insert_or_assign(str, f);
return true; 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)) { if (funcs.count(str)) {
for (int i = 0; i < args->args.size() - 1; i++) { if(args->size())
args->args[i] = args->args[i]->resolve(state); for (int i = 0; i < args->args.size() - 1; i++)
} args->args[i] = args->args[i].resolve(state);
return funcs[str](self, state, args); return funcs[str](self, state, args);
} }
state->push_error(errors::error{ errors::non_existing_function, utils::concat("Attempt to call '",str,"' a nil value!") }); state->push_error(errors::error{ errors::non_existing_function, utils::concat("Attempt to call '",str,"' a nil value!") });
return nullptr; return nullptr;
} }
std::unordered_map<std::string, value* (*)(void*, dms_state*, dms_args*)> Invoker::Export() { std::unordered_map<std::string, value (*)(void*, dms_state*, dms_args*)> Invoker::Export() {
return funcs; return funcs;
} }
void Invoker::Import(std::unordered_map<std::string, value* (*)(void*, dms_state*, dms_args*)> tempf) { void Invoker::Import(std::unordered_map<std::string, value (*)(void*, dms_state*, dms_args*)> tempf) {
for (auto const& x : tempf) for (auto const& x : tempf)
{ {
// Copy the contents of the imported invoker into // Copy the contents of the imported invoker into

View File

@ -4,17 +4,17 @@
namespace dms { namespace dms {
struct dms_state; struct dms_state;
class Invoker { class Invoker {
std::unordered_map<std::string, value* (*)(void*, dms_state*, dms_args*)>funcs; std::unordered_map<std::string, value (*)(void*, dms_state*, dms_args*)>funcs;
void* self = nullptr; void* self = nullptr;
public: public:
bool preventOverwriting = true; 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 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 preventoverride);
void _init(void* ref); 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 // Exports the methods from an Invoker object
std::unordered_map<std::string, value* (*)(void*, dms_state*, dms_args*)> Export(); std::unordered_map<std::string, value (*)(void*, dms_state*, dms_args*)> Export();
// Imports methods from another Invoker, this will add and overwrite any method with the same name // Imports methods from another Invoker, this will add and overwrite any method with the same name
void Import(std::unordered_map<std::string, value* (*)(void*, dms_state*, dms_args*)> tempf); void Import(std::unordered_map<std::string, value (*)(void*, dms_state*, dms_args*)> tempf);
}; };
} }

View File

@ -64,17 +64,17 @@ namespace dms {
bool match_process_debug(tokenstream* stream); bool match_process_debug(tokenstream* stream);
bool match_process_disp(tokenstream* stream); bool match_process_disp(tokenstream* stream);
bool match_process_choice(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_goto(tokenstream* stream);
bool match_process_jump(tokenstream* stream); bool match_process_jump(tokenstream* stream);
bool match_process_exit(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_IFFF(tokenstream* stream);
bool match_process_assignment(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_wait(tokenstream* stream);
bool match_process_standard(tokenstream* stream, value* v = nullptr); // All types that are matchable are handled here! bool match_process_standard(tokenstream* stream, value& v); // All types that are matchable are handled here!
bool match_process_index(tokenstream* stream,value* v = nullptr, bool leftside = false); bool match_process_index(tokenstream* stream,value& v, bool leftside = false);
bool match_process_return(tokenstream* stream); bool match_process_return(tokenstream* stream);
// Build // Build

View File

@ -4,10 +4,10 @@ namespace dms {
cmd* c = new cmd; cmd* c = new cmd;
c->opcode = codes::GOTO; c->opcode = codes::GOTO;
if (v) { if (v) {
c->args.push(buildVariable(g)); c->args.push(value(g,datatypes::variable));
} }
else { else {
c->args.push(buildValue(g)); c->args.push(value(g));
} }
current_chunk->addCmd(c); current_chunk->addCmd(c);
} }
@ -19,8 +19,20 @@ namespace dms {
void LineParser::buildLabel(std::string l) { void LineParser::buildLabel(std::string l) {
cmd* c = new cmd; cmd* c = new cmd;
c->opcode = codes::LABL; c->opcode = codes::LABL;
c->args.push(buildValue(l)); c->args.push(value(l));
current_chunk->addCmd(c); current_chunk->addCmd(c);
current_chunk->addLabel(l); 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);
}
} }

View File

@ -3,7 +3,7 @@ using namespace dms::tokens;
using namespace dms::utils; using namespace dms::utils;
// TODO: process if elseif else statements, for loops and while loops // TODO: process if elseif else statements, for loops and while loops
namespace dms { 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)) { if (match_process_expression(stream, v)) {
return true; return true;
} }
@ -17,38 +17,38 @@ namespace dms {
return true; return true;
} }
else if (stream->match(tokens::True)) { else if (stream->match(tokens::True)) {
v->set(buildBool(true)); v.set(buildBool(true));
stream->next(); stream->next();
return true; return true;
} }
else if (stream->match(tokens::False)) { else if (stream->match(tokens::False)) {
v->set(buildBool(false)); v.set(buildBool(false));
stream->next(); stream->next();
return true; return true;
} }
else if (stream->match(tokens::number)) { else if (stream->match(tokens::number)) {
v->set(buildNumber(std::stod(stream->next().name))); v.set(std::stod(stream->next().name));
return true; return true;
} }
else if (stream->match(tokens::string)) { else if (stream->match(tokens::string)) {
v->set(buildString(stream->next().name)); v.set(buildString(stream->next().name));
return true; return true;
} }
else if (stream->match(tokens::name)) { else if (stream->match(tokens::name)) {
v->set(buildString(stream->next().name)); v.set(buildString(stream->next().name));
v->type = datatypes::variable; v.type = datatypes::variable;
return true; return true;
} }
else if (stream->match(tokens::nil)) { else if (stream->match(tokens::nil)) {
stream->next(); stream->next();
v->set(); v.set();
return true; return true;
} }
else if (stream->match(tokens::bracketo, tokens::name, tokens::bracketc)) { else if (stream->match(tokens::bracketo, tokens::name, tokens::bracketc)) {
// We are assigning a block as a variable // We are assigning a block as a variable
stream->next(); stream->next();
v->set(buildString(stream->next().name)); v.set(buildString(stream->next().name));
v->type = datatypes::block; v.type = datatypes::block;
stream->next(); stream->next();
return true; return true;
} }
@ -57,16 +57,16 @@ namespace dms {
} }
return false; 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)) { if (stream->match(tokens::cbracketo)) {
token start = stream->peek(); token start = stream->peek();
token ancor = start; token ancor = start;
std::vector<token> t = stream->next(tokens::cbracketo, tokens::cbracketc); std::vector<token> t = stream->next(tokens::cbracketo, tokens::cbracketc);
tokenstream tempstream; tokenstream tempstream;
tempstream.init(&t); tempstream.init(&t);
value* ref = buildVariable(); value ref = value(datatypes::variable);
value* length = new value; value length = value();
value* dict = nullptr; value dict = value();
size_t count = 0; size_t count = 0;
cmd* c = new cmd; cmd* c = new cmd;
c->opcode = codes::LIST; c->opcode = codes::LIST;
@ -91,7 +91,7 @@ namespace dms {
} }
// Match Dict // Match Dict
else if (tempstream.match(tokens::name,tokens::colon)) { else if (tempstream.match(tokens::name,tokens::colon)) {
dict = buildVariable(tempstream.next().name); dict = value(tempstream.next().name,datatypes::variable);
tempstream.next(); tempstream.next();
if (!match_process_standard(&tempstream,ref)) { if (!match_process_standard(&tempstream,ref)) {
badSymbol(); badSymbol();
@ -123,7 +123,7 @@ namespace dms {
} }
current_chunk->addCmd(c); current_chunk->addCmd(c);
// Build new value // Build new value
ref = buildVariable(); ref = value(datatypes::variable);
tempstream.next(); tempstream.next();
} }
else if (tempstream.match(tokens::cbracketo)) { else if (tempstream.match(tokens::cbracketo)) {
@ -133,11 +133,11 @@ namespace dms {
badSymbol(&tempstream); 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 = new cmd;
c->opcode = codes::INST; c->opcode = codes::INST;
c->args.push(v); c->args.push(v);
c->args.push(buildNil()); c->args.push(value());
if (dict != nullptr) { if (dict != nullptr) {
c->args.push(dict); c->args.push(dict);
dict = nullptr; dict = nullptr;
@ -150,10 +150,9 @@ namespace dms {
bool LineParser::match_process_disp(tokenstream* stream) { bool LineParser::match_process_disp(tokenstream* stream) {
if ((isBlock(bt_block) || isBlock(bt_method)) && stream->match(tokens::newline, tokens::string, tokens::newline)) { if ((isBlock(bt_block) || isBlock(bt_method)) && stream->match(tokens::newline, tokens::string, tokens::newline)) {
stream->next(); // Standard consumption stream->next(); // Standard consumption
std::string msg = stream->next().name;
cmd* c = new cmd; cmd* c = new cmd;
c->opcode = codes::DISP; 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(c); // Add the cmd to the current chunk
current_chunk->addCmd(new cmd{ codes::HALT }); current_chunk->addCmd(new cmd{ codes::HALT });
return true; return true;
@ -167,7 +166,7 @@ namespace dms {
std::string msg = stream->next().name; std::string msg = stream->next().name;
cmd* c = new cmd; cmd* c = new cmd;
c->opcode = codes::APND; 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(c); // Add the cmd to the current chunk
current_chunk->addCmd(new cmd{ codes::HALT }); current_chunk->addCmd(new cmd{ codes::HALT });
return true; return true;
@ -179,8 +178,8 @@ namespace dms {
std::string msg = stream->next().name; std::string msg = stream->next().name;
cmd* c = new cmd; cmd* c = new cmd;
c->opcode = codes::STAT; c->opcode = codes::STAT;
c->args.push(buildVariable(name)); c->args.push(value(name,datatypes::variable));
c->args.push(buildValue(msg)); c->args.push(value(msg));
current_chunk->addCmd(c); // Add the cmd to the current chunk 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)) { 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; std::string msg = stream->next().name;
cmd* c = new cmd; cmd* c = new cmd;
c->opcode = codes::SSPK; c->opcode = codes::SSPK;
c->args.push(buildVariable(name)); c->args.push(value(name, datatypes::variable));
current_chunk->addCmd(c); current_chunk->addCmd(c);
c = new cmd; c = new cmd;
c->opcode = codes::DISP; 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(c); // Add the cmd to the current chunk
current_chunk->addCmd(new cmd{ codes::HALT }); current_chunk->addCmd(new cmd{ codes::HALT });
return true; return true;
@ -206,7 +205,7 @@ namespace dms {
// Command to set the speaker // Command to set the speaker
cmd* c = new cmd; cmd* c = new cmd;
c->opcode = codes::SSPK; c->opcode = codes::SSPK;
c->args.push(buildVariable(name)); c->args.push(value(name,datatypes::variable));
current_chunk->addCmd(c); current_chunk->addCmd(c);
stream->next(); stream->next();
stream->next(); stream->next();
@ -239,12 +238,12 @@ namespace dms {
} }
cmd* c = new cmd; cmd* c = new cmd;
c->opcode = codes::DACT; c->opcode = codes::DACT;
c->args.push(buildValue(mode)); c->args.push(value(mode));
current_chunk->addCmd(c); current_chunk->addCmd(c);
// Now build the apnd msg cmd // Now build the apnd msg cmd
c = new cmd; c = new cmd;
c->opcode = codes::APND; c->opcode = codes::APND;
c->args.push(buildValue(stream->next().name)); c->args.push(value(stream->next().name));
current_chunk->addCmd(c); current_chunk->addCmd(c);
} }
else { else {
@ -256,7 +255,7 @@ namespace dms {
else if (stream->match(tokens::string)) { else if (stream->match(tokens::string)) {
cmd* c = new cmd; cmd* c = new cmd;
c->opcode = codes::APND; c->opcode = codes::APND;
c->args.push(buildValue(stream->next().name)); c->args.push(value(stream->next().name));
current_chunk->addCmd(c); current_chunk->addCmd(c);
} }
else if (stream->match(tokens::newline)) { else if (stream->match(tokens::newline)) {
@ -279,7 +278,7 @@ namespace dms {
if (stream->match(tokens::ret)) { if (stream->match(tokens::ret)) {
cmd* c = new cmd; cmd* c = new cmd;
c->opcode = codes::RETN; c->opcode = codes::RETN;
value* ref = buildVariable(); value ref = value(datatypes::variable);
stream->next(); stream->next();
if (match_process_standard(stream, ref)) { if (match_process_standard(stream, ref)) {
c->args.push(ref); c->args.push(ref);
@ -299,11 +298,10 @@ namespace dms {
return false; return false;
} }
bool LineParser::match_process_assignment(tokenstream* stream) { bool LineParser::match_process_assignment(tokenstream* stream) {
value* v = buildVariable(); value v = value();
v->set();
if (match_process_index(stream, v, true)) { if (match_process_index(stream, v, true)) {
cmd* c = current_chunk->cmds.back(); cmd* c = current_chunk->cmds.back();
value* ref = buildVariable(); value ref = value(datatypes::variable);
if (stream->peek().type == tokens::equal) { if (stream->peek().type == tokens::equal) {
stream->next(); stream->next();
} }
@ -320,26 +318,21 @@ namespace dms {
} }
} }
else if (stream->match(tokens::name,tokens::equal)) { 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 stream->next(); // Consume the equal
cmd* c = new cmd; cmd* c = new cmd;
c->opcode = codes::ASGN; c->opcode = codes::ASGN;
c->args.push(var); c->args.push(var);
value* ref = buildVariable(); value ref = value(datatypes::variable);
if (match_process_standard(stream,ref)) { if (match_process_standard(stream,ref)) {
c->args.push(ref); c->args.push(ref);
current_chunk->addCmd(c); current_chunk->addCmd(c);
delete[] v;
return true; return true;
} }
else if (stream->match(tokens::newline)) { else if (stream->match(tokens::newline)) {
stream->next(); stream->next();
} }
} }
else {
// We should clean up this
delete[] v;
}
return false; return false;
} }
bool LineParser::match_process_debug(tokenstream* stream) { bool LineParser::match_process_debug(tokenstream* stream) {
@ -350,10 +343,10 @@ namespace dms {
cmd* c = new cmd; cmd* c = new cmd;
c->opcode = codes::DEBG; c->opcode = codes::DEBG;
if (stream->match(tokens::string)) { if (stream->match(tokens::string)) {
c->args.push(buildValue(stream->next().name)); c->args.push(value(stream->next().name));
} }
else { else {
c->args.push(buildVariable(stream->next().name)); c->args.push(value(stream->next().name,datatypes::variable));
} }
current_chunk->addCmd(c); current_chunk->addCmd(c);
return true; return true;
@ -379,8 +372,8 @@ namespace dms {
std::string choi_str = concat("CHOI_", fn); std::string choi_str = concat("CHOI_", fn);
std::string choicelabel = concat("$CHOI_END_", choi_str,"_", stream->peek().line_num); std::string choicelabel = concat("$CHOI_END_", choi_str,"_", stream->peek().line_num);
c->opcode = codes::CHOI; c->opcode = codes::CHOI;
c->args.push(buildValue(prompt)); c->args.push(prompt);
c->args.push(buildValue(fn)); 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 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 start = false;
bool hasfunc = false; bool hasfunc = false;
@ -416,10 +409,10 @@ namespace dms {
} }
else if (stream->match(tokens::string)) { else if (stream->match(tokens::string)) {
std::string name = stream->next().name; 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! value val = value();
if (match_process_function(stream,nullptr,false)) { // No returns and also no nesting of functions! 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 // We cannot have a nested function here, but if we dont have that then we add our goto
hasfunc = true; hasfunc = true;
buildGoto(choicelabel); buildGoto(choicelabel);
@ -436,6 +429,7 @@ namespace dms {
badSymbol(stream); badSymbol(stream);
} }
} }
buildGoto(choicelabel);
cmd* cc = current_chunk->cmds.back(); // Delete last element cmd* cc = current_chunk->cmds.back(); // Delete last element
current_chunk->cmds.pop_back(); current_chunk->cmds.pop_back();
delete cc; delete cc;
@ -448,9 +442,9 @@ namespace dms {
void cleanup(value* v) { void cleanup(value* v) {
v->nuke(); // Make sure we clean up the data 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, 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! 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; cmd* c = new cmd;
c->opcode = codes::FUNC; c->opcode = codes::FUNC;
std::string n = stream->next().name; 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 // Let's set the target
if (v != nullptr) { if (!v.isNil()) {
c->args.push(v); // Push the supplied variable c->args.push(v); // Push the supplied variable
} }
else { else {
c->args.push(buildValue()); // Creates a nil value c->args.push(value()); // Creates a nil value
} }
// Already we have built: FUNC name val // Already we have built: FUNC name val
// Next we add arguments this is where things get interesting // 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(token{ tokens::nil,codes::NOOP,"",t[0].line_num });
t.push_back(end); t.push_back(end);
tempstream.init(&t); // Turn tokens we consumed into a tokenstream tempstream.init(&t); // Turn tokens we consumed into a tokenstream
value* tempval; value tempval;
token tok; 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 // 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 while (tempstream.peek().type != tokens::none) { // End of stream
debugInvoker(stream); debugInvoker(stream);
tempval = buildVariable(); tempval = value(datatypes::variable);
tok = tempstream.peek(); tok = tempstream.peek();
if (tempstream.match(tokens::seperator)) { if (tempstream.match(tokens::seperator)) {
// We have a seperator for function arguments // We have a seperator for function arguments
tempstream.next(); // Consume it tempstream.next(); // Consume it
cleanup(tempval); // We don't need it
} }
else if (match_process_standard(&tempstream, tempval)) { else if (match_process_standard(&tempstream, tempval)) {
c->args.push(tempval); c->args.push(tempval);
@ -539,14 +532,11 @@ namespace dms {
tempstream.next(); tempstream.next();
} }
else if (tempstream.match(tokens::parac)) { else if (tempstream.match(tokens::parac)) {
cleanup(tempval);
tempstream.next(); tempstream.next();
current_chunk->addCmd(c); // We push this onto the chunk after all dependants if any have been handled current_chunk->addCmd(c); // We push this onto the chunk after all dependants if any have been handled
//lastCall.pop();
return true; return true;
} }
else { else {
cleanup(tempval); // Cleanup
badSymbol(&tempstream); badSymbol(&tempstream);
} }
} }
@ -555,15 +545,15 @@ namespace dms {
cmd* c = new cmd; cmd* c = new cmd;
c->opcode = codes::OFUN; c->opcode = codes::OFUN;
// OFUN obj fname target args // 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 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 // Let's set the target
if (v != nullptr) { if (!v.isNil()) {
c->args.push(v); // Push the supplied variable c->args.push(v); // Push the supplied variable
} }
else { else {
c->args.push(buildValue()); // Creates a nil value c->args.push(value()); // Creates a nil value
} }
// Already we have built: FUNC name val // Already we have built: FUNC name val
// Next we add arguments this is where things get interesting // 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(token{ tokens::nil,codes::NOOP,"",t[0].line_num });
t.push_back(end); t.push_back(end);
tempstream.init(&t); // Turn tokens we consumed into a tokenstream tempstream.init(&t); // Turn tokens we consumed into a tokenstream
value* tempval; value tempval;
token tok; 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 // 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 while (tempstream.peek().type != tokens::none) { // End of stream
debugInvoker(stream); debugInvoker(stream);
tempval = buildVariable(); tempval = value(datatypes::variable);
tok = tempstream.peek(); tok = tempstream.peek();
if (tempstream.match(tokens::seperator)) { if (tempstream.match(tokens::seperator)) {
// We have a seperator for function arguments // We have a seperator for function arguments
tempstream.next(); // Consume it tempstream.next(); // Consume it
cleanup(tempval); // We don't need it
} }
else if (match_process_standard(&tempstream, tempval)) { else if (match_process_standard(&tempstream, tempval)) {
c->args.push(tempval); c->args.push(tempval);
@ -600,14 +589,12 @@ namespace dms {
tempstream.next(); tempstream.next();
} }
else if (tempstream.match(tokens::parac)) { else if (tempstream.match(tokens::parac)) {
cleanup(tempval);
tempstream.next(); tempstream.next();
current_chunk->addCmd(c); // We push this onto the chunk after all dependants if any have been handled current_chunk->addCmd(c); // We push this onto the chunk after all dependants if any have been handled
//lastCall.pop(); //lastCall.pop();
return true; return true;
} }
else { else {
cleanup(tempval); // Cleanup
badSymbol(&tempstream); badSymbol(&tempstream);
} }
} }
@ -627,7 +614,7 @@ namespace dms {
} }
return false; 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)) { if (stream->match(tokens::name,tokens::bracketo)) {
std::string name = stream->next().name; std::string name = stream->next().name;
std::vector<token> tok = stream->next(tokens::bracketo, tokens::bracketc); std::vector<token> 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 }); 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 = ... tokenstream tempstream; // As usual the tokens are balanced match to [...] where the contents of tok = ...
tempstream.init(&tok); tempstream.init(&tok);
value* tempval = buildVariable(); value tempval = value(datatypes::variable);
cmd* c = new cmd; cmd* c = new cmd;
if (leftside) { if (leftside) {
c->opcode = codes::ASID; c->opcode = codes::ASID;
@ -647,7 +634,7 @@ namespace dms {
while (tempstream.peek().type != tokens::none) { // Keep going until we hit the end while (tempstream.peek().type != tokens::none) { // Keep going until we hit the end
if (match_process_standard(&tempstream, tempval)) { if (match_process_standard(&tempstream, tempval)) {
c->args.push(v); c->args.push(v);
c->args.push(buildBlock(name)); c->args.push(value(name,datatypes::block));
c->args.push(tempval); c->args.push(tempval);
} }
else if (nlcount) { else if (nlcount) {
@ -677,10 +664,10 @@ namespace dms {
c->opcode = codes::JUMP; c->opcode = codes::JUMP;
stream->next(); // consume jump stream->next(); // consume jump
if (stream->match(tokens::name)) { if (stream->match(tokens::name)) {
c->args.push(buildVariable(stream->next().name)); c->args.push(value(stream->next().name,datatypes::variable));
} }
else { else {
c->args.push(buildValue(stream->next().name)); c->args.push(value(stream->next().name));
} }
current_chunk->addCmd(c); current_chunk->addCmd(c);
return true; return true;
@ -694,10 +681,10 @@ namespace dms {
c->opcode = codes::EXIT; c->opcode = codes::EXIT;
if (stream->match(tokens::number) || stream->match(tokens::name)) { if (stream->match(tokens::number) || stream->match(tokens::name)) {
if(stream->match(tokens::number)){ if(stream->match(tokens::number)){
c->args.push(buildValue(std::stod(stream->next().name))); c->args.push(value(std::stod(stream->next().name)));
} }
else { else {
c->args.push(buildVariable(stream->next().name)); c->args.push(value(stream->next().name,datatypes::variable));
} }
} }
current_chunk->addCmd(c); current_chunk->addCmd(c);
@ -722,13 +709,13 @@ namespace dms {
return false; return false;
} }
void reset(value*& l, codes::op& op, value*& r) { void reset(value& l, codes::op& op, value& r) {
l = nullptr; l = value();
op = codes::NOOP; 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! // 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); stream->store(current_chunk);
cmd* lastcmd = nullptr; 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) { 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 // 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; cmd* c = new cmd;
value* wv = nullptr; value wv;
value* left; // lefthand value left; // lefthand
codes::op op; // opperator codes::op op; // opperator
value* right; // righthand value right; // righthand
reset(left, op, right); reset(left, op, right);
size_t loops = 0; size_t loops = 0;
bool hasOP = false; bool hasOP = false;
@ -748,11 +735,11 @@ namespace dms {
if (stream->match(tokens::parao)) { if (stream->match(tokens::parao)) {
tokenstream temp; tokenstream temp;
temp.init(&(stream->next(tokens::parao, tokens::parac))); // Balanced match! 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 (match_process_expression(&temp, tmpvalue)) {
if (left == nullptr) if (left.isNil())
left = tmpvalue; left = tmpvalue;
else if (right == nullptr) else if (right.isNil())
right = tmpvalue; right = tmpvalue;
else else
badSymbol(stream); badSymbol(stream);
@ -772,8 +759,8 @@ namespace dms {
} }
else if (stream->match(tokens::minus)) { else if (stream->match(tokens::minus)) {
hasOP = true; hasOP = true;
if (left == nullptr) { if (left.isNil()) {
left = buildValue(0); // -5 is the same as 0-5 right? Also -(5+5) is the same as 0-(5+5) So we good 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) if (op == codes::NOOP)
op = codes::SUB; op = codes::SUB;
@ -815,11 +802,11 @@ namespace dms {
} }
else if (stream->match(tokens::name,tokens::parao)) { 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! //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 (match_process_function(stream,tmpvalue)) {
if (left == nullptr) if (left.isNil())
left = tmpvalue; left = tmpvalue;
else if (right == nullptr) else if (right.isNil())
right = tmpvalue; right = tmpvalue;
else else
badSymbol(stream); badSymbol(stream);
@ -830,24 +817,24 @@ namespace dms {
} }
else if (stream->match(tokens::number)) { else if (stream->match(tokens::number)) {
double num = std::stod(stream->next().name); double num = std::stod(stream->next().name);
if (left == nullptr) if (left.isNil())
left = buildValue(num); left = value(num);
else if (right == nullptr) else if (right.isNil())
right = buildValue(num); right = value(num);
else else
badSymbol(stream); badSymbol(stream);
} }
else if (stream->match(tokens::name)) { 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! // We tested functions already! So if that fails and we have a name then... we have a variable lets handle this!
if (left == nullptr) if (left.isNil())
left = buildVariable(stream->next().name); left = value(stream->next().name,datatypes::variable);
else if (right == nullptr) else if (right.isNil())
right = buildVariable(stream->next().name); right = value(stream->next().name,datatypes::variable);
else else
badSymbol(stream); badSymbol(stream);
} }
else if (stream->match(tokens::newline) || stream->match(tokens::parac) || stream->match(tokens::seperator)) { 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! return stream->restore(lastcmd, current_chunk); // Always return false and restores the position in stream!
cmd* cc = new cmd; cmd* cc = new cmd;
cc->opcode = codes::ASGN; cc->opcode = codes::ASGN;
@ -866,16 +853,16 @@ namespace dms {
else { else {
return stream->restore(lastcmd, current_chunk); 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; cmd* c = new cmd;
c->opcode = op; c->opcode = op;
if (wv == nullptr) { if (wv.isNil()) {
value* temp = buildVariable(); value temp = value(datatypes::variable);
c->args.push(temp); c->args.push(temp);
wv = temp; wv = temp;
} }
else { else {
wv = buildVariable(); wv = value(datatypes::variable);
c->args.push(wv); c->args.push(wv);
} }
c->args.push(left); c->args.push(left);

View File

@ -353,11 +353,13 @@ namespace dms {
if (state->isEnabled("debugging")) { if (state->isEnabled("debugging")) {
cmd* c = new cmd; cmd* c = new cmd;
c->opcode = codes::FILE; c->opcode = codes::FILE;
c->args.push(buildValue(fn)); c->args.push(value(fn));
current_chunk->addCmd(c); current_chunk->addCmd(c);
} }
while (stream->peek().type != tokens::eof) { while (stream->peek().type != tokens::eof) {
debugInvoker(stream); debugInvoker(stream);
//utils::print(current);
//utils::print("[flags]");
if (current.type == tokens::flag) { if (current.type == tokens::flag) {
temp = stream->next(tokens::newline); temp = stream->next(tokens::newline);
stream->prev(); // Unconsume the newline piece stream->prev(); // Unconsume the newline piece
@ -370,14 +372,14 @@ namespace dms {
tolower(temp[0].name); tolower(temp[0].name);
state->enable(temp[0].name); state->enable(temp[0].name);
flagcmd->opcode = code; flagcmd->opcode = code;
flagcmd->args.push(buildValue(temp[0].name)); flagcmd->args.push(value(temp[0].name));
current_chunk->addCmd(flagcmd); current_chunk->addCmd(flagcmd);
flagcmd = new cmd; flagcmd = new cmd;
} }
else if (code == codes::ENTR && tok == tokens::name) { else if (code == codes::ENTR && tok == tokens::name) {
state->entry = temp[0].name; state->entry = temp[0].name;
flagcmd->opcode = code; flagcmd->opcode = code;
flagcmd->args.push(buildValue(temp[0].name)); flagcmd->args.push(value(temp[0].name));
current_chunk->addCmd(flagcmd); current_chunk->addCmd(flagcmd);
flagcmd = new cmd; flagcmd = new cmd;
} }
@ -385,14 +387,14 @@ namespace dms {
tolower(temp[0].name); tolower(temp[0].name);
state->disable(temp[0].name); state->disable(temp[0].name);
flagcmd->opcode = code; flagcmd->opcode = code;
flagcmd->args.push(buildValue(temp[0].name)); flagcmd->args.push(value(temp[0].name));
current_chunk->addCmd(flagcmd); current_chunk->addCmd(flagcmd);
flagcmd = new cmd; flagcmd = new cmd;
} }
else if (code == codes::VERN && tok == tokens::number) { else if (code == codes::VERN && tok == tokens::number) {
state->version = std::stod(temp[0].name); state->version = std::stod(temp[0].name);
flagcmd->opcode = code; 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); current_chunk->addCmd(flagcmd);
flagcmd = new cmd; 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 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) { if (tokens[i].type == tokens::name) {
// We got a name which is refering to a variable so lets build one // We got a name which is refering to a variable so lets build one
value* v = new value{}; value v;
v->type = datatypes::variable; // Special type, it writes data to the string portion, but is interperted as a lookup 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); v.s = buildString(tokens[i].name);
args.push(v); args.push(v);
} }
else if (tokens[i].type == tokens::seperator) { else if (tokens[i].type == tokens::seperator) {
@ -490,19 +492,29 @@ namespace dms {
} }
} }
// Let's handle function stuff! // Let's handle function stuff!
//utils::print("[return]");
match_process_return(stream); match_process_return(stream);
//utils::print("[disp]");
match_process_disp(stream); // Match and process dialogue match_process_disp(stream); // Match and process dialogue
//utils::print("[label]");
if (stream->match(tokens::newline,tokens::label)) { // Match and process labels if (stream->match(tokens::newline,tokens::label)) { // Match and process labels
stream->next(); stream->next();
buildLabel(stream->next().name); 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); match_process_assignment(stream);
//utils::print("[debug]");
match_process_debug(stream); match_process_debug(stream);
//utils::print("[goto]");
match_process_goto(stream); match_process_goto(stream);
//utils::print("[exit]");
match_process_exit(stream); match_process_exit(stream);
//utils::print("[wait]");
match_process_wait(stream); match_process_wait(stream);
//utils::print("[jump]");
match_process_jump(stream); match_process_jump(stream);
current = stream->next(); current = stream->next();
} }

View File

@ -203,29 +203,17 @@ namespace dms {
void LineParser::badSymbol() { void LineParser::badSymbol() {
state->push_error(errors::error{ errors::unknown,concat("Unexpected symbol '",_stream->peek().toString(),"'"),true,_stream->next().line_num,current_chunk }); 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) { void LineParser::debugInvoker(tokenstream* stream) {
if (state->isEnabled("debugging") && stream->peek().type != tokens::newline) { 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 // 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 // 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; return;
} }
int current_line = stream->peek().line_num; int current_line = stream->peek().line_num;
cmd* ln = new cmd; cmd* ln = new cmd;
ln->opcode = codes::LINE; ln->opcode = codes::LINE;
ln->args.push(buildValue(current_line)); ln->args.push(value(current_line));
current_chunk->addCmd(ln); current_chunk->addCmd(ln);
} }
} }
@ -259,16 +247,16 @@ namespace dms {
if (state->isEnabled("leaking") && (current_chunk != nullptr && current_chunk->name != "$INIT")) { if (state->isEnabled("leaking") && (current_chunk != nullptr && current_chunk->name != "$INIT")) {
cmd* c = new cmd; cmd* c = new cmd;
c->opcode = codes::JUMP; c->opcode = codes::JUMP;
c->args.push(buildValue(bk_name)); c->args.push(value(bk_name));
current_chunk->addCmd(c); current_chunk->addCmd(c);
} }
if (current_chunk != nullptr && current_chunk->name == "$END") { if (current_chunk != nullptr && current_chunk->name == "$END") {
cmd* c = new cmd; cmd* c = new cmd;
c->opcode = codes::EXIT; c->opcode = codes::EXIT;
if (state->entry != "$undefined") if (state->entry != "$undefined")
c->args.push(buildValue(0)); c->args.push(value(0));
else else
c->args.push(buildValue(bk_name)); c->args.push(value(bk_name));
current_chunk->addCmd(c); current_chunk->addCmd(c);
} }
current_chunk = new chunk; current_chunk = new chunk;

View File

@ -1,12 +1,12 @@
#include "character.h" #include "character.h"
#include "utils.h" #include "utils.h"
namespace dms { 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)) { if(utils::typeassert(*args, datatypes::string)) {
character* me = (character*)self; character* me = (character*)self;
me->set("fname", buildValue(args->args[0]->getPrintable())); me->set("fname", args->args[0]);
} }
return buildNil(); return value();
} }
character::character() { character::character() {
// Set the self so the registered function can access themselves // Set the self so the registered function can access themselves
@ -16,16 +16,16 @@ namespace dms {
} }
std::string character::getName() { std::string character::getName() {
if (has("nickname")) { if (has("nickname")) {
return values["nickname"]->getPrintable(); return values["nickname"].getPrintable();
} }
if (seen && has("fname") && has("lname")) { 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")) { else if (seen && has("fname")) {
return utils::concat(values["fname"]->getPrintable()); return utils::concat(values["fname"].getPrintable());
} }
else if (!seen && has("unknown")) { else if (!seen && has("unknown")) {
return values["unknown"]->getPrintable(); return values["unknown"].getPrintable();
} }
else { else {
return "unknown"; return "unknown";

View File

@ -11,7 +11,7 @@ namespace dms {
friend std::ostream& operator << (std::ostream& out, const cmd& c) { friend std::ostream& operator << (std::ostream& out, const cmd& c) {
out << codes::list[c.opcode] << " "; out << codes::list[c.opcode] << " ";
for (size_t i = 0; i < c.args.args.size(); i++) { for (size_t i = 0; i < c.args.args.size(); i++) {
out << *c.args.args[i] << " "; out << c.args.args[i] << " ";
} }
return out; return out;
} }

View File

@ -14,4 +14,6 @@
#include "utils.h" #include "utils.h"
#include "value.h" #include "value.h"
#include "Invoker.h" #include "Invoker.h"
#include "memory.h"
#include "dms_list.h"

View File

@ -14,48 +14,48 @@ namespace dms {
void dms_custom::Init(dms_state* state) { void dms_custom::Init(dms_state* state) {
this->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!" }); state->push_error(errors::error{ errors::unknown,"Attempting to index a non enviroment!" });
return nullptr; 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!" }); state->push_error(errors::error{ errors::unknown,"Attempting to create a new index on a non enviroment!" });
return false; 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!"}); state->push_error(errors::error{errors::unknown,"Attempting to call a non function value!"});
return nullptr; return nullptr;
} }
value* dms_custom::ToString() { value dms_custom::ToString() {
return buildValue(utils::concat("Custom: ",this)); 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!" }); state->push_error(errors::error{ errors::unknown,"Attempting to add a non number value!" });
return nullptr; 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!" }); state->push_error(errors::error{ errors::unknown,"Attempting to subtract a non number value!" });
return nullptr; 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!" }); state->push_error(errors::error{ errors::unknown,"Attempting to multiply a non number value!" });
return nullptr; 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!" }); state->push_error(errors::error{ errors::unknown,"Attempting to divide a non number value!" });
return nullptr; 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!" }); state->push_error(errors::error{ errors::unknown,"Attempting to raise a non number value!" });
return nullptr; return nullptr;
} }
value* dms_custom::EQUAL(value* left, value* right) { value dms_custom::EQUAL(value left, value right) {
return buildValue(left->getPrintable() == right->getPrintable()); return value(left.getPrintable() == right.getPrintable());
} }
value* dms_custom::LESS_THAN(value* left, value* right) { value dms_custom::LESS_THAN(value left, value right) {
return buildValue(left->getPrintable() < right->getPrintable()); return value(left.getPrintable() < right.getPrintable());
} }
value* dms_custom::LESS_THAN_EQUAL(value* left, value* right) { value dms_custom::LESS_THAN_EQUAL(value left, value right) {
return buildValue(left->getPrintable() <= right->getPrintable()); return value(left.getPrintable() <= right.getPrintable());
} }
} }

11
DMS/dms_list.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
#include "memory.h"
namespace dms {
struct dms_list
{
memory hpart;
std::vector<value> ipart;
void pushValue(value val);
value getValue(value val);
};
}

View File

@ -8,18 +8,15 @@ namespace dms {
cmd* c = new cmd; cmd* c = new cmd;
for (const auto& [key, val] : chunks) { for (const auto& [key, val] : chunks) {
if (val->type == blocktype::bt_character || val->type == blocktype::bt_env) { 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->opcode = codes::ASGN;
c->args.push(buildVariable(key)); c->args.push(value(key, datatypes::variable));
c->args.push(v); c->args.push(value(key, datatypes::block));
chunks["$INIT"]->addCmd(c); chunks["$INIT"]->addCmd(c);
c = new cmd; c = new cmd;
} }
else if (val->type == blocktype::bt_method) { else if (val->type == blocktype::bt_method) {
c->opcode = codes::RETN; c->opcode = codes::RETN;
c->args.push(buildNil()); c->args.push(value());
val->addCmd(c); val->addCmd(c);
c = new cmd; c = new cmd;
} }
@ -27,31 +24,31 @@ namespace dms {
c->opcode = codes::JUMP; c->opcode = codes::JUMP;
if (entry != "$undefined") if (entry != "$undefined")
c->args.push(buildValue(entry)); c->args.push(value(entry));
else else
c->args.push(buildValue(chunks.begin()->first)); c->args.push(value(chunks.begin()->first));
chunks["$INIT"]->addCmd(c); chunks["$INIT"]->addCmd(c);
if (!handler->OnStateInit(this)) if (!handler->OnStateInit(this))
stop = true; stop = true;
} }
std::unordered_map<std::string, value*>* dms_state::getMem() { memory* dms_state::getMem() {
return mem_stack.top(); return &mem_stack.top();
} }
void dms_state::pushMem() { void dms_state::pushMem() {
mem_stack.push(new std::unordered_map<std::string, value*>); mem_stack.push(memory());
} }
void dms_state::popMem() { void dms_state::popMem() {
mem_stack.pop(); 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(); std::string func = state->call_stack.top();
if (state->functionExists(func)) { if (state->functionExists(func)) {
state->call_stack.pop(); state->call_stack.pop();
value* ret = nullptr; value ret;
state->pushMem(); state->pushMem();
std::unordered_map<std::string, value*>* Fmem = state->getMem(); memory* Fmem = state->getMem();
for (int i = 0; i < state->chunks[func]->params.args.size(); i++) { 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); state->run(func, Fmem);
ret = state->return_stack.top(); ret = state->return_stack.top();
@ -59,14 +56,11 @@ namespace dms {
state->popMem(); state->popMem();
return ret; return ret;
} }
return buildNil(); return value();
}
void dms_state::pushMem(std::unordered_map<std::string, value*>* m) {
mem_stack.push(m);
} }
dms_state::dms_state() { dms_state::dms_state() {
// We should define the defaults for the enables // We should define the defaults for the enables
pushMem(&memory); pushMem(); // Main memory
enables.insert_or_assign("leaking", false); enables.insert_or_assign("leaking", false);
enables.insert_or_assign("debugging", false); enables.insert_or_assign("debugging", false);
enables.insert_or_assign("warnings", false); // enables.insert_or_assign("warnings", false); //
@ -78,15 +72,15 @@ namespace dms {
c->type = blocktype::bt_block; c->type = blocktype::bt_block;
cmd* cc = new cmd; cmd* cc = new cmd;
cc->opcode = codes::EXIT; cc->opcode = codes::EXIT;
cc->args.push(buildValue(0)); cc->args.push(value(0));
c->addCmd(cc); c->addCmd(cc);
push_chunk("$END", c); push_chunk("$END", c);
setHandler(new Handler); // Use the default implementation setHandler(new Handler); // Use the default implementation
invoker.registerFunction("$BlockInvoke$", blockInvoke); invoker.registerFunction("$BlockInvoke$", blockInvoke);
} }
bool dms_state::typeAssert(value* val, datatypes type) { bool dms_state::typeAssert(value val, datatypes type) {
if (val->type != type) { if (val.type != type) {
push_error(errors::error{ errors::invalid_type ,utils::concat("Expected a ",datatype[type]," got a ",datatype[val->type],"!") }); push_error(errors::error{ errors::invalid_type ,utils::concat("Expected a ",datatype[type]," got a ",datatype[val.type],"!") });
return false; return false;
} }
return true; return true;
@ -136,23 +130,10 @@ namespace dms {
return false; return false;
} }
bool dms_state::assign(std::unordered_map<std::string, value*>* mem, value* var, value* val) { bool dms_state::assign(value var, value val) {
if (mem->count(var->s->getValue()) == 0) { (*getMem())[var.getPrintable()] = val;
mem->insert_or_assign(var->s->getValue(), val);
return true; 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;
}
}
void dms_state::dump(bool print) { void dms_state::dump(bool print) {
if (print) if (print)
std::cout << "Number of chunks: " << chunks.size() << std::endl; std::cout << "Number of chunks: " << chunks.size() << std::endl;

View File

@ -9,18 +9,20 @@
#include "dms_exceptions.h" #include "dms_exceptions.h"
#include "Character.h" #include "Character.h"
#include "enviroment.h" #include "enviroment.h"
#include "memory.h"
#include <stack> #include <stack>
#include "dms_list.h"
namespace dms { namespace dms {
struct Handler; struct Handler;
value* blockInvoke(void*, dms_state*, dms_args*); value blockInvoke(void*, dms_state*, dms_args*);
struct dms_state struct dms_state
{ {
Handler* handler = nullptr; Handler* handler = nullptr;
bool hasFirst = false; bool hasFirst = false;
Invoker invoker; Invoker invoker;
std::stack<std::string> call_stack; std::stack<std::string> call_stack;
std::stack<value*> return_stack; std::stack<value> return_stack;
std::stack<std::unordered_map<std::string, value*>*> mem_stack; std::stack<memory> mem_stack;
std::vector<value*> garbage; std::vector<value*> garbage;
std::unordered_map<std::string, chunk*> chunks; std::unordered_map<std::string, chunk*> chunks;
std::unordered_map<std::string, character*> characters; std::unordered_map<std::string, character*> characters;
@ -53,19 +55,18 @@ namespace dms {
character* getCharacter(std::string c); character* getCharacter(std::string c);
enviroment* getEnvironment(std::string c); enviroment* getEnvironment(std::string c);
bool assign(std::unordered_map<std::string, value*>* mem,value* var, value* val); bool assign(value var, value val);
size_t seek(std::string label,std::vector<cmd*> cmds ,codes::op code, size_t pos); size_t seek(std::string label,std::vector<cmd*> cmds ,codes::op code, size_t pos);
bool characterExists(std::string bk_name); bool characterExists(std::string bk_name);
bool environmentExists(std::string bk_name); bool environmentExists(std::string bk_name);
bool functionExists(std::string bk_name); bool functionExists(std::string bk_name);
bool blockExists(std::string bk_name); bool blockExists(std::string bk_name);
bool typeAssert(value* val, datatypes type); bool typeAssert(value val, datatypes type);
std::unordered_map<std::string, value*>* getMem(); memory* getMem();
void pushMem(); void pushMem();
void popMem(); void popMem();
value* func();
bool run(); bool run();
bool run(std::string ent,std::unordered_map<std::string, value*>* mem); bool run(std::string ent,memory* mem);
bool run(std::string instance); bool run(std::string instance);
// This is called once and once only. Dynamically loading code is not a thing! // This is called once and once only. Dynamically loading code is not a thing!
void init(); void init();
@ -73,8 +74,6 @@ namespace dms {
private: private:
// From what I gathered // From what I gathered
//std::mutex memory_mutex; //std::mutex memory_mutex;
std::unordered_map<std::string, value*> memory;
void pushMem(std::unordered_map<std::string, value*>*);
bool stop = false; bool stop = false;
bool init_init = false; bool init_init = false;
void init(chunk* chunk, size_t &pos,size_t &max, std::vector<cmd*>& cmds); void init(chunk* chunk, size_t &pos,size_t &max, std::vector<cmd*>& cmds);

View File

@ -12,17 +12,16 @@ namespace dms {
this->handler = hand; this->handler = hand;
} }
void checkCharacter(character* cc,std::string index, datatypes type) { void checkCharacter(character* cc,std::string index, datatypes type) {
value* val = cc->get(index); value val = cc->get(index);
if (val==nullptr) { // If a type mismatch is present, overwrite them with the defaults
if (val.type!=type) {
if (type == datatypes::string) if (type == datatypes::string)
cc->values[index] = buildValue(""); cc->values[index] = value("");
else if (type == datatypes::boolean) { else if (type == datatypes::boolean) {
cc->values[index] = buildValue(false); cc->values[index] = value(false);
} }
} else if (type == datatypes::number) {
else if (val != nullptr) { cc->values[index] = value(0);
if (val->type != type) {
cc->values.erase(index);
} }
} }
} }
@ -56,10 +55,10 @@ namespace dms {
if (blockExists(cha)) { if (blockExists(cha)) {
character* cc = new character; character* cc = new character;
cc->fullname = isEnabled("fullname"); cc->fullname = isEnabled("fullname");
cc->set("fname", buildValue(cha)); cc->set("fname", cha);
cc->set("lname", buildValue("")); cc->set("lname", "");
cc->set("unknown", buildValue("Unknown")); cc->set("unknown", "Unknown");
cc->set("known", buildValue(false)); cc->set("known", false);
if (isEnabled("omniscient")) { if (isEnabled("omniscient")) {
cc->seen = true; cc->seen = true;
} }
@ -71,7 +70,7 @@ namespace dms {
checkCharacter(cc, "lname", datatypes::string); checkCharacter(cc, "lname", datatypes::string);
checkCharacter(cc, "unknown", datatypes::string); checkCharacter(cc, "unknown", datatypes::string);
checkCharacter(cc, "known", datatypes::boolean); checkCharacter(cc, "known", datatypes::boolean);
if (cc->get("known")->b->getValue() == true) { if (cc->get("known").b == true) {
cc->seen = true; cc->seen = true;
} }
} }
@ -92,7 +91,7 @@ namespace dms {
} }
size_t dms_state::seek(std::string label, std::vector<cmd*> cmds, codes::op code, size_t pos) { size_t dms_state::seek(std::string label, std::vector<cmd*> cmds, codes::op code, size_t pos) {
for (size_t i = pos; i < cmds.size(); i++) { 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 i;
} }
return 0; 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,"]") }); push_error(errors::error{ errors::non_existing_block ,utils::concat("Attempted to Jump to a non existing block [",entry,"]") });
return false; return false;
} }
return run("$INIT",&memory); return run("$INIT",getMem());
} }
bool dms_state::run(std::string ent, std::unordered_map<std::string, value*>* mem) { bool dms_state::run(std::string ent, memory* mem) {
if (stop) { if (stop) {
exitcode = 1; exitcode = 1;
return false; return false;
@ -143,19 +142,19 @@ namespace dms {
// Handle flags here // Handle flags here
case ENTR: case ENTR:
// When reading code from a file the flags are compiled and we need to load them // 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; break;
case ENAB: case ENAB:
enable(c->args.args[0]->s->getValue()); enable(c->args.args[0].getPrintable());
break; break;
case DISA: case DISA:
disable(c->args.args[0]->s->getValue()); disable(c->args.args[0].getPrintable());
break; break;
case LOAD: case LOAD:
// Nothing needs to be done here // Nothing needs to be done here
break; break;
case VERN: case VERN:
Sversion = c->args.args[0]->n->getValue(); Sversion = c->args.args[0].n;
// Version X.xx // Version X.xx
// X: Will not guarantee compatibality. Code breaking changes should be expected especially on lower versions // 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 // 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 // Flags handled
case EXIT: case EXIT:
if (c->args.args.size()) { if (c->args.args.size()) {
exitcode = c->args.args[0]->n->getValue(); exitcode = c->args.args[0].n;
} }
return true; return true;
break; 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: 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 //c->args.args[0]->nuke(); // Lets clean this up
return_stack.push(ret); return_stack.push(ret);
return true; // We did it, let's return this return true; // We did it, let's return this
@ -187,35 +199,32 @@ namespace dms {
break; break;
case OFUN: case OFUN:
{ {
std::string obj = c->args.args[0]->getPrintable(); std::string obj = c->args.args[0].getPrintable();
std::string funcname = c->args.args[1]->getPrintable(); std::string funcname = c->args.args[1].getPrintable();
value* assn = c->args.args[2]; value assn = c->args.args[2];
dms_args args; dms_args args;
for (int i = 3; i < c->args.args.size(); i++) { for (int i = 3; i < c->args.args.size(); i++) {
args.push(c->args.args[i]); args.push(c->args.args[i]);
} }
value* ret = nullptr; value ret;
if (characterExists(obj)) { if (characterExists(obj)) {
ret = getCharacter(obj)->Invoke(funcname, this, &args); ret = getCharacter(obj)->Invoke(funcname, this, &args);
} }
else if (environmentExists(obj)) { else if (environmentExists(obj)) {
ret = getEnvironment(obj)->Invoke(funcname, this, &args); ret = getEnvironment(obj)->Invoke(funcname, this, &args);
} }
//value* ret = invoker.Invoke(funcname, nullptr, this, &args); if (assn.type != datatypes::nil) {
if (ret == nullptr) assign(assn, ret);
return false;
if (assn->type != datatypes::nil) {
assign(mem, assn, ret);
} }
} }
break; break;
case FUNC: case FUNC:
{ {
std::string funcname = c->args.args[0]->getPrintable(); std::string funcname = c->args.args[0].getPrintable();
value* assn = c->args.args[1]; value assn = c->args.args[1];
dms_args args; dms_args args;
value* ret = nullptr; value ret;
for (int i = 2; i < c->args.args.size(); i++) { for (int i = 2; i < c->args.args.size(); i++) {
args.push(c->args.args[i]); args.push(c->args.args[i]);
} }
@ -225,126 +234,124 @@ namespace dms {
ret = invoker.Invoke("$BlockInvoke$", this, &args); ret = invoker.Invoke("$BlockInvoke$", this, &args);
} }
else { else {
value* ret = invoker.Invoke(funcname, this, &args); ret = invoker.Invoke(funcname, this, &args);
} }
if (ret == nullptr) if (assn.type != datatypes::nil) {
return false; assign(assn, ret);
if (assn->type != datatypes::nil) {
assign(getMem(), assn, ret);
} }
} }
break; break;
case ASID: case ASID:
{ {
value* env = c->args.args[1]; value env = c->args.args[1];
value* indx = c->args.args[2]->resolve(this); value indx = c->args.args[2].resolve(this);
value* assn = c->args.args[3]->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 if (env.type == datatypes::block && blockExists(env.getPrintable())) { // If this is a block let's handle this
enviroment* e = nullptr; enviroment* e = nullptr;
if (environments.count(env->getPrintable())) { if (environments.count(env.getPrintable())) {
e = environments[env->getPrintable()]; e = environments[env.getPrintable()];
} }
else if (characters.count(env->getPrintable())) { else if (characters.count(env.getPrintable())) {
e = characters[env->getPrintable()]; e = characters[env.getPrintable()];
} }
e->values[indx->getPrintable()] = assn; e->values[indx.getPrintable()] = assn;
} }
else if (env->type == datatypes::env) { else if (env.type == datatypes::env) {
if (indx->type == datatypes::number) { if (indx.type == datatypes::number) {
env->e->pushValue(assn); env.e->pushValue(assn);
} }
else { 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; return false;
} }
} }
else if (env->type == datatypes::custom) { else if (env.type == datatypes::custom) {
env->c->NewIndex(indx, assn); env.c->NewIndex(indx, assn);
//assign(mem, assn, env->c->Index(indx)); //assign( assn, env->c->Index(indx));
// Call the method within the custom data // Call the method within the custom data
} }
break; break;
} }
case ADD: case ADD:
{ {
value* assn = c->args.args[0]; value assn = c->args.args[0];
value* o1 = c->args.args[1]; value o1 = c->args.args[1];
value* o2 = c->args.args[2]; value o2 = c->args.args[2];
value* ret = buildValue(o1->resolve(this)->n->getValue()+o2->resolve(this)->n->getValue()); value ret = value(o1.resolve(this).n+o2.resolve(this).n);
assign(getMem(), assn, ret); assign(assn, ret);
} }
break; break;
case SUB: case SUB:
{ {
value* assn = c->args.args[0]; value assn = c->args.args[0];
value* o1 = c->args.args[1]; value o1 = c->args.args[1];
value* o2 = c->args.args[2]; value o2 = c->args.args[2];
value* ret = buildValue(o1->resolve(this)->n->getValue() - o2->resolve(this)->n->getValue()); value ret = value(o1.resolve(this).n - o2.resolve(this).n);
assign(getMem(), assn, ret); assign(assn, ret);
} }
break; break;
case MUL: case MUL:
{ {
value* assn = c->args.args[0]; value assn = c->args.args[0];
value* o1 = c->args.args[1]; value o1 = c->args.args[1];
value* o2 = c->args.args[2]; value o2 = c->args.args[2];
value* ret = buildValue(o1->resolve(this)->n->getValue() * o2->resolve(this)->n->getValue()); value ret = value(o1.resolve(this).n * o2.resolve(this).n);
assign(getMem(), assn, ret); assign(assn, ret);
} }
break; break;
case DIV: case DIV:
{ {
value* assn = c->args.args[0]; value assn = c->args.args[0];
value* o1 = c->args.args[1]; value o1 = c->args.args[1];
value* o2 = c->args.args[2]; value o2 = c->args.args[2];
value* ret = buildValue(o1->resolve(this)->n->getValue() / o2->resolve(this)->n->getValue()); value ret = value(o1.resolve(this).n / o2.resolve(this).n);
assign(getMem(), assn, ret); assign(assn, ret);
} }
break; break;
case POW: case POW:
{ {
value* assn = c->args.args[0]; value assn = c->args.args[0];
value* o1 = c->args.args[1]; value o1 = c->args.args[1];
value* o2 = c->args.args[2]; value o2 = c->args.args[2];
value* ret = buildValue(pow(o1->resolve(this)->n->getValue(), o2->resolve(this)->n->getValue())); value ret = value(pow(o1.resolve(this).n, o2.resolve(this).n));
assign(getMem(), assn, ret); assign(assn, ret);
} }
break; break;
case MOD: case MOD:
{ {
value* assn = c->args.args[0]; value assn = c->args.args[0];
value* o1 = c->args.args[1]; value o1 = c->args.args[1];
value* o2 = c->args.args[2]; value o2 = c->args.args[2];
value* ret = buildValue(std::fmod(o1->resolve(this)->n->getValue(),o2->resolve(this)->n->getValue())); value ret = value(std::fmod(o1.resolve(this).n,o2.resolve(this).n));
assign(getMem(), assn, ret); assign(assn, ret);
} }
break; break;
case INDX: case INDX:
{ {
value* assn = c->args.args[0]; value assn = c->args.args[0];
value* env = c->args.args[1]; value env = c->args.args[1];
value* indx = c->args.args[2]->resolve(this); 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 if (env.type == datatypes::block && blockExists(env.getPrintable())) { // If this is a block let's handle this
enviroment* e = nullptr; enviroment* e = nullptr;
if (environments.count(env->getPrintable())) { if (environments.count(env.getPrintable())) {
e = environments[env->getPrintable()]; e = environments[env.getPrintable()];
} }
else if (characters.count(env->getPrintable())) { else if (characters.count(env.getPrintable())) {
e = characters[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) { else if (env.type == datatypes::env) {
if (indx->type == datatypes::number) { if (indx.type == datatypes::number) {
assign(mem, assn, env->e->getValue(indx)); assign( assn, env.e->getValue(indx));
} }
else { 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; return false;
} }
} }
else if (env->type == datatypes::custom) { else if (env.type == datatypes::custom) {
assign(mem, assn, env->c->Index(indx)); assign( assn, env.c->Index(indx));
// Call the method within the custom data // Call the method within the custom data
} }
} }
@ -352,17 +359,18 @@ namespace dms {
case LIST: case LIST:
//We need to create an enviroment value then set that //We need to create an enviroment value then set that
{ {
dms_env* env = new dms_env; dms_list* env = new dms_list;
env->hpart.insert_or_assign("$size", c->args.args[1]); // Inject the size of the list
value* val = new value; env->hpart["$size"] = c->args.args[1];
val->set(env); value val = new value;
assign(mem,c->args.args[0], val); val.set(env);
assign(c->args.args[0], val);
} }
break; break;
case INST: case INST:
{ {
value* list = (*mem)[c->args.args[0]->s->getValue()]; value list = (*mem)[c->args.args[0].getPrintable()];
list->e->pushValue(c->args.args[1]); list.e->pushValue(c->args.args[1]);
} }
break; break;
case HALT: case HALT:
@ -371,7 +379,7 @@ namespace dms {
std::cout << std::endl; std::cout << std::endl;
break; break;
case WAIT: case WAIT:
sleep((int)(c->args.args[0]->n->getValue()*1000)); sleep((int)(c->args.args[0].n*1000));
break; break;
case DSPD: case DSPD:
if (speaker == nullptr) { if (speaker == nullptr) {
@ -379,34 +387,34 @@ namespace dms {
return false; return false;
} }
else { else {
speaker->spd = c->args.args[0]->n->getValue(); speaker->spd = c->args.args[0].n;
} }
break; break;
case SSPK: case SSPK:
//Because we are using void* we must cast our pointers //Because we are using void* we must cast our pointers
if (characterExists(c->args.args[0]->s->getValue())){ if (characterExists(c->args.args[0].s->getValue())){
speaker = getCharacter(c->args.args[0]->s->getValue()); speaker = getCharacter(c->args.args[0].s->getValue());
if (!handler->handleSpeaker(this, speaker)) if (!handler->handleSpeaker(this, speaker))
return false; return false;
} }
else { 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; return false;
} }
break; break;
case APND: 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; return false;
break; break;
case DISP: 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; return false;
break; break;
case ASGN: case ASGN:
assign(mem,c->args.args[0], c->args.args[1]); assign(c->args.args[0], c->args.args[1]);
break; break;
case LINE: case LINE:
cur_line = c->args.args[0]->n->getValue(); cur_line = c->args.args[0].n;
break; break;
case NOOP: case NOOP:
break; break;
@ -414,12 +422,12 @@ namespace dms {
//Because we are using void* we must cast our pointers //Because we are using void* we must cast our pointers
{ {
std::vector<std::string> args; std::vector<std::string> args;
std::string prompt = c->args.args[0]->s->getValue(); std::string prompt = c->args.args[0].s->getValue();
std::string fn = c->args.args[1]->s->getValue(); std::string fn = c->args.args[1].s->getValue();
for (size_t i = 2; i < c->args.args.size(); i++) 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 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) { if (!nnpos) {
push_error(errors::error{ errors::choice_unknown ,utils::concat("Unknown choice!") }); push_error(errors::error{ errors::choice_unknown ,utils::concat("Unknown choice!") });
return false; return false;
@ -432,7 +440,7 @@ namespace dms {
case JUMP: case JUMP:
// Value assert resolves the data so a variable must eventually equal a string // Value assert resolves the data so a variable must eventually equal a string
if (utils::valueassert(c->args, this, datatypes::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) { if (chunks[block] == NULL) {
push_error(errors::error{ errors::non_existing_block ,utils::concat("Attempted to Jump to a non existing block [",block,"]") }); push_error(errors::error{ errors::non_existing_block ,utils::concat("Attempted to Jump to a non existing block [",block,"]") });
return false; return false;
@ -446,7 +454,9 @@ namespace dms {
} }
} }
else { 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 }); push_error(errors::error{ errors::invalid_arguments, utils::concat("String expected got ",datatype[set]), true,ln });
return false; return false;
} }

Binary file not shown.

View File

@ -22,9 +22,6 @@ Line <6> name fullname
Line <6> newline Line <6> newline
Line <6> newline Line <6> newline
Line <7> newline Line <7> newline
Line <8> flag
Line <8> name debugging
Line <8> newline
Line <8> newline Line <8> newline
Line <9> flag Line <9> flag
Line <9> string loadtest.dms Line <9> string loadtest.dms
@ -45,250 +42,336 @@ Line <13> name main
Line <13> bracketc ] Line <13> bracketc ]
Line <13> newline Line <13> newline
Line <13> newline Line <13> newline
Line <14> string Time to test function calls! Line <14> name Ryan
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> colon : 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 <14> newline Line <14> newline
Line <15> name excited Line <15> name Bob
Line <15> colon : Line <15> colon :
Line <15> string ./path/to/file Line <15> string Hi `Ryan`, I'm good.
Line <15> newline Line <15> newline
Line <15> newline Line <15> newline
Line <16> name a
Line <16> equal =
Line <16> number 1000
Line <16> newline Line <16> newline
Line <16> newline Line <16> newline
Line <17> bracketo [ Line <17> name test
Line <17> name step Line <17> equal =
Line <17> colon : Line <17> name invokeTest
Line <17> name function
Line <17> parao ( Line <17> parao (
Line <17> name a Line <17> string Running external code!
Line <17> seperator ,
Line <17> name b
Line <17> seperator ,
Line <17> name c
Line <17> parac ) Line <17> parac )
Line <17> bracketc ]
Line <17> newline Line <17> newline
Line <17> newline Line <17> newline
Line <18> string Testing... Line <17> newline
Line <18> string Loop Test... `test`
Line <18> newline Line <18> newline
Line <19> name d Line <18> newline
Line <19> equal = Line <19> control
Line <19> parao ( Line <19> string Pick one
Line <19> number 100 Line <19> cbracketo {
Line <19> plus +
Line <19> name b
Line <19> parac )
Line <19> divide /
Line <19> name c
Line <19> newline Line <19> newline
Line <19> newline Line <19> newline
Line <20> name e Line <20> string this
Line <20> equal = Line <20> gotoo
Line <20> string somestring Line <20> string this
Line <20> newline Line <20> newline
Line <20> newline Line <20> newline
Line <21> name e Line <21> string test2
Line <21> equal = Line <21> name tryme
Line <21> nil nil Line <21> parao (
Line <21> true true
Line <21> parac )
Line <21> newline Line <21> newline
Line <21> newline Line <21> newline
Line <22> name g Line <22> string that
Line <22> equal = Line <22> gotoo
Line <22> false false Line <22> string that
Line <22> newline Line <22> newline
Line <22> newline Line <22> newline
Line <23> ret Line <23> string test
Line <23> name d 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 <23> newline Line <23> newline
Line <24> cbracketc }
Line <24> newline Line <24> newline
Line <24> newline Line <24> newline
Line <25> bracketo [ Line <25> label this
Line <25> name inv
Line <25> colon :
Line <25> name env
Line <25> bracketc ]
Line <25> newline Line <25> newline
Line <25> newline Line <25> newline
Line <26> name slot1 Line <26> string At "this"
Line <26> equal =
Line <26> string S1
Line <26> newline Line <26> newline
Line <26> newline Line <26> newline
Line <27> name slot2 Line <27> gotoo
Line <27> equal = Line <27> string loop
Line <27> string S2
Line <27> newline Line <27> newline
Line <27> newline Line <27> newline
Line <28> name slot3 Line <28> label that
Line <28> equal =
Line <28> string S3
Line <28> newline Line <28> newline
Line <28> newline Line <28> newline
Line <29> name slot4 Line <29> string At "that"
Line <29> equal =
Line <29> string S4
Line <29> newline Line <29> newline
Line <29> newline Line <29> newline
Line <30> name slot5 Line <30> label loop
Line <30> equal =
Line <30> string S5
Line <30> newline Line <30> newline
Line <30> newline Line <30> newline
Line <31> name slot6 Line <31> name a
Line <31> equal = 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 <31> newline Line <31> newline
Line <32> name slot7 Line <32> string a = `a`
Line <32> equal =
Line <32> string S7
Line <32> newline Line <32> newline
Line <32> newline Line <32> newline
Line <33> name slot8 Line <33> gotoo
Line <33> equal = Line <33> string loop
Line <33> string S8
Line <33> newline Line <33> newline
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

View File

@ -3,10 +3,10 @@ namespace dms {
bool enviroment::has(std::string index) { bool enviroment::has(std::string index) {
return values.count(index); return values.count(index);
} }
void enviroment::set(std::string index, value* val) { void enviroment::set(std::string index, value val) {
values.insert_or_assign(index,val); values[index] = val;
} }
value* enviroment::get(std::string index) { value enviroment::get(std::string index) {
return values[index]; return values[index];
} }
} }

View File

@ -2,6 +2,7 @@
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include "value.h" #include "value.h"
#include "memory.h"
#include "Invoker.h" #include "Invoker.h"
namespace dms { namespace dms {
enum class env_type { enum class env_type {
@ -11,10 +12,10 @@ namespace dms {
}; };
struct enviroment : Invoker { struct enviroment : Invoker {
std::string name = ""; std::string name = "";
std::unordered_map<std::string, value*> values; memory values;
env_type type = env_type::env; env_type type = env_type::env;
bool has(std::string index); bool has(std::string index);
void set(std::string index, value* val); void set(std::string index, value val);
value* get(std::string index); value get(std::string index);
}; };
} }

View File

@ -1,5 +1,3 @@
enable tests
disable hello
[default:char] [default:char]
// The default stats for all characters. // The default stats for all characters.
money = 0 money = 0

13
DMS/memory.cpp Normal file
View File

@ -0,0 +1,13 @@
#include "memory.h"
#include <iostream>
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);
}
}

14
DMS/memory.h Normal file
View File

@ -0,0 +1,14 @@
#pragma once
#include <unordered_map>
#include <string>
#include "value.h"
namespace dms {
struct memory
{
size_t count(std::string);
void erase(std::string);
value& operator[](std::string);
private:
std::unordered_map<std::string, value> mem;
};
}

View File

@ -1,35 +0,0 @@
#include "number_utils.h"
namespace dms::number_utils {
dms_number* huge(dms_state* state) {
return buildNumber(std::numeric_limits<double>::max());
}
dms_number* tiny(dms_state* state) {
return buildNumber(std::numeric_limits<double>::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<double>::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);
}
}

View File

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

View File

@ -5,15 +5,32 @@ enable forseelabels
enable savestate enable savestate
disable fullname disable fullname
//enable leaking //enable leaking
enable debugging //enable debugging
loadfile "loadtest.dms" loadfile "loadtest.dms"
version 0.2 version 0.2
using extendedDefine using extendedDefine
[main] [main]
"Time to test function calls!" Ryan: "Hello `Bob`, how are you doing?"
val = newblock(1,2,3) Bob: "Hi `Ryan`, I'm good."
"val = `val`" 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] [Bob:char]
//fname = "Bob" //fname = "Bob"
@ -24,6 +41,11 @@ using extendedDefine
money = 100 money = 100
excited: "path/to/file" excited: "path/to/file"
[test1:function()]
"Inside a function!"
//val = newblock(1,2,3)
//"val = `val`"
[newblock:function(a,b,c)] [newblock:function(a,b,c)]
"Func Arguments: a = `a`, b = `b`, c = `c`" "Func Arguments: a = `a`, b = `b`, c = `c`"
"Time to return" "Time to return"

View File

@ -46,12 +46,12 @@ namespace dms::utils {
datatypes types[12] = { t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12 }; datatypes types[12] = { t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12 };
if (size >= 4) if (size >= 4)
for (size_t i = 0; i < 4; i++) { 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; return false;
} }
else else
for (size_t i = 0; i < size; i++) { 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 false;
} }
return true; return true;
@ -60,12 +60,12 @@ namespace dms::utils {
size_t size = args.args.size(); size_t size = args.args.size();
if (size >= 4) if (size >= 4)
for (size_t i = 0; i < 4; i++) { 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; return false;
} }
else else
for (size_t i = 0; i < size; i++) { 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 false;
} }
return true; return true;
@ -75,12 +75,12 @@ namespace dms::utils {
datatypes types[12] = { t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12 }; datatypes types[12] = { t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12 };
if(size >= 4) if(size >= 4)
for (size_t i = 0; i < 4;i++) { for (size_t i = 0; i < 4;i++) {
if (args.args[i]->type != types[i]) if (args.args[i].type != types[i])
return false; return false;
} }
else else
for (size_t i = 0; i < size; i++) { 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 false;
} }
return true; return true;
@ -90,15 +90,15 @@ namespace dms::utils {
datatypes types[12] = { t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12 }; datatypes types[12] = { t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12 };
if (size >= 4) if (size >= 4)
for (size_t i = 0; i < 4; i++) { for (size_t i = 0; i < 4; i++) {
if (args.args[i]->type != types[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)}); 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; return false;
} }
} }
else else
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
if (args.args[i]->type != types[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)}); 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; return false;
} }
} }

View File

@ -10,11 +10,11 @@
#include <time.h> #include <time.h>
namespace dms::utils { namespace dms::utils {
template<class... Args> template<class... Args>
void print(Args... args) { void print(const Args... args) {
(std::cout << ... << args) << std::endl; (std::cout << ... << args) << std::endl;
} }
template<class... Args> template<class... Args>
void write(Args... args) { void write(const Args... args) {
(std::cout << ... << args); (std::cout << ... << args);
} }
template<class... Args> template<class... Args>

View File

@ -2,42 +2,211 @@
#include "dms_state.h" #include "dms_state.h"
#include "utils.h" #include "utils.h"
namespace dms { namespace dms {
const std::string datatype[] = { "escape","nil", "number", "boolean", "env", "string", "custom", "variable", "block" }; const std::string datatype[] = { "escape", "nil", "number", "boolean", "env", "string", "custom", "variable", "block" };
std::vector<value*> _VALUES;
value::value() { value::value() {
_VALUES.push_back(this); // Used for the interperter! In the end everything is a value // Nothing to do here yet!
// 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!
} }
value* value::copy() { value::value(char const* str, datatypes t) {
value* newVal = new value; type = t;
newVal->type = type; s = buildString(str);
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) { value::value(char const* str) {
newVal->b = buildBool(b->getValue()); type = datatypes::string;
s = buildString(str);
} }
else if (type == datatypes::number) { value::value(std::string str) {
newVal->n = buildNumber(n->getValue()); type = datatypes::string;
s = buildString(str);
} }
else if (type == datatypes::nil) { value::value(std::string str,datatypes t) {
delete newVal; type = t;
return buildNil(); s = buildString(str);
} }
return newVal; value::value(double d) {
type = datatypes::number;
n = d;
} }
value* value::resolve(dms_state* state) { value::value(int d) {
if (type == datatypes::variable && this!=(*state->getMem())[this->s->getValue()]) { type = datatypes::number;
return (*state->getMem())[s->getValue()]->resolve(state); // Variable types return the value n = d;
} }
return this; value::value(bool bo) {
type = datatypes::boolean;
b = bo;
} }
void dms_args::push(value* val) { 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); args.push_back(val);
} }
size_t dms_args::size() { size_t dms_args::size() {
@ -49,7 +218,7 @@ namespace dms {
std::stringstream ind; std::stringstream ind;
bool varStart = false; bool varStart = false;
bool indStart = 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] == '`') { if (indStart && val[i] == '`') {
std::string lookup = var.str(); std::string lookup = var.str();
std::string index = ind.str(); std::string index = ind.str();
@ -60,21 +229,21 @@ namespace dms {
varStart = false; varStart = false;
indStart = false; indStart = false;
if (state->getMem()->count(lookup)) { if (state->getMem()->count(lookup)) {
value* v = (*state->getMem())[lookup]; value v = (*state->getMem())[lookup];
if (v->type == datatypes::block) { 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) { if (state->getCharacter(v.getPrintable()) != nullptr) {
character* cha = state->getCharacter(v->s->getValue()); character* cha = state->getCharacter(v.getPrintable());
if (cha->values.count(index)) { if (cha->values.count(index)) {
temp << cha->values[index]->getPrintable(); temp << cha->values[index].getPrintable();
} }
else { else {
temp << cha->getName(); 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) { else if (state->getEnvironment(v.getPrintable())!=nullptr) {
enviroment* env = state->getEnvironment(v->s->getValue()); enviroment* env = state->getEnvironment(v.getPrintable());
if (env->values.count(index)) { if (env->values.count(index)) {
temp << env->values[index]->getPrintable(); temp << env->values[index].getPrintable();
} }
else { else {
temp << env; temp << env;
@ -84,14 +253,14 @@ namespace dms {
temp << "nil"; temp << "nil";
} }
} }
else if (v->resolve(state)->type == datatypes::env) { else if (v.resolve(state).type == datatypes::env) {
if(v->resolve(state)->e->ipart.size()> std::stoi(index)) if(v.resolve(state).e->ipart.size()> std::stoi(index))
temp << v->resolve(state)->e->ipart[std::stoi(index)-1]->getPrintable(); temp << v.resolve(state).e->ipart[std::stoi(index)-(int64_t)1].getPrintable();
else else
temp << "nil"; temp << "nil";
} }
else { else {
temp << v->resolve(state)->getPrintable(); temp << v.resolve(state).getPrintable();
} }
} }
else { else {
@ -121,17 +290,17 @@ namespace dms {
var.clear(); var.clear();
varStart = false; varStart = false;
if (state->getMem()->count(lookup)) { if (state->getMem()->count(lookup)) {
value* v = (*state->getMem())[lookup]; value v = (*state->getMem())[lookup];
if (v->type == datatypes::block) { if (v.type == datatypes::block) {
if (state->getCharacter(v->s->getValue())) { if (state->getCharacter(v.s->getValue())) {
temp << state->characters[v->s->getValue()]->getName(); temp << state->characters[v.s->getValue()]->getName();
} }
else { else {
temp << "nil"; temp << "nil";
} }
} }
else { else {
temp << v->resolve(state)->getPrintable(); temp << v.resolve(state).getPrintable();
} }
} }
else { else {
@ -163,13 +332,13 @@ namespace dms {
out << s->getValue(); out << s->getValue();
} }
else if (type == number) { else if (type == number) {
out << n->getValue(); out << n;
} }
else if (type == nil) { else if (type == nil) {
out << "nil"; out << "nil";
} }
else if (type == boolean) { else if (type == boolean) {
if (b->getValue()) if (b)
out << "true"; out << "true";
else else
out << "false"; out << "false";
@ -189,112 +358,94 @@ namespace dms {
return out.str(); return out.str();
} }
dms_string* buildString(std::string str) { dms_string* buildString(std::string str) {
size_t len = str.length(); std::stringstream newstr;
uint8_t* arr = new uint8_t[len]; for (int i = 0; i < str.size(); i++)
for (size_t i = 0; i < len; i++) { newstr << str[i];
arr[i] = str.at(i); dms_string* dms_str = new dms_string{ newstr.str() };
}
dms_string* dms_str = new dms_string{ str.length(), arr };
return dms_str; return dms_str;
} }
dms_boolean* buildBool(bool b) { dms_boolean* buildBool(bool b) {
dms_boolean* dms_bool = new dms_boolean{b}; return new dms_boolean{b};
return dms_bool;
}
dms_number* buildNumber(double num) {
dms_number* dms_num = new dms_number{ num };
return dms_num;
} }
std::string value::toString() const { std::string value::toString() const {
std::stringstream temp; std::stringstream temp;
temp << this; temp << this;
return temp.str(); return temp.str();
} }
value* buildValue() { // Compile time
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;
}
void value::nuke() { void value::nuke() {
if (type == datatypes::custom) delete s;
c->_del(); delete e;
delete[] s; delete c;
delete[] b;
delete[] n;
delete[] e;
delete[] c;
s = nullptr; s = nullptr;
b = nullptr;
n = nullptr;
e = nullptr; e = nullptr;
c = 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 // Fixed issue with memory not properly being cleaned up
bool value::typeMatch(const value* o) const { bool value::typeMatch(const value* o) const {
return type == o->type; 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) { void value::set(dms_string* str) {
nuke(); nuke();
s = str; s = str;
type = string; type = string;
} }
void value::set(dms_boolean* bo) { void value::set(bool bo) {
nuke(); nuke();
b = bo; b = bo;
type = boolean; type = boolean;
} }
void value::set(dms_number* num) { void value::set(double num) {
nuke(); nuke();
n = num; n = num;
type = number; type = number;
} }
void dms::value::set(dms_env* en) { void dms::value::set(dms_list* en) {
nuke(); nuke();
e = en; e = en;
type = env; type = env;
@ -310,35 +461,45 @@ namespace dms {
type = nil; type = nil;
} }
std::string dms_string::getValue() { std::string dms_string::getValue() {
std::stringstream temp; return val;
for (size_t i = 0; i < length; i++) {
temp << val[i];
} }
return temp.str(); void dms_list::pushValue(value val) {
}
void dms_env::pushValue(value* val) {
ipart.push_back(val); ipart.push_back(val);
} }
void dms_env::pushValue(value* ind, value* val) { value dms_list::getValue(value ind) {
if (val->type == nil) { if (ind.type == number) {
hpart[ind->toString()]->nuke(); return ipart.at((int)ind.n);
hpart.erase(ind->toString());
count--;
} }
else { else {
hpart.insert_or_assign(ind->toString(), val); return new value();
count++;
} }
} }
value* dms_env::getValue(value* ind) { std::ostream& operator << (std::ostream& out, const dms_args& c) {
if (ind->type == number) { for (size_t i = 0; i < c.args.size(); i++) {
return ipart.at((int)ind->n->getValue()); if (i == c.args.size() - 1)
out << c.args[i];
else
out << c.args[i] << ", ";
} }
else if (ind->type == number) { return out;
return new value{}; // Return a nil value
} }
else { std::string dms_args::toString() {
return hpart.at(ind->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;
} }
} }

View File

@ -6,157 +6,100 @@
#include <map> #include <map>
namespace dms { namespace dms {
struct dms_env; struct dms_list;
struct value; struct value;
struct dms_args; struct dms_args;
struct dms_state;
extern const std::string datatype[]; extern const std::string datatype[];
enum datatypes { escape, nil, number, boolean, env, string, custom, variable, block, error }; enum datatypes { escape, nil, number, boolean, env, string, custom, variable, block, error };
struct dms_number { struct dms_number {
double val; double val;
double getValue() { return val; } double getValue() { return val; }
friend std::ostream& operator << (std::ostream& out, const dms_number& c) { friend std::ostream& operator << (std::ostream& out, const dms_number& c);
out << c.val;
return out;
};
}; };
struct dms_boolean { struct dms_boolean {
bool val; bool val;
bool getValue() { return val; } bool getValue() { return val; }
friend std::ostream& operator << (std::ostream& out, const dms_boolean& c) { friend std::ostream& operator << (std::ostream& out, const dms_boolean& c);
out << c.val;
return out;
}; };
};
struct dms_state;
struct dms_string { struct dms_string {
size_t length = 0; std::string val;
uint8_t* val = nullptr;
std::string getValue(); std::string getValue();
std::string getValue(dms_state* state); std::string getValue(dms_state* state);
friend std::ostream& operator << (std::ostream& out, const dms_string& c) { 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;
};
}; };
// Custom data that you can work with by overriding this code // Custom data that you can work with by overriding this code
struct dms_custom { struct dms_custom {
void Init(dms_state* state); void Init(dms_state* state);
void _set(value* v); void _set(value* v);
void _del(); void _del();
virtual value Index(value data);
virtual value* Index(value* data); virtual bool NewIndex(value var, value val);
virtual bool NewIndex(value* var, value* val); virtual value Call(dms_args* args);
virtual value* Call(dms_args* args); virtual value ToString();
virtual value* ToString(); virtual value ADD(value left, value right);
virtual value* ADD(value* left, value* right); virtual value SUB(value left, value right);
virtual value* SUB(value* left, value* right); virtual value MUL(value left, value right);
virtual value* MUL(value* left, value* right); virtual value DIV(value left, value right);
virtual value* DIV(value* left, value* right); virtual value POW(value left, value right);
virtual value* POW(value* left, value* right); virtual value EQUAL(value left, value right);
virtual value* EQUAL(value* left, value* right); virtual value LESS_THAN(value left, value right);
virtual value* LESS_THAN(value* left, value* right); virtual value LESS_THAN_EQUAL(value left, value right);
virtual value* LESS_THAN_EQUAL(value* left, value* right);
private: private:
dms_state* state=nullptr; dms_state* state=nullptr;
value* self; value* self;
}; };
dms_string* buildString(std::string str); dms_string* buildString(std::string str);
dms_boolean* buildBool(bool b); dms_boolean* buildBool(bool b);
dms_number* buildNumber(double num);
struct value { struct value {
public: public:
datatypes type = nil; datatypes type = datatypes::nil;
dms_boolean* b = nullptr; bool b=false;
dms_number* n = nullptr; double n=0;
dms_string* s = nullptr; dms_string* s = nullptr;
dms_env* e = nullptr; dms_list* e = nullptr;
dms_custom* c = nullptr; dms_custom* c = nullptr;
value(); value();
value* resolve(dms_state*); value(datatypes);
value* copy(); 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 nuke();
void set(value*);
void set(dms_string* str); void set(dms_string* str);
void set(dms_boolean* bo); void set(bool bo);
void set(dms_number* num); void set(double num);
void set(dms_env* en); void set(dms_list* en);
void set(dms_custom* cus); void set(dms_custom* cus);
void set(); void set();
bool typeMatch(const value* o) const; bool typeMatch(const value* o) const;
std::string getPrintable() const; std::string getPrintable() const;
std::string toString() const; std::string toString() const;
friend std::ostream& operator << (std::ostream& out, const value& c) { 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;
}; };
};
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 { struct dms_args {
std::vector<value*> args; std::vector<value> args;
void push(value* val); void push(value val);
size_t size(); size_t size();
friend std::ostream& operator << (std::ostream& out, const dms_args& c) { friend std::ostream& operator << (std::ostream& out, const dms_args& c);
for (size_t i=0; i < c.args.size(); i++) { std::string toString();
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<std::string, value*> hpart;
std::vector<value*> ipart;
void pushValue(value* val);
void pushValue(value* ind, value* val);
value* getValue(value* val);
private:
size_t count = 0;
}; };
} }