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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,17 +4,17 @@
namespace dms {
struct dms_state;
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;
public:
bool preventOverwriting = true;
bool registerFunction(std::string str, value* (*f)(void*, dms_state*, dms_args*));
bool registerFunction(std::string str, value* (*f)(void*, dms_state*, dms_args*), bool preventoverride);
bool registerFunction(std::string str, value (*f)(void*, dms_state*, dms_args*));
bool registerFunction(std::string str, value (*f)(void*, dms_state*, dms_args*), bool preventoverride);
void _init(void* ref);
value* Invoke(std::string str, dms_state* state, dms_args* args);
value Invoke(std::string str, dms_state* state, dms_args* args);
// Exports the methods from an Invoker object
std::unordered_map<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
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_disp(tokenstream* stream);
bool match_process_choice(tokenstream* stream);
bool match_process_function(tokenstream* stream, value* v=nullptr, bool nested = true);
bool match_process_function(tokenstream* stream, value& v, bool nested = true);
bool match_process_goto(tokenstream* stream);
bool match_process_jump(tokenstream* stream);
bool match_process_exit(tokenstream* stream);
bool match_process_expression(tokenstream* stream, value* v);
bool match_process_expression(tokenstream* stream, value& v);
bool match_process_IFFF(tokenstream* stream);
bool match_process_assignment(tokenstream* stream);
bool match_process_list(tokenstream* stream, value* v = nullptr);
bool match_process_list(tokenstream* stream, value& v);
bool match_process_wait(tokenstream* stream);
bool match_process_standard(tokenstream* stream, value* v = nullptr); // All types that are matchable are handled here!
bool match_process_index(tokenstream* stream,value* v = nullptr, bool leftside = false);
bool match_process_standard(tokenstream* stream, value& v); // All types that are matchable are handled here!
bool match_process_index(tokenstream* stream,value& v, bool leftside = false);
bool match_process_return(tokenstream* stream);
// Build

View File

@ -4,10 +4,10 @@ namespace dms {
cmd* c = new cmd;
c->opcode = codes::GOTO;
if (v) {
c->args.push(buildVariable(g));
c->args.push(value(g,datatypes::variable));
}
else {
c->args.push(buildValue(g));
c->args.push(value(g));
}
current_chunk->addCmd(c);
}
@ -19,8 +19,20 @@ namespace dms {
void LineParser::buildLabel(std::string l) {
cmd* c = new cmd;
c->opcode = codes::LABL;
c->args.push(buildValue(l));
c->args.push(value(l));
current_chunk->addCmd(c);
current_chunk->addLabel(l);
}
void LineParser::buildSpeed(double s) {
cmd* c = new cmd;
c->opcode = codes::DSPD;
c->args.push(value(s));
current_chunk->addCmd(c);
}
void LineParser::buildWait(double w) {
cmd* c = new cmd;
c->opcode = codes::WAIT;
c->args.push(value(w));
current_chunk->addCmd(c);
}
}

View File

@ -3,7 +3,7 @@ using namespace dms::tokens;
using namespace dms::utils;
// TODO: process if elseif else statements, for loops and while loops
namespace dms {
bool LineParser::match_process_standard(tokenstream* stream, value* v) {
bool LineParser::match_process_standard(tokenstream* stream, value& v) {
if (match_process_expression(stream, v)) {
return true;
}
@ -17,38 +17,38 @@ namespace dms {
return true;
}
else if (stream->match(tokens::True)) {
v->set(buildBool(true));
v.set(buildBool(true));
stream->next();
return true;
}
else if (stream->match(tokens::False)) {
v->set(buildBool(false));
v.set(buildBool(false));
stream->next();
return true;
}
else if (stream->match(tokens::number)) {
v->set(buildNumber(std::stod(stream->next().name)));
v.set(std::stod(stream->next().name));
return true;
}
else if (stream->match(tokens::string)) {
v->set(buildString(stream->next().name));
v.set(buildString(stream->next().name));
return true;
}
else if (stream->match(tokens::name)) {
v->set(buildString(stream->next().name));
v->type = datatypes::variable;
v.set(buildString(stream->next().name));
v.type = datatypes::variable;
return true;
}
else if (stream->match(tokens::nil)) {
stream->next();
v->set();
v.set();
return true;
}
else if (stream->match(tokens::bracketo, tokens::name, tokens::bracketc)) {
// We are assigning a block as a variable
stream->next();
v->set(buildString(stream->next().name));
v->type = datatypes::block;
v.set(buildString(stream->next().name));
v.type = datatypes::block;
stream->next();
return true;
}
@ -57,16 +57,16 @@ namespace dms {
}
return false;
}
bool LineParser::match_process_list(tokenstream* stream, value* v) {
bool LineParser::match_process_list(tokenstream* stream, value& v) {
if (stream->match(tokens::cbracketo)) {
token start = stream->peek();
token ancor = start;
std::vector<token> t = stream->next(tokens::cbracketo, tokens::cbracketc);
tokenstream tempstream;
tempstream.init(&t);
value* ref = buildVariable();
value* length = new value;
value* dict = nullptr;
value ref = value(datatypes::variable);
value length = value();
value dict = value();
size_t count = 0;
cmd* c = new cmd;
c->opcode = codes::LIST;
@ -91,7 +91,7 @@ namespace dms {
}
// Match Dict
else if (tempstream.match(tokens::name,tokens::colon)) {
dict = buildVariable(tempstream.next().name);
dict = value(tempstream.next().name,datatypes::variable);
tempstream.next();
if (!match_process_standard(&tempstream,ref)) {
badSymbol();
@ -123,7 +123,7 @@ namespace dms {
}
current_chunk->addCmd(c);
// Build new value
ref = buildVariable();
ref = value(datatypes::variable);
tempstream.next();
}
else if (tempstream.match(tokens::cbracketo)) {
@ -133,11 +133,11 @@ namespace dms {
badSymbol(&tempstream);
}
}
length->set(buildNumber(count)); // the second argument is the length of the list! This should be modified if lists are changed at runtime!
length.set((double)count); // the second argument is the length of the list! This should be modified if lists are changed at runtime!
c = new cmd;
c->opcode = codes::INST;
c->args.push(v);
c->args.push(buildNil());
c->args.push(value());
if (dict != nullptr) {
c->args.push(dict);
dict = nullptr;
@ -150,10 +150,9 @@ namespace dms {
bool LineParser::match_process_disp(tokenstream* stream) {
if ((isBlock(bt_block) || isBlock(bt_method)) && stream->match(tokens::newline, tokens::string, tokens::newline)) {
stream->next(); // Standard consumption
std::string msg = stream->next().name;
cmd* c = new cmd;
c->opcode = codes::DISP;
c->args.push(buildValue(msg));
c->args.push(value(stream->next().name));
current_chunk->addCmd(c); // Add the cmd to the current chunk
current_chunk->addCmd(new cmd{ codes::HALT });
return true;
@ -167,7 +166,7 @@ namespace dms {
std::string msg = stream->next().name;
cmd* c = new cmd;
c->opcode = codes::APND;
c->args.push(buildValue(concat(" ", msg)));
c->args.push(value(concat(" ", msg)));
current_chunk->addCmd(c); // Add the cmd to the current chunk
current_chunk->addCmd(new cmd{ codes::HALT });
return true;
@ -179,8 +178,8 @@ namespace dms {
std::string msg = stream->next().name;
cmd* c = new cmd;
c->opcode = codes::STAT;
c->args.push(buildVariable(name));
c->args.push(buildValue(msg));
c->args.push(value(name,datatypes::variable));
c->args.push(value(msg));
current_chunk->addCmd(c); // Add the cmd to the current chunk
}
else if ((isBlock(bt_block) || isBlock(bt_method)) && stream->match(tokens::newline, tokens::name, tokens::colon, tokens::string, tokens::newline)) {
@ -192,11 +191,11 @@ namespace dms {
std::string msg = stream->next().name;
cmd* c = new cmd;
c->opcode = codes::SSPK;
c->args.push(buildVariable(name));
c->args.push(value(name, datatypes::variable));
current_chunk->addCmd(c);
c = new cmd;
c->opcode = codes::DISP;
c->args.push(buildValue(msg));
c->args.push(value(msg));
current_chunk->addCmd(c); // Add the cmd to the current chunk
current_chunk->addCmd(new cmd{ codes::HALT });
return true;
@ -206,7 +205,7 @@ namespace dms {
// Command to set the speaker
cmd* c = new cmd;
c->opcode = codes::SSPK;
c->args.push(buildVariable(name));
c->args.push(value(name,datatypes::variable));
current_chunk->addCmd(c);
stream->next();
stream->next();
@ -239,12 +238,12 @@ namespace dms {
}
cmd* c = new cmd;
c->opcode = codes::DACT;
c->args.push(buildValue(mode));
c->args.push(value(mode));
current_chunk->addCmd(c);
// Now build the apnd msg cmd
c = new cmd;
c->opcode = codes::APND;
c->args.push(buildValue(stream->next().name));
c->args.push(value(stream->next().name));
current_chunk->addCmd(c);
}
else {
@ -256,7 +255,7 @@ namespace dms {
else if (stream->match(tokens::string)) {
cmd* c = new cmd;
c->opcode = codes::APND;
c->args.push(buildValue(stream->next().name));
c->args.push(value(stream->next().name));
current_chunk->addCmd(c);
}
else if (stream->match(tokens::newline)) {
@ -279,7 +278,7 @@ namespace dms {
if (stream->match(tokens::ret)) {
cmd* c = new cmd;
c->opcode = codes::RETN;
value* ref = buildVariable();
value ref = value(datatypes::variable);
stream->next();
if (match_process_standard(stream, ref)) {
c->args.push(ref);
@ -299,11 +298,10 @@ namespace dms {
return false;
}
bool LineParser::match_process_assignment(tokenstream* stream) {
value* v = buildVariable();
v->set();
value v = value();
if (match_process_index(stream, v, true)) {
cmd* c = current_chunk->cmds.back();
value* ref = buildVariable();
value ref = value(datatypes::variable);
if (stream->peek().type == tokens::equal) {
stream->next();
}
@ -320,26 +318,21 @@ namespace dms {
}
}
else if (stream->match(tokens::name,tokens::equal)) {
value* var = buildVariable(stream->next().name); // The variable that we will be setting stuff to
value var = value(stream->next().name,datatypes::variable); // The variable that we will be setting stuff to
stream->next(); // Consume the equal
cmd* c = new cmd;
c->opcode = codes::ASGN;
c->args.push(var);
value* ref = buildVariable();
value ref = value(datatypes::variable);
if (match_process_standard(stream,ref)) {
c->args.push(ref);
current_chunk->addCmd(c);
delete[] v;
return true;
}
else if (stream->match(tokens::newline)) {
stream->next();
}
}
else {
// We should clean up this
delete[] v;
}
return false;
}
bool LineParser::match_process_debug(tokenstream* stream) {
@ -350,10 +343,10 @@ namespace dms {
cmd* c = new cmd;
c->opcode = codes::DEBG;
if (stream->match(tokens::string)) {
c->args.push(buildValue(stream->next().name));
c->args.push(value(stream->next().name));
}
else {
c->args.push(buildVariable(stream->next().name));
c->args.push(value(stream->next().name,datatypes::variable));
}
current_chunk->addCmd(c);
return true;
@ -379,8 +372,8 @@ namespace dms {
std::string choi_str = concat("CHOI_", fn);
std::string choicelabel = concat("$CHOI_END_", choi_str,"_", stream->peek().line_num);
c->opcode = codes::CHOI;
c->args.push(buildValue(prompt));
c->args.push(buildValue(fn));
c->args.push(prompt);
c->args.push(fn);
current_chunk->addCmd(c); // We will keep a reference to this and add to it as we go through the list
bool start = false;
bool hasfunc = false;
@ -416,10 +409,10 @@ namespace dms {
}
else if (stream->match(tokens::string)) {
std::string name = stream->next().name;
c->args.push(buildValue(name)); // We append the choice to the first part of the CHOI cmd
c->args.push(value(name)); // We append the choice to the first part of the CHOI cmd
// We consumed the option now lets do some matching, note that all of these are one liners in the bytecode!
if (match_process_function(stream,nullptr,false)) { // No returns and also no nesting of functions!
value val = value();
if (match_process_function(stream,val,false)) { // No returns and also no nesting of functions!
// We cannot have a nested function here, but if we dont have that then we add our goto
hasfunc = true;
buildGoto(choicelabel);
@ -436,6 +429,7 @@ namespace dms {
badSymbol(stream);
}
}
buildGoto(choicelabel);
cmd* cc = current_chunk->cmds.back(); // Delete last element
current_chunk->cmds.pop_back();
delete cc;
@ -448,9 +442,9 @@ namespace dms {
void cleanup(value* v) {
v->nuke(); // Make sure we clean up the data
delete[] v; // We didn't need it, lets clean it up!
delete v; // We didn't need it, lets clean it up!
}
bool LineParser::match_process_function(tokenstream* stream, value* v, bool nested) {
bool LineParser::match_process_function(tokenstream* stream, value& v, bool nested) {
/*
Functions should be able to handle function calls as arguments,
HOWEVER functions cannot be passed as values since they aren't values like they are in other languages!
@ -496,13 +490,13 @@ namespace dms {
cmd* c = new cmd;
c->opcode = codes::FUNC;
std::string n = stream->next().name;
c->args.push(buildVariable(n)); // Set the func identifier as the first variable
c->args.push(value(n,datatypes::variable)); // Set the func identifier as the first variable
// Let's set the target
if (v != nullptr) {
if (!v.isNil()) {
c->args.push(v); // Push the supplied variable
}
else {
c->args.push(buildValue()); // Creates a nil value
c->args.push(value()); // Creates a nil value
}
// Already we have built: FUNC name val
// Next we add arguments this is where things get interesting
@ -519,18 +513,17 @@ namespace dms {
t.push_back(token{ tokens::nil,codes::NOOP,"",t[0].line_num });
t.push_back(end);
tempstream.init(&t); // Turn tokens we consumed into a tokenstream
value* tempval;
value tempval;
token tok;
value* ref = buildVariable();
value ref = value(datatypes::variable);
// This part we add values to the opcodes for the bytecode FUNC val a1 a2 a3 ... an
while (tempstream.peek().type != tokens::none) { // End of stream
debugInvoker(stream);
tempval = buildVariable();
tempval = value(datatypes::variable);
tok = tempstream.peek();
if (tempstream.match(tokens::seperator)) {
// We have a seperator for function arguments
tempstream.next(); // Consume it
cleanup(tempval); // We don't need it
}
else if (match_process_standard(&tempstream, tempval)) {
c->args.push(tempval);
@ -539,14 +532,11 @@ namespace dms {
tempstream.next();
}
else if (tempstream.match(tokens::parac)) {
cleanup(tempval);
tempstream.next();
current_chunk->addCmd(c); // We push this onto the chunk after all dependants if any have been handled
//lastCall.pop();
return true;
}
else {
cleanup(tempval); // Cleanup
badSymbol(&tempstream);
}
}
@ -555,15 +545,15 @@ namespace dms {
cmd* c = new cmd;
c->opcode = codes::OFUN;
// OFUN obj fname target args
c->args.push(buildVariable(stream->next().name)); // push the obj
c->args.push(value(stream->next().name,datatypes::variable)); // push the obj
stream->next(); // consume the dot
c->args.push(buildVariable(stream->next().name)); // push the fname
c->args.push(value(stream->next().name,datatypes::variable)); // push the fname
// Let's set the target
if (v != nullptr) {
if (!v.isNil()) {
c->args.push(v); // Push the supplied variable
}
else {
c->args.push(buildValue()); // Creates a nil value
c->args.push(value()); // Creates a nil value
}
// Already we have built: FUNC name val
// Next we add arguments this is where things get interesting
@ -580,18 +570,17 @@ namespace dms {
t.push_back(token{ tokens::nil,codes::NOOP,"",t[0].line_num });
t.push_back(end);
tempstream.init(&t); // Turn tokens we consumed into a tokenstream
value* tempval;
value tempval;
token tok;
value* ref = buildVariable();
value ref = value(datatypes::variable);
// This part we add values to the opcodes for the bytecode FUNC val a1 a2 a3 ... an
while (tempstream.peek().type != tokens::none) { // End of stream
debugInvoker(stream);
tempval = buildVariable();
tempval = value(datatypes::variable);
tok = tempstream.peek();
if (tempstream.match(tokens::seperator)) {
// We have a seperator for function arguments
tempstream.next(); // Consume it
cleanup(tempval); // We don't need it
}
else if (match_process_standard(&tempstream, tempval)) {
c->args.push(tempval);
@ -600,14 +589,12 @@ namespace dms {
tempstream.next();
}
else if (tempstream.match(tokens::parac)) {
cleanup(tempval);
tempstream.next();
current_chunk->addCmd(c); // We push this onto the chunk after all dependants if any have been handled
//lastCall.pop();
return true;
}
else {
cleanup(tempval); // Cleanup
badSymbol(&tempstream);
}
}
@ -627,7 +614,7 @@ namespace dms {
}
return false;
}
bool LineParser::match_process_index(tokenstream* stream, value* v, bool leftside) {
bool LineParser::match_process_index(tokenstream* stream, value& v, bool leftside) {
if (stream->match(tokens::name,tokens::bracketo)) {
std::string name = stream->next().name;
std::vector<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 });
tokenstream tempstream; // As usual the tokens are balanced match to [...] where the contents of tok = ...
tempstream.init(&tok);
value* tempval = buildVariable();
value tempval = value(datatypes::variable);
cmd* c = new cmd;
if (leftside) {
c->opcode = codes::ASID;
@ -647,7 +634,7 @@ namespace dms {
while (tempstream.peek().type != tokens::none) { // Keep going until we hit the end
if (match_process_standard(&tempstream, tempval)) {
c->args.push(v);
c->args.push(buildBlock(name));
c->args.push(value(name,datatypes::block));
c->args.push(tempval);
}
else if (nlcount) {
@ -677,10 +664,10 @@ namespace dms {
c->opcode = codes::JUMP;
stream->next(); // consume jump
if (stream->match(tokens::name)) {
c->args.push(buildVariable(stream->next().name));
c->args.push(value(stream->next().name,datatypes::variable));
}
else {
c->args.push(buildValue(stream->next().name));
c->args.push(value(stream->next().name));
}
current_chunk->addCmd(c);
return true;
@ -694,10 +681,10 @@ namespace dms {
c->opcode = codes::EXIT;
if (stream->match(tokens::number) || stream->match(tokens::name)) {
if(stream->match(tokens::number)){
c->args.push(buildValue(std::stod(stream->next().name)));
c->args.push(value(std::stod(stream->next().name)));
}
else {
c->args.push(buildVariable(stream->next().name));
c->args.push(value(stream->next().name,datatypes::variable));
}
}
current_chunk->addCmd(c);
@ -722,13 +709,13 @@ namespace dms {
return false;
}
void reset(value*& l, codes::op& op, value*& r) {
l = nullptr;
void reset(value& l, codes::op& op, value& r) {
l = value();
op = codes::NOOP;
r = nullptr;
r = value();
}
bool LineParser::match_process_expression(tokenstream* stream, value* v) {
bool LineParser::match_process_expression(tokenstream* stream, value& v) {
// I will have to consume for this to work so we need to keep track of what was incase we return false!
stream->store(current_chunk);
cmd* lastcmd = nullptr;
@ -736,10 +723,10 @@ namespace dms {
if ((stream->match(tokens::number) || stream->match(tokens::name) || stream->match(tokens::parao)) && stream->tokens.size()>=3) {
// What do we know, math expressions can only be on a single line. We know where to stop looking if we have to
cmd* c = new cmd;
value* wv = nullptr;
value* left; // lefthand
value wv;
value left; // lefthand
codes::op op; // opperator
value* right; // righthand
value right; // righthand
reset(left, op, right);
size_t loops = 0;
bool hasOP = false;
@ -748,11 +735,11 @@ namespace dms {
if (stream->match(tokens::parao)) {
tokenstream temp;
temp.init(&(stream->next(tokens::parao, tokens::parac))); // Balanced match!
value* tmpvalue = buildVariable();
value tmpvalue = value(datatypes::variable);
if (match_process_expression(&temp, tmpvalue)) {
if (left == nullptr)
if (left.isNil())
left = tmpvalue;
else if (right == nullptr)
else if (right.isNil())
right = tmpvalue;
else
badSymbol(stream);
@ -772,8 +759,8 @@ namespace dms {
}
else if (stream->match(tokens::minus)) {
hasOP = true;
if (left == nullptr) {
left = buildValue(0); // -5 is the same as 0-5 right? Also -(5+5) is the same as 0-(5+5) So we good
if (left.isNil()) {
left = value(0); // -5 is the same as 0-5 right? Also -(5+5) is the same as 0-(5+5) So we good
}
if (op == codes::NOOP)
op = codes::SUB;
@ -815,11 +802,11 @@ namespace dms {
}
else if (stream->match(tokens::name,tokens::parao)) {
//Function template ^^^ If we encounter an issue the method should push an error, incase it misses something we will!
value* tmpvalue = buildVariable();
value tmpvalue = value(datatypes::variable);
if (match_process_function(stream,tmpvalue)) {
if (left == nullptr)
if (left.isNil())
left = tmpvalue;
else if (right == nullptr)
else if (right.isNil())
right = tmpvalue;
else
badSymbol(stream);
@ -830,24 +817,24 @@ namespace dms {
}
else if (stream->match(tokens::number)) {
double num = std::stod(stream->next().name);
if (left == nullptr)
left = buildValue(num);
else if (right == nullptr)
right = buildValue(num);
if (left.isNil())
left = value(num);
else if (right.isNil())
right = value(num);
else
badSymbol(stream);
}
else if (stream->match(tokens::name)) {
// We tested functions already! So if that fails and we have a name then... we have a variable lets handle this!
if (left == nullptr)
left = buildVariable(stream->next().name);
else if (right == nullptr)
right = buildVariable(stream->next().name);
if (left.isNil())
left = value(stream->next().name,datatypes::variable);
else if (right.isNil())
right = value(stream->next().name,datatypes::variable);
else
badSymbol(stream);
}
else if (stream->match(tokens::newline) || stream->match(tokens::parac) || stream->match(tokens::seperator)) {
if (wv == nullptr)
if (wv.isNil())
return stream->restore(lastcmd, current_chunk); // Always return false and restores the position in stream!
cmd* cc = new cmd;
cc->opcode = codes::ASGN;
@ -866,16 +853,16 @@ namespace dms {
else {
return stream->restore(lastcmd, current_chunk);
}
if (left != nullptr && right != nullptr && op != codes::NOOP) {
if (!left.isNil() && !right.isNil() && op != codes::NOOP) {
cmd* c = new cmd;
c->opcode = op;
if (wv == nullptr) {
value* temp = buildVariable();
if (wv.isNil()) {
value temp = value(datatypes::variable);
c->args.push(temp);
wv = temp;
}
else {
wv = buildVariable();
wv = value(datatypes::variable);
c->args.push(wv);
}
c->args.push(left);

View File

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

View File

@ -203,29 +203,17 @@ namespace dms {
void LineParser::badSymbol() {
state->push_error(errors::error{ errors::unknown,concat("Unexpected symbol '",_stream->peek().toString(),"'"),true,_stream->next().line_num,current_chunk });
}
void LineParser::buildSpeed(double s) {
cmd* c = new cmd;
c->opcode = codes::DSPD;
c->args.push(buildValue(s));
current_chunk->addCmd(c);
}
void LineParser::buildWait(double w) {
cmd* c = new cmd;
c->opcode = codes::WAIT;
c->args.push(buildValue(w));
current_chunk->addCmd(c);
}
void LineParser::debugInvoker(tokenstream* stream) {
if (state->isEnabled("debugging") && stream->peek().type != tokens::newline) {
// A very nasty if statement, I won't hide it, this could be made much more readable
// This checks if the last cmd is a LINE cmd and if its the same line number as the current one we simply skip it
if (current_chunk->cmds.size() >= 2 && current_chunk->cmds[current_chunk->cmds.size() - 1]!=nullptr && current_chunk->cmds[current_chunk->cmds.size() - 1]->opcode==codes::LINE && (size_t)current_chunk->cmds[current_chunk->cmds.size()-1]->args.args[0]->n->getValue()== (size_t)stream->peek().line_num) {
if (current_chunk->cmds.size() >= 2 && current_chunk->cmds[current_chunk->cmds.size() - 1]!=nullptr && current_chunk->cmds[current_chunk->cmds.size() - 1]->opcode==codes::LINE && (size_t)current_chunk->cmds[current_chunk->cmds.size()-1]->args.args[0].n== (size_t)stream->peek().line_num) {
return;
}
int current_line = stream->peek().line_num;
cmd* ln = new cmd;
ln->opcode = codes::LINE;
ln->args.push(buildValue(current_line));
ln->args.push(value(current_line));
current_chunk->addCmd(ln);
}
}
@ -259,16 +247,16 @@ namespace dms {
if (state->isEnabled("leaking") && (current_chunk != nullptr && current_chunk->name != "$INIT")) {
cmd* c = new cmd;
c->opcode = codes::JUMP;
c->args.push(buildValue(bk_name));
c->args.push(value(bk_name));
current_chunk->addCmd(c);
}
if (current_chunk != nullptr && current_chunk->name == "$END") {
cmd* c = new cmd;
c->opcode = codes::EXIT;
if (state->entry != "$undefined")
c->args.push(buildValue(0));
c->args.push(value(0));
else
c->args.push(buildValue(bk_name));
c->args.push(value(bk_name));
current_chunk->addCmd(c);
}
current_chunk = new chunk;

View File

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

View File

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

View File

@ -14,4 +14,6 @@
#include "utils.h"
#include "value.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) {
this->state = state;
}
value* dms_custom::Index(value* data) {
value dms_custom::Index(value data) {
state->push_error(errors::error{ errors::unknown,"Attempting to index a non enviroment!" });
return nullptr;
}
bool dms_custom::NewIndex(value* var, value* val) {
bool dms_custom::NewIndex(value var, value val) {
state->push_error(errors::error{ errors::unknown,"Attempting to create a new index on a non enviroment!" });
return false;
}
value* dms_custom::Call(dms_args* args) {
value dms_custom::Call(dms_args* args) {
state->push_error(errors::error{errors::unknown,"Attempting to call a non function value!"});
return nullptr;
}
value* dms_custom::ToString() {
return buildValue(utils::concat("Custom: ",this));
value dms_custom::ToString() {
return value(utils::concat("Custom: ",this));
}
value* dms_custom::ADD(value* left, value* right) {
value dms_custom::ADD(value left, value right) {
state->push_error(errors::error{ errors::unknown,"Attempting to add a non number value!" });
return nullptr;
}
value* dms_custom::SUB(value* left, value* right) {
value dms_custom::SUB(value left, value right) {
state->push_error(errors::error{ errors::unknown,"Attempting to subtract a non number value!" });
return nullptr;
}
value* dms_custom::MUL(value* left, value* right) {
value dms_custom::MUL(value left, value right) {
state->push_error(errors::error{ errors::unknown,"Attempting to multiply a non number value!" });
return nullptr;
}
value* dms_custom::DIV(value* left, value* right) {
value dms_custom::DIV(value left, value right) {
state->push_error(errors::error{ errors::unknown,"Attempting to divide a non number value!" });
return nullptr;
}
value* dms_custom::POW(value* left, value* right) {
value dms_custom::POW(value left, value right) {
state->push_error(errors::error{ errors::unknown,"Attempting to raise a non number value!" });
return nullptr;
}
value* dms_custom::EQUAL(value* left, value* right) {
return buildValue(left->getPrintable() == right->getPrintable());
value dms_custom::EQUAL(value left, value right) {
return value(left.getPrintable() == right.getPrintable());
}
value* dms_custom::LESS_THAN(value* left, value* right) {
return buildValue(left->getPrintable() < right->getPrintable());
value dms_custom::LESS_THAN(value left, value right) {
return value(left.getPrintable() < right.getPrintable());
}
value* dms_custom::LESS_THAN_EQUAL(value* left, value* right) {
return buildValue(left->getPrintable() <= right->getPrintable());
value dms_custom::LESS_THAN_EQUAL(value left, value right) {
return value(left.getPrintable() <= right.getPrintable());
}
}

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

View File

@ -9,18 +9,20 @@
#include "dms_exceptions.h"
#include "Character.h"
#include "enviroment.h"
#include "memory.h"
#include <stack>
#include "dms_list.h"
namespace dms {
struct Handler;
value* blockInvoke(void*, dms_state*, dms_args*);
value blockInvoke(void*, dms_state*, dms_args*);
struct dms_state
{
Handler* handler = nullptr;
bool hasFirst = false;
Invoker invoker;
std::stack<std::string> call_stack;
std::stack<value*> return_stack;
std::stack<std::unordered_map<std::string, value*>*> mem_stack;
std::stack<value> return_stack;
std::stack<memory> mem_stack;
std::vector<value*> garbage;
std::unordered_map<std::string, chunk*> chunks;
std::unordered_map<std::string, character*> characters;
@ -53,19 +55,18 @@ namespace dms {
character* getCharacter(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);
bool characterExists(std::string bk_name);
bool environmentExists(std::string bk_name);
bool functionExists(std::string bk_name);
bool blockExists(std::string bk_name);
bool typeAssert(value* val, datatypes type);
std::unordered_map<std::string, value*>* getMem();
bool typeAssert(value val, datatypes type);
memory* getMem();
void pushMem();
void popMem();
value* func();
bool run();
bool run(std::string ent,std::unordered_map<std::string, value*>* mem);
bool run(std::string ent,memory* mem);
bool run(std::string instance);
// This is called once and once only. Dynamically loading code is not a thing!
void init();
@ -73,8 +74,6 @@ namespace dms {
private:
// From what I gathered
//std::mutex memory_mutex;
std::unordered_map<std::string, value*> memory;
void pushMem(std::unordered_map<std::string, value*>*);
bool stop = false;
bool init_init = false;
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;
}
void checkCharacter(character* cc,std::string index, datatypes type) {
value* val = cc->get(index);
if (val==nullptr) {
value val = cc->get(index);
// If a type mismatch is present, overwrite them with the defaults
if (val.type!=type) {
if (type == datatypes::string)
cc->values[index] = buildValue("");
cc->values[index] = value("");
else if (type == datatypes::boolean) {
cc->values[index] = buildValue(false);
cc->values[index] = value(false);
}
}
else if (val != nullptr) {
if (val->type != type) {
cc->values.erase(index);
else if (type == datatypes::number) {
cc->values[index] = value(0);
}
}
}
@ -56,10 +55,10 @@ namespace dms {
if (blockExists(cha)) {
character* cc = new character;
cc->fullname = isEnabled("fullname");
cc->set("fname", buildValue(cha));
cc->set("lname", buildValue(""));
cc->set("unknown", buildValue("Unknown"));
cc->set("known", buildValue(false));
cc->set("fname", cha);
cc->set("lname", "");
cc->set("unknown", "Unknown");
cc->set("known", false);
if (isEnabled("omniscient")) {
cc->seen = true;
}
@ -71,7 +70,7 @@ namespace dms {
checkCharacter(cc, "lname", datatypes::string);
checkCharacter(cc, "unknown", datatypes::string);
checkCharacter(cc, "known", datatypes::boolean);
if (cc->get("known")->b->getValue() == true) {
if (cc->get("known").b == true) {
cc->seen = true;
}
}
@ -92,7 +91,7 @@ namespace dms {
}
size_t dms_state::seek(std::string label, std::vector<cmd*> cmds, codes::op code, size_t pos) {
for (size_t i = pos; i < cmds.size(); i++) {
if (cmds[i]->opcode == code && cmds[i]->args.args[0]->s->getValue() == label)
if (cmds[i]->opcode == code && cmds[i]->args.args[0].getPrintable() == label)
return i;
}
return 0;
@ -113,9 +112,9 @@ namespace dms {
push_error(errors::error{ errors::non_existing_block ,utils::concat("Attempted to Jump to a non existing block [",entry,"]") });
return false;
}
return run("$INIT",&memory);
return run("$INIT",getMem());
}
bool dms_state::run(std::string ent, std::unordered_map<std::string, value*>* mem) {
bool dms_state::run(std::string ent, memory* mem) {
if (stop) {
exitcode = 1;
return false;
@ -143,19 +142,19 @@ namespace dms {
// Handle flags here
case ENTR:
// When reading code from a file the flags are compiled and we need to load them
entry = c->args.args[0]->s->getValue();
entry = c->args.args[0].getPrintable();
break;
case ENAB:
enable(c->args.args[0]->s->getValue());
enable(c->args.args[0].getPrintable());
break;
case DISA:
disable(c->args.args[0]->s->getValue());
disable(c->args.args[0].getPrintable());
break;
case LOAD:
// Nothing needs to be done here
break;
case VERN:
Sversion = c->args.args[0]->n->getValue();
Sversion = c->args.args[0].n;
// Version X.xx
// X: Will not guarantee compatibality. Code breaking changes should be expected especially on lower versions
// xx: Will not break compatibality. They may add features as it goes up the ranks, but those changes do not break older code. If they do they will increase the X part and not the xx part
@ -173,13 +172,26 @@ namespace dms {
// Flags handled
case EXIT:
if (c->args.args.size()) {
exitcode = c->args.args[0]->n->getValue();
exitcode = c->args.args[0].n;
}
return true;
break;
case GOTO:
{
value labl = c->args.args[0];
size_t nnpos = seek(labl.getPrintable(),cmds, LABL, 0);
if (!nnpos) {
push_error(errors::error{ errors::choice_unknown ,utils::concat("Unknown choice!") });
return false;
}
else {
pos = nnpos;
}
}
break;
case RETN:
{
value* ret = c->args.args[0]->resolve(this)->copy();
value ret = c->args.args[0].resolve(this);
//c->args.args[0]->nuke(); // Lets clean this up
return_stack.push(ret);
return true; // We did it, let's return this
@ -187,35 +199,32 @@ namespace dms {
break;
case OFUN:
{
std::string obj = c->args.args[0]->getPrintable();
std::string funcname = c->args.args[1]->getPrintable();
value* assn = c->args.args[2];
std::string obj = c->args.args[0].getPrintable();
std::string funcname = c->args.args[1].getPrintable();
value assn = c->args.args[2];
dms_args args;
for (int i = 3; i < c->args.args.size(); i++) {
args.push(c->args.args[i]);
}
value* ret = nullptr;
value ret;
if (characterExists(obj)) {
ret = getCharacter(obj)->Invoke(funcname, this, &args);
}
else if (environmentExists(obj)) {
ret = getEnvironment(obj)->Invoke(funcname, this, &args);
}
//value* ret = invoker.Invoke(funcname, nullptr, this, &args);
if (ret == nullptr)
return false;
if (assn->type != datatypes::nil) {
assign(mem, assn, ret);
if (assn.type != datatypes::nil) {
assign(assn, ret);
}
}
break;
case FUNC:
{
std::string funcname = c->args.args[0]->getPrintable();
value* assn = c->args.args[1];
std::string funcname = c->args.args[0].getPrintable();
value assn = c->args.args[1];
dms_args args;
value* ret = nullptr;
value ret;
for (int i = 2; i < c->args.args.size(); i++) {
args.push(c->args.args[i]);
}
@ -225,126 +234,124 @@ namespace dms {
ret = invoker.Invoke("$BlockInvoke$", this, &args);
}
else {
value* ret = invoker.Invoke(funcname, this, &args);
ret = invoker.Invoke(funcname, this, &args);
}
if (ret == nullptr)
return false;
if (assn->type != datatypes::nil) {
assign(getMem(), assn, ret);
if (assn.type != datatypes::nil) {
assign(assn, ret);
}
}
break;
case ASID:
{
value* env = c->args.args[1];
value* indx = c->args.args[2]->resolve(this);
value* assn = c->args.args[3]->resolve(this);
if (env->type == datatypes::block && blockExists(env->getPrintable())) { // If this is a block let's handle this
value env = c->args.args[1];
value indx = c->args.args[2].resolve(this);
value assn = c->args.args[3].resolve(this);
if (env.type == datatypes::block && blockExists(env.getPrintable())) { // If this is a block let's handle this
enviroment* e = nullptr;
if (environments.count(env->getPrintable())) {
e = environments[env->getPrintable()];
if (environments.count(env.getPrintable())) {
e = environments[env.getPrintable()];
}
else if (characters.count(env->getPrintable())) {
e = characters[env->getPrintable()];
else if (characters.count(env.getPrintable())) {
e = characters[env.getPrintable()];
}
e->values[indx->getPrintable()] = assn;
e->values[indx.getPrintable()] = assn;
}
else if (env->type == datatypes::env) {
if (indx->type == datatypes::number) {
env->e->pushValue(assn);
else if (env.type == datatypes::env) {
if (indx.type == datatypes::number) {
env.e->pushValue(assn);
}
else {
push_error(errors::error{ errors::invalid_type ,concat("Expected a number value got ",datatype[indx->type]) });
push_error(errors::error{ errors::invalid_type ,concat("Expected a number value got ",datatype[indx.type]) });
return false;
}
}
else if (env->type == datatypes::custom) {
env->c->NewIndex(indx, assn);
//assign(mem, assn, env->c->Index(indx));
else if (env.type == datatypes::custom) {
env.c->NewIndex(indx, assn);
//assign( assn, env->c->Index(indx));
// Call the method within the custom data
}
break;
}
case ADD:
{
value* assn = c->args.args[0];
value* o1 = c->args.args[1];
value* o2 = c->args.args[2];
value* ret = buildValue(o1->resolve(this)->n->getValue()+o2->resolve(this)->n->getValue());
assign(getMem(), assn, ret);
value assn = c->args.args[0];
value o1 = c->args.args[1];
value o2 = c->args.args[2];
value ret = value(o1.resolve(this).n+o2.resolve(this).n);
assign(assn, ret);
}
break;
case SUB:
{
value* assn = c->args.args[0];
value* o1 = c->args.args[1];
value* o2 = c->args.args[2];
value* ret = buildValue(o1->resolve(this)->n->getValue() - o2->resolve(this)->n->getValue());
assign(getMem(), assn, ret);
value assn = c->args.args[0];
value o1 = c->args.args[1];
value o2 = c->args.args[2];
value ret = value(o1.resolve(this).n - o2.resolve(this).n);
assign(assn, ret);
}
break;
case MUL:
{
value* assn = c->args.args[0];
value* o1 = c->args.args[1];
value* o2 = c->args.args[2];
value* ret = buildValue(o1->resolve(this)->n->getValue() * o2->resolve(this)->n->getValue());
assign(getMem(), assn, ret);
value assn = c->args.args[0];
value o1 = c->args.args[1];
value o2 = c->args.args[2];
value ret = value(o1.resolve(this).n * o2.resolve(this).n);
assign(assn, ret);
}
break;
case DIV:
{
value* assn = c->args.args[0];
value* o1 = c->args.args[1];
value* o2 = c->args.args[2];
value* ret = buildValue(o1->resolve(this)->n->getValue() / o2->resolve(this)->n->getValue());
assign(getMem(), assn, ret);
value assn = c->args.args[0];
value o1 = c->args.args[1];
value o2 = c->args.args[2];
value ret = value(o1.resolve(this).n / o2.resolve(this).n);
assign(assn, ret);
}
break;
case POW:
{
value* assn = c->args.args[0];
value* o1 = c->args.args[1];
value* o2 = c->args.args[2];
value* ret = buildValue(pow(o1->resolve(this)->n->getValue(), o2->resolve(this)->n->getValue()));
assign(getMem(), assn, ret);
value assn = c->args.args[0];
value o1 = c->args.args[1];
value o2 = c->args.args[2];
value ret = value(pow(o1.resolve(this).n, o2.resolve(this).n));
assign(assn, ret);
}
break;
case MOD:
{
value* assn = c->args.args[0];
value* o1 = c->args.args[1];
value* o2 = c->args.args[2];
value* ret = buildValue(std::fmod(o1->resolve(this)->n->getValue(),o2->resolve(this)->n->getValue()));
assign(getMem(), assn, ret);
value assn = c->args.args[0];
value o1 = c->args.args[1];
value o2 = c->args.args[2];
value ret = value(std::fmod(o1.resolve(this).n,o2.resolve(this).n));
assign(assn, ret);
}
break;
case INDX:
{
value* assn = c->args.args[0];
value* env = c->args.args[1];
value* indx = c->args.args[2]->resolve(this);
if (env->type == datatypes::block && blockExists(env->getPrintable())) { // If this is a block let's handle this
value assn = c->args.args[0];
value env = c->args.args[1];
value indx = c->args.args[2].resolve(this);
if (env.type == datatypes::block && blockExists(env.getPrintable())) { // If this is a block let's handle this
enviroment* e = nullptr;
if (environments.count(env->getPrintable())) {
e = environments[env->getPrintable()];
if (environments.count(env.getPrintable())) {
e = environments[env.getPrintable()];
}
else if (characters.count(env->getPrintable())) {
e = characters[env->getPrintable()];
else if (characters.count(env.getPrintable())) {
e = characters[env.getPrintable()];
}
assign(mem, assn, e->values[indx->getPrintable()]);
assign( assn, e->values[indx.getPrintable()]);
}
else if (env->type == datatypes::env) {
if (indx->type == datatypes::number) {
assign(mem, assn, env->e->getValue(indx));
else if (env.type == datatypes::env) {
if (indx.type == datatypes::number) {
assign( assn, env.e->getValue(indx));
}
else {
push_error(errors::error{ errors::invalid_type ,concat("Expected a number value got ",datatype[indx->type]) });
push_error(errors::error{ errors::invalid_type ,concat("Expected a number value got ",datatype[indx.type]) });
return false;
}
}
else if (env->type == datatypes::custom) {
assign(mem, assn, env->c->Index(indx));
else if (env.type == datatypes::custom) {
assign( assn, env.c->Index(indx));
// Call the method within the custom data
}
}
@ -352,17 +359,18 @@ namespace dms {
case LIST:
//We need to create an enviroment value then set that
{
dms_env* env = new dms_env;
env->hpart.insert_or_assign("$size", c->args.args[1]);
value* val = new value;
val->set(env);
assign(mem,c->args.args[0], val);
dms_list* env = new dms_list;
// Inject the size of the list
env->hpart["$size"] = c->args.args[1];
value val = new value;
val.set(env);
assign(c->args.args[0], val);
}
break;
case INST:
{
value* list = (*mem)[c->args.args[0]->s->getValue()];
list->e->pushValue(c->args.args[1]);
value list = (*mem)[c->args.args[0].getPrintable()];
list.e->pushValue(c->args.args[1]);
}
break;
case HALT:
@ -371,7 +379,7 @@ namespace dms {
std::cout << std::endl;
break;
case WAIT:
sleep((int)(c->args.args[0]->n->getValue()*1000));
sleep((int)(c->args.args[0].n*1000));
break;
case DSPD:
if (speaker == nullptr) {
@ -379,34 +387,34 @@ namespace dms {
return false;
}
else {
speaker->spd = c->args.args[0]->n->getValue();
speaker->spd = c->args.args[0].n;
}
break;
case SSPK:
//Because we are using void* we must cast our pointers
if (characterExists(c->args.args[0]->s->getValue())){
speaker = getCharacter(c->args.args[0]->s->getValue());
if (characterExists(c->args.args[0].s->getValue())){
speaker = getCharacter(c->args.args[0].s->getValue());
if (!handler->handleSpeaker(this, speaker))
return false;
}
else {
push_error(errors::error{ errors::disp_unknown,concat("Unknown character '",c->args.args[0]->s->getValue(),"'!")});
push_error(errors::error{ errors::disp_unknown,concat("Unknown character '",c->args.args[0].s->getValue(),"'!")});
return false;
}
break;
case APND:
if (!handler->handleMessageAppend(this, c->args.args[0]->s->getValue(this)))
if (!handler->handleMessageAppend(this, c->args.args[0].s->getValue(this)))
return false;
break;
case DISP:
if (!handler->handleMessageDisplay(this, c->args.args[0]->s->getValue(this)))
if (!handler->handleMessageDisplay(this, c->args.args[0].s->getValue(this)))
return false;
break;
case ASGN:
assign(mem,c->args.args[0], c->args.args[1]);
assign(c->args.args[0], c->args.args[1]);
break;
case LINE:
cur_line = c->args.args[0]->n->getValue();
cur_line = c->args.args[0].n;
break;
case NOOP:
break;
@ -414,12 +422,12 @@ namespace dms {
//Because we are using void* we must cast our pointers
{
std::vector<std::string> args;
std::string prompt = c->args.args[0]->s->getValue();
std::string fn = c->args.args[1]->s->getValue();
std::string prompt = c->args.args[0].s->getValue();
std::string fn = c->args.args[1].s->getValue();
for (size_t i = 2; i < c->args.args.size(); i++)
args.push_back(c->args.args[i]->resolve(this)->s->getValue());
args.push_back(c->args.args[i].resolve(this).s->getValue());
size_t npos = handler->handleChoice(this, prompt, args);
size_t nnpos = seek(concat("CHOI_", fn, "_", npos),cmds,LABL,npos);
size_t nnpos = seek(concat("CHOI_", fn, "_", npos),cmds,LABL,pos);
if (!nnpos) {
push_error(errors::error{ errors::choice_unknown ,utils::concat("Unknown choice!") });
return false;
@ -432,7 +440,7 @@ namespace dms {
case JUMP:
// Value assert resolves the data so a variable must eventually equal a string
if (utils::valueassert(c->args, this, datatypes::string)) {
std::string block = c->args.args[0]->resolve(this)->s->getValue();
std::string block = c->args.args[0].resolve(this).s->getValue();
if (chunks[block] == NULL) {
push_error(errors::error{ errors::non_existing_block ,utils::concat("Attempted to Jump to a non existing block [",block,"]") });
return false;
@ -446,7 +454,9 @@ namespace dms {
}
}
else {
datatypes set = c->args.args[0]->resolve(this)->type;
//utils::print(c->args.args[0].type);
datatypes set = c->args.args[0].resolve(this).type;
//utils::print("> ",set);
push_error(errors::error{ errors::invalid_arguments, utils::concat("String expected got ",datatype[set]), true,ln });
return false;
}

Binary file not shown.

View File

@ -22,9 +22,6 @@ Line <6> name fullname
Line <6> newline
Line <6> newline
Line <7> newline
Line <8> flag
Line <8> name debugging
Line <8> newline
Line <8> newline
Line <9> flag
Line <9> string loadtest.dms
@ -45,250 +42,336 @@ Line <13> name main
Line <13> bracketc ]
Line <13> newline
Line <13> newline
Line <14> string Time to test function calls!
Line <14> newline
Line <14> newline
Line <15> name val
Line <15> equal =
Line <15> name newblock
Line <15> parao (
Line <15> number 1
Line <15> seperator ,
Line <15> number 2
Line <15> seperator ,
Line <15> number 3
Line <15> parac )
Line <15> newline
Line <15> newline
Line <16> string val = `val`
Line <16> newline
Line <16> newline
Line <17> newline
Line <17> newline
Line <18> bracketo [
Line <18> name Bob
Line <18> colon :
Line <18> name char
Line <18> bracketc ]
Line <18> newline
Line <18> newline
Line <19> newline
Line <20> newline
Line <21> newline
Line <22> name unknown
Line <22> equal =
Line <22> string Some Random Guy
Line <22> newline
Line <22> newline
Line <23> name age
Line <23> equal =
Line <23> number 0.24
Line <23> newline
Line <23> newline
Line <24> name money
Line <24> equal =
Line <24> number 100
Line <24> newline
Line <24> newline
Line <25> name excited
Line <25> colon :
Line <25> string path/to/file
Line <25> newline
Line <25> newline
Line <26> newline
Line <26> newline
Line <27> bracketo [
Line <27> name newblock
Line <27> colon :
Line <27> name function
Line <27> parao (
Line <27> name a
Line <27> seperator ,
Line <27> name b
Line <27> seperator ,
Line <27> name c
Line <27> parac )
Line <27> bracketc ]
Line <27> newline
Line <27> newline
Line <28> string Func Arguments: a = `a`, b = `b`, c = `c`
Line <28> newline
Line <28> newline
Line <29> string Time to return
Line <29> newline
Line <29> newline
Line <30> ret
Line <30> name a
Line <30> plus +
Line <30> name b
Line <30> plus +
Line <30> name c
Line <30> newline
Line <30> newline
Line <30> eof
Line <1> newline
Line <1> newline
Line <1> flag
Line <1> name tests
Line <1> newline
Line <1> newline
Line <2> flag
Line <2> name hello
Line <2> newline
Line <2> newline
Line <3> bracketo [
Line <3> name default
Line <3> colon :
Line <3> name char
Line <3> bracketc ]
Line <3> newline
Line <3> newline
Line <4> newline
Line <5> name money
Line <5> equal =
Line <5> number 0
Line <5> newline
Line <5> newline
Line <6> name test
Line <6> equal =
Line <6> nil nil
Line <6> newline
Line <6> newline
Line <7> newline
Line <7> newline
Line <8> bracketo [
Line <8> name Ryan
Line <8> colon :
Line <8> name char
Line <8> bracketc ]
Line <8> newline
Line <8> newline
Line <9> name age
Line <9> equal =
Line <9> number 21
Line <9> newline
Line <9> newline
Line <10> name money
Line <10> equal =
Line <10> number 1000
Line <10> newline
Line <10> newline
Line <11> name lname
Line <11> equal =
Line <11> string Ward
Line <11> newline
Line <11> newline
Line <12> name known
Line <12> equal =
Line <12> true true
Line <12> newline
Line <12> newline
Line <13> newline
Line <14> name calm
Line <14> name Ryan
Line <14> colon :
Line <14> string ./path/to/file
Line <14> string Hello `Bob`, how are you doing?
Line <14> newline
Line <14> newline
Line <15> name excited
Line <15> name Bob
Line <15> colon :
Line <15> string ./path/to/file
Line <15> string Hi `Ryan`, I'm good.
Line <15> newline
Line <15> newline
Line <16> name a
Line <16> equal =
Line <16> number 1000
Line <16> newline
Line <16> newline
Line <17> bracketo [
Line <17> name step
Line <17> colon :
Line <17> name function
Line <17> name test
Line <17> equal =
Line <17> name invokeTest
Line <17> parao (
Line <17> name a
Line <17> seperator ,
Line <17> name b
Line <17> seperator ,
Line <17> name c
Line <17> string Running external code!
Line <17> parac )
Line <17> bracketc ]
Line <17> newline
Line <17> newline
Line <18> string Testing...
Line <17> newline
Line <18> string Loop Test... `test`
Line <18> newline
Line <19> name d
Line <19> equal =
Line <19> parao (
Line <19> number 100
Line <19> plus +
Line <19> name b
Line <19> parac )
Line <19> divide /
Line <19> name c
Line <18> newline
Line <19> control
Line <19> string Pick one
Line <19> cbracketo {
Line <19> newline
Line <19> newline
Line <20> name e
Line <20> equal =
Line <20> string somestring
Line <20> string this
Line <20> gotoo
Line <20> string this
Line <20> newline
Line <20> newline
Line <21> name e
Line <21> equal =
Line <21> nil nil
Line <21> string test2
Line <21> name tryme
Line <21> parao (
Line <21> true true
Line <21> parac )
Line <21> newline
Line <21> newline
Line <22> name g
Line <22> equal =
Line <22> false false
Line <22> string that
Line <22> gotoo
Line <22> string that
Line <22> newline
Line <22> newline
Line <23> ret
Line <23> name d
Line <23> string test
Line <23> name test
Line <23> parao (
Line <23> number 1
Line <23> seperator ,
Line <23> number 2
Line <23> seperator ,
Line <23> number 3
Line <23> parac )
Line <23> newline
Line <23> newline
Line <24> cbracketc }
Line <24> newline
Line <24> newline
Line <25> bracketo [
Line <25> name inv
Line <25> colon :
Line <25> name env
Line <25> bracketc ]
Line <25> label this
Line <25> newline
Line <25> newline
Line <26> name slot1
Line <26> equal =
Line <26> string S1
Line <26> string At "this"
Line <26> newline
Line <26> newline
Line <27> name slot2
Line <27> equal =
Line <27> string S2
Line <27> gotoo
Line <27> string loop
Line <27> newline
Line <27> newline
Line <28> name slot3
Line <28> equal =
Line <28> string S3
Line <28> label that
Line <28> newline
Line <28> newline
Line <29> name slot4
Line <29> equal =
Line <29> string S4
Line <29> string At "that"
Line <29> newline
Line <29> newline
Line <30> name slot5
Line <30> equal =
Line <30> string S5
Line <30> label loop
Line <30> newline
Line <30> newline
Line <31> name slot6
Line <31> name a
Line <31> equal =
Line <31> string S6
Line <31> name a
Line <31> plus +
Line <31> number 1
Line <31> newline
Line <31> newline
Line <32> name slot7
Line <32> equal =
Line <32> string S7
Line <32> string a = `a`
Line <32> newline
Line <32> newline
Line <33> name slot8
Line <33> equal =
Line <33> string S8
Line <33> gotoo
Line <33> string loop
Line <33> newline
Line <33> newline
Line <33> eof
Line <34> newline
Line <34> newline
Line <35> bracketo [
Line <35> name Bob
Line <35> colon :
Line <35> name char
Line <35> bracketc ]
Line <35> newline
Line <35> newline
Line <36> newline
Line <37> newline
Line <38> newline
Line <39> name unknown
Line <39> equal =
Line <39> string Some Random Guy
Line <39> newline
Line <39> newline
Line <40> name age
Line <40> equal =
Line <40> number 0.24
Line <40> newline
Line <40> newline
Line <41> name money
Line <41> equal =
Line <41> number 100
Line <41> newline
Line <41> newline
Line <42> name excited
Line <42> colon :
Line <42> string path/to/file
Line <42> newline
Line <42> newline
Line <43> newline
Line <43> newline
Line <44> bracketo [
Line <44> name test1
Line <44> colon :
Line <44> name function
Line <44> parao (
Line <44> parac )
Line <44> bracketc ]
Line <44> newline
Line <44> newline
Line <45> string Inside a function!
Line <45> newline
Line <45> newline
Line <46> newline
Line <47> newline
Line <48> newline
Line <48> newline
Line <49> bracketo [
Line <49> name newblock
Line <49> colon :
Line <49> name function
Line <49> parao (
Line <49> name a
Line <49> seperator ,
Line <49> name b
Line <49> seperator ,
Line <49> name c
Line <49> parac )
Line <49> bracketc ]
Line <49> newline
Line <49> newline
Line <50> string Func Arguments: a = `a`, b = `b`, c = `c`
Line <50> newline
Line <50> newline
Line <51> string Time to return
Line <51> newline
Line <51> newline
Line <52> ret
Line <52> name a
Line <52> plus +
Line <52> name b
Line <52> plus +
Line <52> name c
Line <52> newline
Line <52> newline
Line <52> eof
Line <1> newline
Line <1> newline
Line <1> bracketo [
Line <1> name default
Line <1> colon :
Line <1> name char
Line <1> bracketc ]
Line <1> newline
Line <1> newline
Line <2> newline
Line <3> name money
Line <3> equal =
Line <3> number 0
Line <3> newline
Line <3> newline
Line <4> name test
Line <4> equal =
Line <4> nil nil
Line <4> newline
Line <4> newline
Line <5> newline
Line <5> newline
Line <6> bracketo [
Line <6> name Ryan
Line <6> colon :
Line <6> name char
Line <6> bracketc ]
Line <6> newline
Line <6> newline
Line <7> name age
Line <7> equal =
Line <7> number 21
Line <7> newline
Line <7> newline
Line <8> name money
Line <8> equal =
Line <8> number 1000
Line <8> newline
Line <8> newline
Line <9> name lname
Line <9> equal =
Line <9> string Ward
Line <9> newline
Line <9> newline
Line <10> name known
Line <10> equal =
Line <10> true true
Line <10> newline
Line <10> newline
Line <11> newline
Line <12> name calm
Line <12> colon :
Line <12> string ./path/to/file
Line <12> newline
Line <12> newline
Line <13> name excited
Line <13> colon :
Line <13> string ./path/to/file
Line <13> newline
Line <13> newline
Line <14> newline
Line <14> newline
Line <15> bracketo [
Line <15> name step
Line <15> colon :
Line <15> name function
Line <15> parao (
Line <15> name a
Line <15> seperator ,
Line <15> name b
Line <15> seperator ,
Line <15> name c
Line <15> parac )
Line <15> bracketc ]
Line <15> newline
Line <15> newline
Line <16> string Testing...
Line <16> newline
Line <17> name d
Line <17> equal =
Line <17> parao (
Line <17> number 100
Line <17> plus +
Line <17> name b
Line <17> parac )
Line <17> divide /
Line <17> name c
Line <17> newline
Line <17> newline
Line <18> name e
Line <18> equal =
Line <18> string somestring
Line <18> newline
Line <18> newline
Line <19> name e
Line <19> equal =
Line <19> nil nil
Line <19> newline
Line <19> newline
Line <20> name g
Line <20> equal =
Line <20> false false
Line <20> newline
Line <20> newline
Line <21> ret
Line <21> name d
Line <21> newline
Line <21> newline
Line <22> newline
Line <22> newline
Line <23> bracketo [
Line <23> name inv
Line <23> colon :
Line <23> name env
Line <23> bracketc ]
Line <23> newline
Line <23> newline
Line <24> name slot1
Line <24> equal =
Line <24> string S1
Line <24> newline
Line <24> newline
Line <25> name slot2
Line <25> equal =
Line <25> string S2
Line <25> newline
Line <25> newline
Line <26> name slot3
Line <26> equal =
Line <26> string S3
Line <26> newline
Line <26> newline
Line <27> name slot4
Line <27> equal =
Line <27> string S4
Line <27> newline
Line <27> newline
Line <28> name slot5
Line <28> equal =
Line <28> string S5
Line <28> newline
Line <28> newline
Line <29> name slot6
Line <29> equal =
Line <29> string S6
Line <29> newline
Line <29> newline
Line <30> name slot7
Line <30> equal =
Line <30> string S7
Line <30> newline
Line <30> newline
Line <31> name slot8
Line <31> equal =
Line <31> string S8
Line <31> newline
Line <31> newline
Line <31> eof

View File

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

View File

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

View File

@ -1,5 +1,3 @@
enable tests
disable hello
[default:char]
// The default stats for all characters.
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
disable fullname
//enable leaking
enable debugging
//enable debugging
loadfile "loadtest.dms"
version 0.2
using extendedDefine
[main]
"Time to test function calls!"
val = newblock(1,2,3)
"val = `val`"
Ryan: "Hello `Bob`, how are you doing?"
Bob: "Hi `Ryan`, I'm good."
a = 1000
test = invokeTest("Running external code!");
"Loop Test... `test`"
choice "Pick one" {
"this" goto "this"
"test2" tryme(true)
"that" goto "that"
"test" test(1,2,3)
}
::this::
"At \"this\""
goto "loop"
::that::
"At \"that\""
::loop::
a = a + 1
"a = `a`"
goto "loop"
[Bob:char]
//fname = "Bob"
@ -24,6 +41,11 @@ using extendedDefine
money = 100
excited: "path/to/file"
[test1:function()]
"Inside a function!"
//val = newblock(1,2,3)
//"val = `val`"
[newblock:function(a,b,c)]
"Func Arguments: a = `a`, b = `b`, c = `c`"
"Time to return"

View File

@ -46,12 +46,12 @@ namespace dms::utils {
datatypes types[12] = { t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12 };
if (size >= 4)
for (size_t i = 0; i < 4; i++) {
if (args.args[i]->resolve(state)->type != types[i])
if (args.args[i].resolve(state).type != types[i])
return false;
}
else
for (size_t i = 0; i < size; i++) {
if (args.args[i]->resolve(state)->type != types[i])
if (args.args[i].resolve(state).type != types[i])
return false;
}
return true;
@ -60,12 +60,12 @@ namespace dms::utils {
size_t size = args.args.size();
if (size >= 4)
for (size_t i = 0; i < 4; i++) {
if (args.args[i]->resolve(state)->type != t1)
if (args.args[i].resolve(state).type != t1)
return false;
}
else
for (size_t i = 0; i < size; i++) {
if (args.args[i]->resolve(state)->type != t1)
if (args.args[i].resolve(state).type != t1)
return false;
}
return true;
@ -75,12 +75,12 @@ namespace dms::utils {
datatypes types[12] = { t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12 };
if(size >= 4)
for (size_t i = 0; i < 4;i++) {
if (args.args[i]->type != types[i])
if (args.args[i].type != types[i])
return false;
}
else
for (size_t i = 0; i < size; i++) {
if (args.args[i]->type != types[i])
if (args.args[i].type != types[i])
return false;
}
return true;
@ -90,15 +90,15 @@ namespace dms::utils {
datatypes types[12] = { t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12 };
if (size >= 4)
for (size_t i = 0; i < 4; i++) {
if (args.args[i]->type != types[i]) {
state->push_error(dms::errors::error{ errors::invalid_arguments, "Invalid arguments! Expected (" + resolveTypes(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12) + ") Got: " + resolveTypes(args.args[i]->type)});
if (args.args[i].type != types[i]) {
state->push_error(dms::errors::error{ errors::invalid_arguments, "Invalid arguments! Expected (" + resolveTypes(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12) + ") Got: " + resolveTypes(args.args[i].type)});
return false;
}
}
else
for (size_t i = 0; i < size; i++) {
if (args.args[i]->type != types[i]) {
state->push_error(dms::errors::error{ errors::invalid_arguments, "Invalid arguments! Expected (" + resolveTypes(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12) + ") Got: " + resolveTypes(args.args[i]->type)});
if (args.args[i].type != types[i]) {
state->push_error(dms::errors::error{ errors::invalid_arguments, "Invalid arguments! Expected (" + resolveTypes(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12) + ") Got: " + resolveTypes(args.args[i].type)});
return false;
}
}

View File

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

View File

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

View File

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