Files
kyn/src/defs/defs.cpp

229 lines
6.9 KiB
C++

#include "defs.h"
#include "../error/error.h"
#include <vector>
#include <string>
#include <memory>
#include <utility>
#include "../datatypes/lists.h"
InstructionType strToInstructionType(std::string in) {
if (in == "println") return InstructionType::Println;
else if (in == "print") return InstructionType::Print;
else if (in == "math") return InstructionType::Math;
else if (in == "let") return InstructionType::Let;
else if (in == "exit") return InstructionType::Exit;
else if (in == "if") return InstructionType::If;
else if (in == "while") return InstructionType::While;
else if (in == "compare") return InstructionType::Compare;
else if (in == "input") return InstructionType::Input;
else if (in == "return") return InstructionType::Return;
else if (in == "concat") return InstructionType::Concat;
else return InstructionType::Variable;
}
Instruction::Instruction(std::vector<std::string> toks) {
if (!toks.empty()) {
// Get type of instruction from first token
instruction = strToInstructionType(toks[0]);
if (instruction == InstructionType::Variable) {
for (std::string tok : toks) {
args.push_back(Value(tok));
}
} else {
// The rest are the args, convert them to values first
for (size_t i = 1; i < toks.size(); i++) {
args.push_back(Value(toks[i]));
}
}
} else {
error("Empty tokens!");
}
}
Instruction::Instruction(std::vector<Value> toks) {
if (!toks.empty()) {
// Check type of value in first token, then compute token
if (toks[0].valtype == ValueType::Real) {
instruction = strToInstructionType(toks[0].real);
} else {
error("Instruction should be a real");
}
if (instruction == InstructionType::Variable) {
for (const auto& tok : toks) {
args.push_back(tok);
}
} else {
// The rest are the args
for (size_t i = 1; i < toks.size(); i++) {
args.push_back(toks[i]);
}
}
} else {
error("Empty tokens!");
}
}
Value::Value(std::string stringval) : valtype(ValueType::Real), real(stringval) {}
Value::Value(Instruction instval) : valtype(ValueType::Processed), processed(std::make_unique<Instruction>(std::move(instval))) {}
Value::Value() : valtype(ValueType::Real) {}
Value::Value(InstructionGroup instgroup) : valtype(ValueType::InstructionGroup), instructionGroup(instgroup) {};
Value::Value(std::vector<Value> listval) : valtype(ValueType::List), list(std::move(listval)) {}
Value::Value(const Value& other) : valtype(other.valtype), real(other.real), varName(other.varName), instructionGroup(other.instructionGroup), list(other.list) {
if (other.processed) {
processed = std::make_unique<Instruction>(*other.processed);
}
}
Value::Value(Varname varname) : valtype(ValueType::Variable), varName(varname) {}
Varname::Varname(std::string in) : key(in.substr(1)) {}
Varname::Varname() : key("") {}
Value& Value::operator=(const Value& other) {
if (this != &other) {
valtype = other.valtype;
real = other.real;
varName = other.varName;
instructionGroup = other.instructionGroup;
list = other.list;
if (other.processed) {
processed = std::make_unique<Instruction>(*other.processed);
} else {
processed.reset();
}
}
return *this;
}
std::string Value::toString() const {
std::string out = "Value(type: ";
switch (valtype) {
case ValueType::Real:
out += "Real, value: " + real + ")";
break;
case ValueType::Processed:
out += "Processed, value: ";
if (processed) {
out += processed->toString();
} else {
out += "null";
}
out += ")";
break;
case ValueType::InstructionGroup:
out += "InstructionGroup, contains " + std::to_string(instructionGroup.size()) + " instructions)";
break;
case ValueType::List: {
out += "List, items: [";
for (const auto& item : list) {
out += item.toString() + ", ";
}
out += "])";
break;
}
default:
out += "FIXME)";
break;
}
return out;
}
std::string Instruction::toString() const {
std::string out = "Instruction(type: ";
switch (instruction) {
case InstructionType::None:
out += "None";
break;
case InstructionType::Println:
out += "Println";
break;
case InstructionType::Math:
out += "Math";
break;
case InstructionType::Let:
out += "Let";
break;
case InstructionType::If:
out += "If";
break;
case InstructionType::Compare:
out += "Compare";
break;
case InstructionType::Input:
out += "Input";
break;
default:
out += "FIXME";
break;
}
out += ", args: [";
for (const auto& val : args) {
out += val.toString() + ", ";
}
out += "])";
return out;
}
std::vector<Value> split(std::string line) {
std::vector<Value> splitvals;
std::string buf;
bool instring = false;
int brackets = 0;
char bracket_type = 0;
for (char chr : line) {
if (chr == ' ' && !instring && brackets == 0 && !buf.empty()) {
if (buf[0] == '$') {
splitvals.push_back(Value(Varname(buf)));
} else {
splitvals.push_back(Value(buf));
}
buf = "";
} else if (chr == '(' || chr == '[') {
if (brackets == 0) {
bracket_type = chr;
if (!buf.empty()) {
splitvals.push_back(Value(buf));
buf = "";
}
} else {
buf += chr;
}
brackets++;
} else if (chr == ')' || chr == ']') {
brackets--;
if (brackets == 0) {
if (!buf.empty()) {
if (bracket_type == '(') {
splitvals.push_back(Value(Instruction(split(buf))));
} else {
splitvals.push_back(Value(parse_list_content(buf)));
}
buf = "";
}
} else {
buf += chr;
}
} else if (chr == '"') {
instring = !instring;
} else {
buf += chr;
}
}
if (!buf.empty()) {
if (buf[0] == '$') {
splitvals.push_back(Value(Varname(buf)));
} else {
splitvals.push_back(Value(buf));
}
}
return splitvals;
}
bool inReplMode = false;