309 lines
7.1 KiB
C++
309 lines
7.1 KiB
C++
#include "value.h"
|
|
#include "dms_state.h"
|
|
namespace dms {
|
|
const std::string datatype[] = { "escape","nil", "number", "boolean", "env", "string", "custom", "variable", "block" };
|
|
std::vector<value*> _VALUES;
|
|
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!
|
|
}
|
|
value* value::resolve(std::unordered_map<std::string, value*> memory) {
|
|
if (type == datatypes::variable) {
|
|
return memory[s->getValue()]->resolve(memory); // Variable types return the value
|
|
}
|
|
return this;
|
|
}
|
|
void dms_args::push(value* val) {
|
|
args.push_back(val);
|
|
}
|
|
std::string dms_string::getValue(dms_state* state) {
|
|
std::stringstream temp;
|
|
std::stringstream var;
|
|
std::stringstream ind;
|
|
bool varStart = false;
|
|
bool indStart = false;
|
|
for (size_t i = 0; i < length; i++) {
|
|
if (indStart && val[i] == '`') {
|
|
std::string lookup = var.str();
|
|
std::string index = ind.str();
|
|
var.str("");
|
|
var.clear();
|
|
ind.str("");
|
|
ind.clear();
|
|
varStart = false;
|
|
indStart = false;
|
|
if (state->memory.count(lookup)) {
|
|
value* v = state->memory[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());
|
|
if (cha->values.count(index)) {
|
|
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->getEnviroment(v->s->getValue()) != nullptr) {
|
|
enviroment* env = state->getEnviroment(v->s->getValue());
|
|
if (env->values.count(index)) {
|
|
temp << env->values[index]->getPrintable();
|
|
}
|
|
else {
|
|
temp << env;
|
|
}
|
|
}
|
|
else {
|
|
temp << "nil";
|
|
}
|
|
}
|
|
else {
|
|
temp << v->getPrintable();
|
|
}
|
|
}
|
|
else {
|
|
temp << "nil";
|
|
}
|
|
}
|
|
else if (indStart && val[i] == ':') {
|
|
state->push_error(errors::error{ errors::badtoken,"Cannot index more than once in a string injection!" });
|
|
varStart = false;
|
|
indStart = false;
|
|
var.str("");
|
|
var.clear();
|
|
ind.str("");
|
|
ind.clear();
|
|
return "";
|
|
}
|
|
else if (indStart) {
|
|
ind << val[i];
|
|
}
|
|
else if (val[i] == '`' && !varStart) {
|
|
varStart = true;
|
|
|
|
}
|
|
else if (val[i] == '`' && varStart) {
|
|
std::string lookup = var.str();
|
|
var.str("");
|
|
var.clear();
|
|
varStart = false;
|
|
if (state->memory.count(lookup)) {
|
|
value* v = state->memory[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->getPrintable();
|
|
}
|
|
}
|
|
else {
|
|
temp << "nil";
|
|
}
|
|
}
|
|
// A space is not allowed at all
|
|
else if (val[i] == ':' && varStart) {
|
|
indStart = true;
|
|
}
|
|
else if (val[i] == ' ' && varStart) {
|
|
temp << var.str();
|
|
varStart = false;
|
|
var.str("");
|
|
var.clear();
|
|
}
|
|
else if (varStart) {
|
|
var << val[i];
|
|
}
|
|
else {
|
|
temp << val[i];
|
|
}
|
|
}
|
|
return temp.str();
|
|
}
|
|
std::string value::getPrintable() const {
|
|
std::stringstream out;
|
|
if (type == string) {
|
|
out << s->getValue();
|
|
}
|
|
else if (type == number) {
|
|
out << n->getValue();
|
|
}
|
|
else if (type == nil) {
|
|
out << "nil";
|
|
}
|
|
else if (type == boolean) {
|
|
if (b->getValue())
|
|
out << "true";
|
|
else
|
|
out << "false";
|
|
}
|
|
else if (type == env) {
|
|
out << "Env: " << this;
|
|
}
|
|
else if (type == custom) {
|
|
out << "Custom Data: " << this;
|
|
}
|
|
else if (type == block) {
|
|
out << s->getValue();
|
|
}
|
|
else if (type == datatypes::variable) {
|
|
out << s->getValue(); // Do the lookup
|
|
}
|
|
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 };
|
|
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;
|
|
}
|
|
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(std::string str) {
|
|
value* val = new value{};
|
|
val->set(buildString(str));
|
|
return val;
|
|
}
|
|
value* buildValue(double dbl) {
|
|
value* val = new value{};
|
|
val->set(buildNumber(dbl));
|
|
return val;
|
|
}
|
|
value* buildValue(int i) {
|
|
value* val = new value{};
|
|
val->set(buildNumber((double)i));
|
|
return val;
|
|
}
|
|
value* buildValue(bool b) {
|
|
value* val = new value{};
|
|
val->set(buildBool(b));
|
|
return val;
|
|
}
|
|
void value::nuke() {
|
|
if (type == datatypes::custom)
|
|
c->_del();
|
|
delete[] s;
|
|
delete[] b;
|
|
delete[] n;
|
|
delete[] e;
|
|
delete[] c;
|
|
s = nullptr;
|
|
b = nullptr;
|
|
n = nullptr;
|
|
e = nullptr;
|
|
c = nullptr;
|
|
}
|
|
// Fixed issue with memory not properly being cleaned up
|
|
bool value::typeMatch(const value* o) const {
|
|
return type == o->type;
|
|
}
|
|
void value::set(dms_string* str) {
|
|
nuke();
|
|
s = str;
|
|
type = string;
|
|
}
|
|
void value::set(dms_boolean* bo) {
|
|
nuke();
|
|
b = bo;
|
|
type = boolean;
|
|
}
|
|
void value::set(dms_number* num) {
|
|
nuke();
|
|
n = num;
|
|
type = number;
|
|
}
|
|
void dms::value::set(dms_env* en) {
|
|
nuke();
|
|
e = en;
|
|
type = env;
|
|
}
|
|
void dms::value::set(dms_custom* cus) {
|
|
nuke();
|
|
c = cus;
|
|
c->_set(this);
|
|
type = custom;
|
|
}
|
|
void value::set() {
|
|
nuke();
|
|
type = nil;
|
|
}
|
|
std::string dms_string::getValue() {
|
|
std::stringstream temp;
|
|
for (size_t i = 0; i < length; i++) {
|
|
temp << val[i];
|
|
}
|
|
return temp.str();
|
|
}
|
|
void dms_env::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--;
|
|
}
|
|
else {
|
|
hpart.insert_or_assign(ind->toString(), val);
|
|
count++;
|
|
}
|
|
}
|
|
value* dms_env::getValue(value* ind) {
|
|
if (ind->type == number) {
|
|
return ipart.at((int)ind->n->getValue());
|
|
}
|
|
else if (ind->type == number) {
|
|
return new value{}; // Return a nil value
|
|
}
|
|
else {
|
|
return hpart.at(ind->toString());
|
|
}
|
|
}
|
|
} |