Rewrote so much code
This commit is contained in:
parent
d91ee2b662
commit
34208eacff
13
DMS/DMS.cpp
13
DMS/DMS.cpp
@ -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) {
|
||||
|
||||
@ -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" />
|
||||
|
||||
@ -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>
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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";
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -14,4 +14,6 @@
|
||||
#include "utils.h"
|
||||
#include "value.h"
|
||||
#include "Invoker.h"
|
||||
#include "memory.h"
|
||||
#include "dms_list.h"
|
||||
|
||||
|
||||
@ -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
11
DMS/dms_list.h
Normal 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);
|
||||
};
|
||||
}
|
||||
@ -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,22 +130,9 @@ 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);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
value* temp = (*mem)[var->s->getValue()];
|
||||
if (temp->type != datatypes::variable) {
|
||||
temp->set(); // Set the removed value to nil
|
||||
garbage.push_back((*mem)[var->s->getValue()]);
|
||||
}
|
||||
else
|
||||
utils::print("> so we have a variable"); // This print should be a reminder for me to do something about this.
|
||||
(*mem)[var->s->getValue()] = val;
|
||||
return true;
|
||||
}
|
||||
bool dms_state::assign(value var, value val) {
|
||||
(*getMem())[var.getPrintable()] = val;
|
||||
return true;
|
||||
}
|
||||
void dms_state::dump(bool print) {
|
||||
if (print)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
BIN
DMS/dump.bin
BIN
DMS/dump.bin
Binary file not shown.
495
DMS/dump.txt
495
DMS/dump.txt
@ -22,9 +22,6 @@ Line <6> name fullname
|
||||
Line <6> newline
|
||||
Line <6> newline
|
||||
Line <7> newline
|
||||
Line <8> flag
|
||||
Line <8> name debugging
|
||||
Line <8> newline
|
||||
Line <8> newline
|
||||
Line <9> flag
|
||||
Line <9> string loadtest.dms
|
||||
@ -45,250 +42,336 @@ Line <13> name main
|
||||
Line <13> bracketc ]
|
||||
Line <13> newline
|
||||
Line <13> newline
|
||||
Line <14> string Time to test function calls!
|
||||
Line <14> newline
|
||||
Line <14> newline
|
||||
Line <15> name val
|
||||
Line <15> equal =
|
||||
Line <15> name newblock
|
||||
Line <15> parao (
|
||||
Line <15> number 1
|
||||
Line <15> seperator ,
|
||||
Line <15> number 2
|
||||
Line <15> seperator ,
|
||||
Line <15> number 3
|
||||
Line <15> parac )
|
||||
Line <15> newline
|
||||
Line <15> newline
|
||||
Line <16> string val = `val`
|
||||
Line <16> newline
|
||||
Line <16> newline
|
||||
Line <17> newline
|
||||
Line <17> newline
|
||||
Line <18> bracketo [
|
||||
Line <18> name Bob
|
||||
Line <18> colon :
|
||||
Line <18> name char
|
||||
Line <18> bracketc ]
|
||||
Line <18> newline
|
||||
Line <18> newline
|
||||
Line <19> newline
|
||||
Line <20> newline
|
||||
Line <21> newline
|
||||
Line <22> name unknown
|
||||
Line <22> equal =
|
||||
Line <22> string Some Random Guy
|
||||
Line <22> newline
|
||||
Line <22> newline
|
||||
Line <23> name age
|
||||
Line <23> equal =
|
||||
Line <23> number 0.24
|
||||
Line <23> newline
|
||||
Line <23> newline
|
||||
Line <24> name money
|
||||
Line <24> equal =
|
||||
Line <24> number 100
|
||||
Line <24> newline
|
||||
Line <24> newline
|
||||
Line <25> name excited
|
||||
Line <25> colon :
|
||||
Line <25> string path/to/file
|
||||
Line <25> newline
|
||||
Line <25> newline
|
||||
Line <26> newline
|
||||
Line <26> newline
|
||||
Line <27> bracketo [
|
||||
Line <27> name newblock
|
||||
Line <27> colon :
|
||||
Line <27> name function
|
||||
Line <27> parao (
|
||||
Line <27> name a
|
||||
Line <27> seperator ,
|
||||
Line <27> name b
|
||||
Line <27> seperator ,
|
||||
Line <27> name c
|
||||
Line <27> parac )
|
||||
Line <27> bracketc ]
|
||||
Line <27> newline
|
||||
Line <27> newline
|
||||
Line <28> string Func Arguments: a = `a`, b = `b`, c = `c`
|
||||
Line <28> newline
|
||||
Line <28> newline
|
||||
Line <29> string Time to return
|
||||
Line <29> newline
|
||||
Line <29> newline
|
||||
Line <30> ret
|
||||
Line <30> name a
|
||||
Line <30> plus +
|
||||
Line <30> name b
|
||||
Line <30> plus +
|
||||
Line <30> name c
|
||||
Line <30> newline
|
||||
Line <30> newline
|
||||
Line <30> eof
|
||||
Line <1> newline
|
||||
Line <1> newline
|
||||
Line <1> flag
|
||||
Line <1> name tests
|
||||
Line <1> newline
|
||||
Line <1> newline
|
||||
Line <2> flag
|
||||
Line <2> name hello
|
||||
Line <2> newline
|
||||
Line <2> newline
|
||||
Line <3> bracketo [
|
||||
Line <3> name default
|
||||
Line <3> colon :
|
||||
Line <3> name char
|
||||
Line <3> bracketc ]
|
||||
Line <3> newline
|
||||
Line <3> newline
|
||||
Line <4> newline
|
||||
Line <5> name money
|
||||
Line <5> equal =
|
||||
Line <5> number 0
|
||||
Line <5> newline
|
||||
Line <5> newline
|
||||
Line <6> name test
|
||||
Line <6> equal =
|
||||
Line <6> nil nil
|
||||
Line <6> newline
|
||||
Line <6> newline
|
||||
Line <7> newline
|
||||
Line <7> newline
|
||||
Line <8> bracketo [
|
||||
Line <8> name Ryan
|
||||
Line <8> colon :
|
||||
Line <8> name char
|
||||
Line <8> bracketc ]
|
||||
Line <8> newline
|
||||
Line <8> newline
|
||||
Line <9> name age
|
||||
Line <9> equal =
|
||||
Line <9> number 21
|
||||
Line <9> newline
|
||||
Line <9> newline
|
||||
Line <10> name money
|
||||
Line <10> equal =
|
||||
Line <10> number 1000
|
||||
Line <10> newline
|
||||
Line <10> newline
|
||||
Line <11> name lname
|
||||
Line <11> equal =
|
||||
Line <11> string Ward
|
||||
Line <11> newline
|
||||
Line <11> newline
|
||||
Line <12> name known
|
||||
Line <12> equal =
|
||||
Line <12> true true
|
||||
Line <12> newline
|
||||
Line <12> newline
|
||||
Line <13> newline
|
||||
Line <14> name calm
|
||||
Line <14> name Ryan
|
||||
Line <14> colon :
|
||||
Line <14> string ./path/to/file
|
||||
Line <14> string Hello `Bob`, how are you doing?
|
||||
Line <14> newline
|
||||
Line <14> newline
|
||||
Line <15> name excited
|
||||
Line <15> name Bob
|
||||
Line <15> colon :
|
||||
Line <15> string ./path/to/file
|
||||
Line <15> string Hi `Ryan`, I'm good.
|
||||
Line <15> newline
|
||||
Line <15> newline
|
||||
Line <16> name a
|
||||
Line <16> equal =
|
||||
Line <16> number 1000
|
||||
Line <16> newline
|
||||
Line <16> newline
|
||||
Line <17> bracketo [
|
||||
Line <17> name step
|
||||
Line <17> colon :
|
||||
Line <17> name function
|
||||
Line <17> name test
|
||||
Line <17> equal =
|
||||
Line <17> name invokeTest
|
||||
Line <17> parao (
|
||||
Line <17> name a
|
||||
Line <17> seperator ,
|
||||
Line <17> name b
|
||||
Line <17> seperator ,
|
||||
Line <17> name c
|
||||
Line <17> string Running external code!
|
||||
Line <17> parac )
|
||||
Line <17> bracketc ]
|
||||
Line <17> newline
|
||||
Line <17> newline
|
||||
Line <18> string Testing...
|
||||
Line <17> newline
|
||||
Line <18> string Loop Test... `test`
|
||||
Line <18> newline
|
||||
Line <19> name d
|
||||
Line <19> equal =
|
||||
Line <19> parao (
|
||||
Line <19> number 100
|
||||
Line <19> plus +
|
||||
Line <19> name b
|
||||
Line <19> parac )
|
||||
Line <19> divide /
|
||||
Line <19> name c
|
||||
Line <18> newline
|
||||
Line <19> control
|
||||
Line <19> string Pick one
|
||||
Line <19> cbracketo {
|
||||
Line <19> newline
|
||||
Line <19> newline
|
||||
Line <20> name e
|
||||
Line <20> equal =
|
||||
Line <20> string somestring
|
||||
Line <20> string this
|
||||
Line <20> gotoo
|
||||
Line <20> string this
|
||||
Line <20> newline
|
||||
Line <20> newline
|
||||
Line <21> name e
|
||||
Line <21> equal =
|
||||
Line <21> nil nil
|
||||
Line <21> string test2
|
||||
Line <21> name tryme
|
||||
Line <21> parao (
|
||||
Line <21> true true
|
||||
Line <21> parac )
|
||||
Line <21> newline
|
||||
Line <21> newline
|
||||
Line <22> name g
|
||||
Line <22> equal =
|
||||
Line <22> false false
|
||||
Line <22> string that
|
||||
Line <22> gotoo
|
||||
Line <22> string that
|
||||
Line <22> newline
|
||||
Line <22> newline
|
||||
Line <23> ret
|
||||
Line <23> name d
|
||||
Line <23> string test
|
||||
Line <23> name test
|
||||
Line <23> parao (
|
||||
Line <23> number 1
|
||||
Line <23> seperator ,
|
||||
Line <23> number 2
|
||||
Line <23> seperator ,
|
||||
Line <23> number 3
|
||||
Line <23> parac )
|
||||
Line <23> newline
|
||||
Line <23> newline
|
||||
Line <24> cbracketc }
|
||||
Line <24> newline
|
||||
Line <24> newline
|
||||
Line <25> bracketo [
|
||||
Line <25> name inv
|
||||
Line <25> colon :
|
||||
Line <25> name env
|
||||
Line <25> bracketc ]
|
||||
Line <25> label this
|
||||
Line <25> newline
|
||||
Line <25> newline
|
||||
Line <26> name slot1
|
||||
Line <26> equal =
|
||||
Line <26> string S1
|
||||
Line <26> string At "this"
|
||||
Line <26> newline
|
||||
Line <26> newline
|
||||
Line <27> name slot2
|
||||
Line <27> equal =
|
||||
Line <27> string S2
|
||||
Line <27> gotoo
|
||||
Line <27> string loop
|
||||
Line <27> newline
|
||||
Line <27> newline
|
||||
Line <28> name slot3
|
||||
Line <28> equal =
|
||||
Line <28> string S3
|
||||
Line <28> label that
|
||||
Line <28> newline
|
||||
Line <28> newline
|
||||
Line <29> name slot4
|
||||
Line <29> equal =
|
||||
Line <29> string S4
|
||||
Line <29> string At "that"
|
||||
Line <29> newline
|
||||
Line <29> newline
|
||||
Line <30> name slot5
|
||||
Line <30> equal =
|
||||
Line <30> string S5
|
||||
Line <30> label loop
|
||||
Line <30> newline
|
||||
Line <30> newline
|
||||
Line <31> name slot6
|
||||
Line <31> name a
|
||||
Line <31> equal =
|
||||
Line <31> string S6
|
||||
Line <31> name a
|
||||
Line <31> plus +
|
||||
Line <31> number 1
|
||||
Line <31> newline
|
||||
Line <31> newline
|
||||
Line <32> name slot7
|
||||
Line <32> equal =
|
||||
Line <32> string S7
|
||||
Line <32> string a = `a`
|
||||
Line <32> newline
|
||||
Line <32> newline
|
||||
Line <33> name slot8
|
||||
Line <33> equal =
|
||||
Line <33> string S8
|
||||
Line <33> gotoo
|
||||
Line <33> string loop
|
||||
Line <33> newline
|
||||
Line <33> newline
|
||||
Line <33> eof
|
||||
Line <34> newline
|
||||
Line <34> newline
|
||||
Line <35> bracketo [
|
||||
Line <35> name Bob
|
||||
Line <35> colon :
|
||||
Line <35> name char
|
||||
Line <35> bracketc ]
|
||||
Line <35> newline
|
||||
Line <35> newline
|
||||
Line <36> newline
|
||||
Line <37> newline
|
||||
Line <38> newline
|
||||
Line <39> name unknown
|
||||
Line <39> equal =
|
||||
Line <39> string Some Random Guy
|
||||
Line <39> newline
|
||||
Line <39> newline
|
||||
Line <40> name age
|
||||
Line <40> equal =
|
||||
Line <40> number 0.24
|
||||
Line <40> newline
|
||||
Line <40> newline
|
||||
Line <41> name money
|
||||
Line <41> equal =
|
||||
Line <41> number 100
|
||||
Line <41> newline
|
||||
Line <41> newline
|
||||
Line <42> name excited
|
||||
Line <42> colon :
|
||||
Line <42> string path/to/file
|
||||
Line <42> newline
|
||||
Line <42> newline
|
||||
Line <43> newline
|
||||
Line <43> newline
|
||||
Line <44> bracketo [
|
||||
Line <44> name test1
|
||||
Line <44> colon :
|
||||
Line <44> name function
|
||||
Line <44> parao (
|
||||
Line <44> parac )
|
||||
Line <44> bracketc ]
|
||||
Line <44> newline
|
||||
Line <44> newline
|
||||
Line <45> string Inside a function!
|
||||
Line <45> newline
|
||||
Line <45> newline
|
||||
Line <46> newline
|
||||
Line <47> newline
|
||||
Line <48> newline
|
||||
Line <48> newline
|
||||
Line <49> bracketo [
|
||||
Line <49> name newblock
|
||||
Line <49> colon :
|
||||
Line <49> name function
|
||||
Line <49> parao (
|
||||
Line <49> name a
|
||||
Line <49> seperator ,
|
||||
Line <49> name b
|
||||
Line <49> seperator ,
|
||||
Line <49> name c
|
||||
Line <49> parac )
|
||||
Line <49> bracketc ]
|
||||
Line <49> newline
|
||||
Line <49> newline
|
||||
Line <50> string Func Arguments: a = `a`, b = `b`, c = `c`
|
||||
Line <50> newline
|
||||
Line <50> newline
|
||||
Line <51> string Time to return
|
||||
Line <51> newline
|
||||
Line <51> newline
|
||||
Line <52> ret
|
||||
Line <52> name a
|
||||
Line <52> plus +
|
||||
Line <52> name b
|
||||
Line <52> plus +
|
||||
Line <52> name c
|
||||
Line <52> newline
|
||||
Line <52> newline
|
||||
Line <52> eof
|
||||
Line <1> newline
|
||||
Line <1> newline
|
||||
Line <1> bracketo [
|
||||
Line <1> name default
|
||||
Line <1> colon :
|
||||
Line <1> name char
|
||||
Line <1> bracketc ]
|
||||
Line <1> newline
|
||||
Line <1> newline
|
||||
Line <2> newline
|
||||
Line <3> name money
|
||||
Line <3> equal =
|
||||
Line <3> number 0
|
||||
Line <3> newline
|
||||
Line <3> newline
|
||||
Line <4> name test
|
||||
Line <4> equal =
|
||||
Line <4> nil nil
|
||||
Line <4> newline
|
||||
Line <4> newline
|
||||
Line <5> newline
|
||||
Line <5> newline
|
||||
Line <6> bracketo [
|
||||
Line <6> name Ryan
|
||||
Line <6> colon :
|
||||
Line <6> name char
|
||||
Line <6> bracketc ]
|
||||
Line <6> newline
|
||||
Line <6> newline
|
||||
Line <7> name age
|
||||
Line <7> equal =
|
||||
Line <7> number 21
|
||||
Line <7> newline
|
||||
Line <7> newline
|
||||
Line <8> name money
|
||||
Line <8> equal =
|
||||
Line <8> number 1000
|
||||
Line <8> newline
|
||||
Line <8> newline
|
||||
Line <9> name lname
|
||||
Line <9> equal =
|
||||
Line <9> string Ward
|
||||
Line <9> newline
|
||||
Line <9> newline
|
||||
Line <10> name known
|
||||
Line <10> equal =
|
||||
Line <10> true true
|
||||
Line <10> newline
|
||||
Line <10> newline
|
||||
Line <11> newline
|
||||
Line <12> name calm
|
||||
Line <12> colon :
|
||||
Line <12> string ./path/to/file
|
||||
Line <12> newline
|
||||
Line <12> newline
|
||||
Line <13> name excited
|
||||
Line <13> colon :
|
||||
Line <13> string ./path/to/file
|
||||
Line <13> newline
|
||||
Line <13> newline
|
||||
Line <14> newline
|
||||
Line <14> newline
|
||||
Line <15> bracketo [
|
||||
Line <15> name step
|
||||
Line <15> colon :
|
||||
Line <15> name function
|
||||
Line <15> parao (
|
||||
Line <15> name a
|
||||
Line <15> seperator ,
|
||||
Line <15> name b
|
||||
Line <15> seperator ,
|
||||
Line <15> name c
|
||||
Line <15> parac )
|
||||
Line <15> bracketc ]
|
||||
Line <15> newline
|
||||
Line <15> newline
|
||||
Line <16> string Testing...
|
||||
Line <16> newline
|
||||
Line <17> name d
|
||||
Line <17> equal =
|
||||
Line <17> parao (
|
||||
Line <17> number 100
|
||||
Line <17> plus +
|
||||
Line <17> name b
|
||||
Line <17> parac )
|
||||
Line <17> divide /
|
||||
Line <17> name c
|
||||
Line <17> newline
|
||||
Line <17> newline
|
||||
Line <18> name e
|
||||
Line <18> equal =
|
||||
Line <18> string somestring
|
||||
Line <18> newline
|
||||
Line <18> newline
|
||||
Line <19> name e
|
||||
Line <19> equal =
|
||||
Line <19> nil nil
|
||||
Line <19> newline
|
||||
Line <19> newline
|
||||
Line <20> name g
|
||||
Line <20> equal =
|
||||
Line <20> false false
|
||||
Line <20> newline
|
||||
Line <20> newline
|
||||
Line <21> ret
|
||||
Line <21> name d
|
||||
Line <21> newline
|
||||
Line <21> newline
|
||||
Line <22> newline
|
||||
Line <22> newline
|
||||
Line <23> bracketo [
|
||||
Line <23> name inv
|
||||
Line <23> colon :
|
||||
Line <23> name env
|
||||
Line <23> bracketc ]
|
||||
Line <23> newline
|
||||
Line <23> newline
|
||||
Line <24> name slot1
|
||||
Line <24> equal =
|
||||
Line <24> string S1
|
||||
Line <24> newline
|
||||
Line <24> newline
|
||||
Line <25> name slot2
|
||||
Line <25> equal =
|
||||
Line <25> string S2
|
||||
Line <25> newline
|
||||
Line <25> newline
|
||||
Line <26> name slot3
|
||||
Line <26> equal =
|
||||
Line <26> string S3
|
||||
Line <26> newline
|
||||
Line <26> newline
|
||||
Line <27> name slot4
|
||||
Line <27> equal =
|
||||
Line <27> string S4
|
||||
Line <27> newline
|
||||
Line <27> newline
|
||||
Line <28> name slot5
|
||||
Line <28> equal =
|
||||
Line <28> string S5
|
||||
Line <28> newline
|
||||
Line <28> newline
|
||||
Line <29> name slot6
|
||||
Line <29> equal =
|
||||
Line <29> string S6
|
||||
Line <29> newline
|
||||
Line <29> newline
|
||||
Line <30> name slot7
|
||||
Line <30> equal =
|
||||
Line <30> string S7
|
||||
Line <30> newline
|
||||
Line <30> newline
|
||||
Line <31> name slot8
|
||||
Line <31> equal =
|
||||
Line <31> string S8
|
||||
Line <31> newline
|
||||
Line <31> newline
|
||||
Line <31> eof
|
||||
|
||||
@ -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];
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
};
|
||||
}
|
||||
@ -1,5 +1,3 @@
|
||||
enable tests
|
||||
disable hello
|
||||
[default:char]
|
||||
// The default stats for all characters.
|
||||
money = 0
|
||||
|
||||
13
DMS/memory.cpp
Normal file
13
DMS/memory.cpp
Normal 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
14
DMS/memory.h
Normal 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;
|
||||
};
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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("");
|
||||
}
|
||||
}
|
||||
30
DMS/test.dms
30
DMS/test.dms
@ -5,15 +5,32 @@ enable forseelabels
|
||||
enable savestate
|
||||
disable fullname
|
||||
//enable leaking
|
||||
enable debugging
|
||||
//enable debugging
|
||||
loadfile "loadtest.dms"
|
||||
version 0.2
|
||||
using extendedDefine
|
||||
|
||||
[main]
|
||||
"Time to test function calls!"
|
||||
val = newblock(1,2,3)
|
||||
"val = `val`"
|
||||
Ryan: "Hello `Bob`, how are you doing?"
|
||||
Bob: "Hi `Ryan`, I'm good."
|
||||
a = 1000
|
||||
test = invokeTest("Running external code!");
|
||||
"Loop Test... `test`"
|
||||
choice "Pick one" {
|
||||
"this" goto "this"
|
||||
"test2" tryme(true)
|
||||
"that" goto "that"
|
||||
"test" test(1,2,3)
|
||||
}
|
||||
::this::
|
||||
"At \"this\""
|
||||
goto "loop"
|
||||
::that::
|
||||
"At \"that\""
|
||||
::loop::
|
||||
a = a + 1
|
||||
"a = `a`"
|
||||
goto "loop"
|
||||
|
||||
[Bob:char]
|
||||
//fname = "Bob"
|
||||
@ -24,6 +41,11 @@ using extendedDefine
|
||||
money = 100
|
||||
excited: "path/to/file"
|
||||
|
||||
[test1:function()]
|
||||
"Inside a function!"
|
||||
//val = newblock(1,2,3)
|
||||
//"val = `val`"
|
||||
|
||||
[newblock:function(a,b,c)]
|
||||
"Func Arguments: a = `a`, b = `b`, c = `c`"
|
||||
"Time to return"
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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>
|
||||
|
||||
457
DMS/value.cpp
457
DMS/value.cpp
@ -2,42 +2,211 @@
|
||||
#include "dms_state.h"
|
||||
#include "utils.h"
|
||||
namespace dms {
|
||||
const std::string datatype[] = { "escape","nil", "number", "boolean", "env", "string", "custom", "variable", "block" };
|
||||
std::vector<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());
|
||||
}
|
||||
else if (type == datatypes::boolean) {
|
||||
newVal->b = buildBool(b->getValue());
|
||||
}
|
||||
else if (type == datatypes::number) {
|
||||
newVal->n = buildNumber(n->getValue());
|
||||
}
|
||||
else if (type == datatypes::nil) {
|
||||
delete newVal;
|
||||
return buildNil();
|
||||
}
|
||||
return newVal;
|
||||
value::value(char const* str, datatypes t) {
|
||||
type = t;
|
||||
s = buildString(str);
|
||||
}
|
||||
value* value::resolve(dms_state* state) {
|
||||
if (type == datatypes::variable && this!=(*state->getMem())[this->s->getValue()]) {
|
||||
return (*state->getMem())[s->getValue()]->resolve(state); // Variable types return the value
|
||||
}
|
||||
return this;
|
||||
value::value(char const* str) {
|
||||
type = datatypes::string;
|
||||
s = buildString(str);
|
||||
}
|
||||
void dms_args::push(value* val) {
|
||||
value::value(std::string str) {
|
||||
type = datatypes::string;
|
||||
s = buildString(str);
|
||||
}
|
||||
value::value(std::string str,datatypes t) {
|
||||
type = t;
|
||||
s = buildString(str);
|
||||
}
|
||||
value::value(double d) {
|
||||
type = datatypes::number;
|
||||
n = d;
|
||||
}
|
||||
value::value(int d) {
|
||||
type = datatypes::number;
|
||||
n = d;
|
||||
}
|
||||
value::value(bool bo) {
|
||||
type = datatypes::boolean;
|
||||
b = bo;
|
||||
}
|
||||
value::~value() {
|
||||
nuke();
|
||||
}
|
||||
size_t count = 0;
|
||||
value::value(datatypes t) : value() {
|
||||
if (t == datatypes::variable) {
|
||||
set(buildString(utils::concat("$",++count)));
|
||||
}
|
||||
type = t;
|
||||
}
|
||||
value::value(const value& other) {
|
||||
if (this != &other) {
|
||||
type = other.type;
|
||||
switch (other.type) {
|
||||
case datatypes::block:
|
||||
s = buildString(other.s->val);
|
||||
break;
|
||||
case datatypes::boolean:
|
||||
b = buildBool(other.b);
|
||||
break;
|
||||
case datatypes::custom:
|
||||
// Handle this later
|
||||
break;
|
||||
case datatypes::env:
|
||||
// Handle this later
|
||||
break;
|
||||
case datatypes::escape:
|
||||
s = buildString(other.s->val);
|
||||
break;
|
||||
case datatypes::nil:
|
||||
// No need to do anything
|
||||
break;
|
||||
case datatypes::number:
|
||||
n = other.n;
|
||||
break;
|
||||
case datatypes::string:
|
||||
s = buildString(other.s->val);
|
||||
break;
|
||||
case datatypes::variable:
|
||||
s = buildString(other.s->val);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
value& value::operator=(value& other) {
|
||||
if (this != &other) {
|
||||
nuke(); // Delete it all
|
||||
type = other.type;
|
||||
switch (other.type) {
|
||||
case datatypes::block:
|
||||
s = buildString(other.s->val);
|
||||
break;
|
||||
case datatypes::boolean:
|
||||
b = other.b;
|
||||
break;
|
||||
case datatypes::custom:
|
||||
// Handle this later
|
||||
break;
|
||||
case datatypes::env:
|
||||
// Handle this later
|
||||
break;
|
||||
case datatypes::escape:
|
||||
s = buildString(other.s->val);
|
||||
break;
|
||||
case datatypes::nil:
|
||||
// No need to do anything
|
||||
break;
|
||||
case datatypes::number:
|
||||
n = other.n;
|
||||
break;
|
||||
case datatypes::string:
|
||||
s = buildString(other.s->val);
|
||||
break;
|
||||
case datatypes::variable:
|
||||
s = buildString(other.s->val);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//other.nuke();
|
||||
}
|
||||
// by convention, always return *this
|
||||
return *this;
|
||||
}
|
||||
bool value::isNil() {
|
||||
return type == datatypes::nil;
|
||||
}
|
||||
value& value::operator=(const value& other) {
|
||||
if (this != &other) {
|
||||
nuke();
|
||||
type = other.type;
|
||||
switch (other.type) {
|
||||
case datatypes::block:
|
||||
s = buildString(other.s->val);
|
||||
break;
|
||||
case datatypes::boolean:
|
||||
b = other.b;
|
||||
break;
|
||||
case datatypes::custom:
|
||||
// Handle this later
|
||||
break;
|
||||
case datatypes::env:
|
||||
// Handle this later
|
||||
break;
|
||||
case datatypes::escape:
|
||||
s = buildString(other.s->val);
|
||||
break;
|
||||
case datatypes::nil:
|
||||
// No need to do anything
|
||||
break;
|
||||
case datatypes::number:
|
||||
n = other.n;
|
||||
break;
|
||||
case datatypes::string:
|
||||
s = buildString(other.s->val);
|
||||
break;
|
||||
case datatypes::variable:
|
||||
s = buildString(other.s->val);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// by convention, always return *this
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const value& lhs, const value& rhs) {
|
||||
return lhs.getPrintable() == rhs.getPrintable();
|
||||
}
|
||||
value operator+(const value& lhs, const value& rhs) {
|
||||
if (lhs.type == datatypes::number && rhs.type == datatypes::number) {
|
||||
return value(lhs.n + rhs.n);
|
||||
}
|
||||
else {
|
||||
return lhs.getPrintable() + rhs.getPrintable();
|
||||
}
|
||||
}
|
||||
value operator-(const value& lhs, const value& rhs) {
|
||||
if (lhs.type == datatypes::number && rhs.type == datatypes::number) {
|
||||
return value(lhs.n - rhs.n);
|
||||
}
|
||||
else {
|
||||
return value(datatypes::error);
|
||||
}
|
||||
}
|
||||
value operator/(const value& lhs, const value& rhs) {
|
||||
if (lhs.type == datatypes::number && rhs.type == datatypes::number) {
|
||||
return value(lhs.n / rhs.n);
|
||||
}
|
||||
else {
|
||||
return value(datatypes::error);
|
||||
}
|
||||
}
|
||||
value operator*(const value& lhs, const value& rhs) {
|
||||
if (lhs.type == datatypes::number && rhs.type == datatypes::number) {
|
||||
return value(lhs.n * rhs.n);
|
||||
}
|
||||
else {
|
||||
return value(datatypes::error);
|
||||
}
|
||||
}
|
||||
bool operator!=(const value& lhs, const value& rhs) {
|
||||
return !(lhs.getPrintable() == rhs.getPrintable());
|
||||
}
|
||||
value value::resolve(dms_state* state) {
|
||||
if (type == datatypes::variable && (*this)!=(*state->getMem())[getPrintable()]) {
|
||||
return (*state->getMem())[getPrintable()].resolve(state);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
void dms_args::push(value val) {
|
||||
args.push_back(val);
|
||||
}
|
||||
size_t dms_args::size() {
|
||||
@ -49,7 +218,7 @@ namespace dms {
|
||||
std::stringstream ind;
|
||||
bool varStart = false;
|
||||
bool indStart = false;
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
for (size_t i = 0; i < val.size(); i++) {
|
||||
if (indStart && val[i] == '`') {
|
||||
std::string lookup = var.str();
|
||||
std::string index = ind.str();
|
||||
@ -60,21 +229,21 @@ namespace dms {
|
||||
varStart = false;
|
||||
indStart = false;
|
||||
if (state->getMem()->count(lookup)) {
|
||||
value* v = (*state->getMem())[lookup];
|
||||
if (v->type == datatypes::block) {
|
||||
if ((state->chunks.count(v->s->getValue()) && state->chunks[v->s->getValue()]->type == blocktype::bt_character) && state->getCharacter(v->s->getValue())!=nullptr) {
|
||||
character* cha = state->getCharacter(v->s->getValue());
|
||||
value v = (*state->getMem())[lookup];
|
||||
if (v.type == datatypes::block) {
|
||||
if (state->getCharacter(v.getPrintable()) != nullptr) {
|
||||
character* cha = state->getCharacter(v.getPrintable());
|
||||
if (cha->values.count(index)) {
|
||||
temp << cha->values[index]->getPrintable();
|
||||
temp << cha->values[index].getPrintable();
|
||||
}
|
||||
else {
|
||||
temp << cha->getName();
|
||||
}
|
||||
}
|
||||
else if ((state->chunks.count(v->s->getValue()) && state->chunks[v->s->getValue()]->type == blocktype::bt_env) && state->getEnvironment(v->s->getValue()) != nullptr) {
|
||||
enviroment* env = state->getEnvironment(v->s->getValue());
|
||||
else if (state->getEnvironment(v.getPrintable())!=nullptr) {
|
||||
enviroment* env = state->getEnvironment(v.getPrintable());
|
||||
if (env->values.count(index)) {
|
||||
temp << env->values[index]->getPrintable();
|
||||
temp << env->values[index].getPrintable();
|
||||
}
|
||||
else {
|
||||
temp << env;
|
||||
@ -84,14 +253,14 @@ namespace dms {
|
||||
temp << "nil";
|
||||
}
|
||||
}
|
||||
else if (v->resolve(state)->type == datatypes::env) {
|
||||
if(v->resolve(state)->e->ipart.size()> std::stoi(index))
|
||||
temp << v->resolve(state)->e->ipart[std::stoi(index)-1]->getPrintable();
|
||||
else if (v.resolve(state).type == datatypes::env) {
|
||||
if(v.resolve(state).e->ipart.size()> std::stoi(index))
|
||||
temp << v.resolve(state).e->ipart[std::stoi(index)-(int64_t)1].getPrintable();
|
||||
else
|
||||
temp << "nil";
|
||||
}
|
||||
else {
|
||||
temp << v->resolve(state)->getPrintable();
|
||||
temp << v.resolve(state).getPrintable();
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -121,17 +290,17 @@ namespace dms {
|
||||
var.clear();
|
||||
varStart = false;
|
||||
if (state->getMem()->count(lookup)) {
|
||||
value* v = (*state->getMem())[lookup];
|
||||
if (v->type == datatypes::block) {
|
||||
if (state->getCharacter(v->s->getValue())) {
|
||||
temp << state->characters[v->s->getValue()]->getName();
|
||||
value v = (*state->getMem())[lookup];
|
||||
if (v.type == datatypes::block) {
|
||||
if (state->getCharacter(v.s->getValue())) {
|
||||
temp << state->characters[v.s->getValue()]->getName();
|
||||
}
|
||||
else {
|
||||
temp << "nil";
|
||||
}
|
||||
}
|
||||
else {
|
||||
temp << v->resolve(state)->getPrintable();
|
||||
temp << v.resolve(state).getPrintable();
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -163,13 +332,13 @@ namespace dms {
|
||||
out << s->getValue();
|
||||
}
|
||||
else if (type == number) {
|
||||
out << n->getValue();
|
||||
out << n;
|
||||
}
|
||||
else if (type == nil) {
|
||||
out << "nil";
|
||||
}
|
||||
else if (type == boolean) {
|
||||
if (b->getValue())
|
||||
if (b)
|
||||
out << "true";
|
||||
else
|
||||
out << "false";
|
||||
@ -189,112 +358,94 @@ namespace dms {
|
||||
return out.str();
|
||||
}
|
||||
dms_string* buildString(std::string str) {
|
||||
size_t len = str.length();
|
||||
uint8_t* arr = new uint8_t[len];
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
arr[i] = str.at(i);
|
||||
}
|
||||
dms_string* dms_str = new dms_string{ str.length(), arr };
|
||||
std::stringstream newstr;
|
||||
for (int i = 0; i < str.size(); i++)
|
||||
newstr << str[i];
|
||||
dms_string* dms_str = new dms_string{ newstr.str() };
|
||||
return dms_str;
|
||||
}
|
||||
dms_boolean* buildBool(bool b) {
|
||||
dms_boolean* dms_bool = new dms_boolean{b};
|
||||
return dms_bool;
|
||||
}
|
||||
dms_number* buildNumber(double num) {
|
||||
dms_number* dms_num = new dms_number{ num };
|
||||
return dms_num;
|
||||
return new dms_boolean{b};
|
||||
}
|
||||
std::string value::toString() const {
|
||||
std::stringstream temp;
|
||||
temp << this;
|
||||
return temp.str();
|
||||
}
|
||||
value* buildValue() {
|
||||
return new value;
|
||||
}
|
||||
value* buildNil() {
|
||||
return new value;
|
||||
}
|
||||
size_t count = 0;
|
||||
value* buildVariable() {
|
||||
count++;
|
||||
std::stringstream str;
|
||||
str << "$" << count;
|
||||
std::string val = str.str();
|
||||
return buildVariable(val);
|
||||
}
|
||||
value* buildBlock(std::string str) {
|
||||
value* val = new value{};
|
||||
val->set(buildString(str));
|
||||
val->type = block;
|
||||
return val;
|
||||
}
|
||||
value* buildVariable(std::string str) {
|
||||
value* val = new value{};
|
||||
val->set(buildString(str));
|
||||
val->type = variable;
|
||||
return val;
|
||||
}
|
||||
value* buildValue(char const* s) {
|
||||
value* val = new value{};
|
||||
val->set(buildString(s));
|
||||
return val;
|
||||
}
|
||||
value* buildValue(std::string str) {
|
||||
value* val = new value{};
|
||||
val->set(buildString(str));
|
||||
return val;
|
||||
}
|
||||
value* buildValue(double dbl) {
|
||||
value* val = new value{};
|
||||
val->set(buildNumber(dbl));
|
||||
return val;
|
||||
}
|
||||
value* buildValue(int i) {
|
||||
value* val = new value{};
|
||||
val->set(buildNumber((double)i));
|
||||
return val;
|
||||
}
|
||||
value* buildValue(bool b) {
|
||||
value* val = new value{};
|
||||
val->set(buildBool(b));
|
||||
return val;
|
||||
}
|
||||
// Compile time
|
||||
void value::nuke() {
|
||||
if (type == datatypes::custom)
|
||||
c->_del();
|
||||
delete[] s;
|
||||
delete[] b;
|
||||
delete[] n;
|
||||
delete[] e;
|
||||
delete[] c;
|
||||
delete s;
|
||||
delete e;
|
||||
delete c;
|
||||
s = nullptr;
|
||||
b = nullptr;
|
||||
n = nullptr;
|
||||
e = nullptr;
|
||||
c = nullptr;
|
||||
}
|
||||
std::ostream& operator << (std::ostream& out, const value& c) {
|
||||
if (c.type == string) {
|
||||
out << (char)c.type << c.s->getValue() << (char)0;
|
||||
}
|
||||
else if (c.type == number) {
|
||||
out << (char)c.type << c.n;
|
||||
}
|
||||
else if (c.type == nil) {
|
||||
out << (char)c.type << "nil";
|
||||
}
|
||||
else if (c.type == boolean) {
|
||||
if(c.b)
|
||||
out << (char)c.type << "true";
|
||||
else
|
||||
out << (char)c.type << "false";
|
||||
}
|
||||
else if (c.type == env) {
|
||||
out << (char)c.type << "Env: " << c;
|
||||
}
|
||||
else if (c.type == custom) {
|
||||
out << (char)c.type << "Custom Data: " << c;
|
||||
}
|
||||
else if (c.type == block) {
|
||||
out << (char)c.type << c.s->getValue();
|
||||
}
|
||||
else if (c.type == datatypes::variable) {
|
||||
out << (char)c.type << c.s->getValue(); // Do the lookup
|
||||
}
|
||||
return out;
|
||||
};
|
||||
// Fixed issue with memory not properly being cleaned up
|
||||
bool value::typeMatch(const value* o) const {
|
||||
return type == o->type;
|
||||
}
|
||||
void value::set(value* val) {
|
||||
if (type == datatypes::number) {
|
||||
n = val->n;
|
||||
}
|
||||
else if (type == datatypes::string || type == datatypes::block || type == datatypes::variable) {
|
||||
s->val = val->s->val;
|
||||
}
|
||||
else if (type == datatypes::boolean) {
|
||||
b = val->b;
|
||||
}
|
||||
else { // Handle custom and env
|
||||
return;
|
||||
}
|
||||
type = val->type;
|
||||
}
|
||||
void value::set(dms_string* str) {
|
||||
nuke();
|
||||
s = str;
|
||||
type = string;
|
||||
}
|
||||
void value::set(dms_boolean* bo) {
|
||||
void value::set(bool bo) {
|
||||
nuke();
|
||||
b = bo;
|
||||
type = boolean;
|
||||
}
|
||||
void value::set(dms_number* num) {
|
||||
void value::set(double num) {
|
||||
nuke();
|
||||
n = num;
|
||||
type = number;
|
||||
}
|
||||
void dms::value::set(dms_env* en) {
|
||||
void dms::value::set(dms_list* en) {
|
||||
nuke();
|
||||
e = en;
|
||||
type = env;
|
||||
@ -310,35 +461,45 @@ namespace dms {
|
||||
type = nil;
|
||||
}
|
||||
std::string dms_string::getValue() {
|
||||
std::stringstream temp;
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
temp << val[i];
|
||||
}
|
||||
return temp.str();
|
||||
return val;
|
||||
}
|
||||
void dms_env::pushValue(value* val) {
|
||||
void dms_list::pushValue(value val) {
|
||||
ipart.push_back(val);
|
||||
}
|
||||
void dms_env::pushValue(value* ind, value* val) {
|
||||
if (val->type == nil) {
|
||||
hpart[ind->toString()]->nuke();
|
||||
hpart.erase(ind->toString());
|
||||
count--;
|
||||
value dms_list::getValue(value ind) {
|
||||
if (ind.type == number) {
|
||||
return ipart.at((int)ind.n);
|
||||
}
|
||||
else {
|
||||
hpart.insert_or_assign(ind->toString(), val);
|
||||
count++;
|
||||
return new value();
|
||||
}
|
||||
}
|
||||
value* dms_env::getValue(value* ind) {
|
||||
if (ind->type == number) {
|
||||
return ipart.at((int)ind->n->getValue());
|
||||
std::ostream& operator << (std::ostream& out, const dms_args& c) {
|
||||
for (size_t i = 0; i < c.args.size(); i++) {
|
||||
if (i == c.args.size() - 1)
|
||||
out << c.args[i];
|
||||
else
|
||||
out << c.args[i] << ", ";
|
||||
}
|
||||
else if (ind->type == number) {
|
||||
return new value{}; // Return a nil value
|
||||
}
|
||||
else {
|
||||
return hpart.at(ind->toString());
|
||||
return out;
|
||||
}
|
||||
std::string dms_args::toString() {
|
||||
std::stringstream str;
|
||||
for (size_t i = 0; i < args.size(); i++) {
|
||||
str << args[i];
|
||||
}
|
||||
return str.str();
|
||||
}
|
||||
std::ostream& operator << (std::ostream& out, const dms_string& c) {
|
||||
out << c.val;
|
||||
return out;
|
||||
}
|
||||
std::ostream& operator << (std::ostream& out, const dms_boolean& c) {
|
||||
out << c.val;
|
||||
return out;
|
||||
}
|
||||
std::ostream& operator << (std::ostream& out, const dms_number& c) {
|
||||
out << c.val;
|
||||
return out;
|
||||
}
|
||||
}
|
||||
161
DMS/value.h
161
DMS/value.h
@ -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();
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user