Simple list implementation

This commit is contained in:
2025-10-02 14:44:48 +10:00
parent d7123aff1e
commit cf85205ff0
12 changed files with 155 additions and 26 deletions

53
src/datatypes/lists.cpp Normal file
View File

@@ -0,0 +1,53 @@
#include "lists.h"
// Helper to trim whitespace from the start and end of a string
std::string trim(const std::string& str) {
size_t first = str.find_first_not_of(" \t\n\r");
if (std::string::npos == first) {
return str;
}
size_t last = str.find_last_not_of(" \t\n\r");
return str.substr(first, (last - first + 1));
}
std::vector<Value> parse_list_content(const std::string& content) {
std::vector<Value> items;
std::string current_item;
bool in_string = false;
int nested_level = 0;
for (char c : content) {
if (c == '"') {
in_string = !in_string;
}
if (c == ',' && !in_string && nested_level == 0) {
// End of an item
std::string trimmed = trim(current_item);
if (!trimmed.empty()) {
if (trimmed.front() == '"' && trimmed.back() == '"') {
items.push_back(Value(trimmed.substr(1, trimmed.length() - 2)));
} else {
items.push_back(Value(trimmed));
}
}
current_item.clear();
} else {
if (c == '[' || c == '(') nested_level++;
if (c == ']' || c == ')') nested_level--;
current_item += c;
}
}
// Last item
std::string trimmed = trim(current_item);
if (!trimmed.empty()) {
if (trimmed.front() == '"' && trimmed.back() == '"') {
items.push_back(Value(trimmed.substr(1, trimmed.length() - 2)));
} else {
items.push_back(Value(trimmed));
}
}
return items;
}

8
src/datatypes/lists.h Normal file
View File

@@ -0,0 +1,8 @@
#pragma once
#include <vector>
#include <string>
#include "../defs/defs.h"
std::vector<Value> parse_list_content(const std::string& content);
std::string trim(const std::string& str);

View File

@@ -4,6 +4,7 @@
#include <string>
#include <memory>
#include <utility>
#include "../datatypes/lists.h"
InstructionType strToInstructionType(std::string in) {
if (in == "println") return InstructionType::Println;
@@ -16,6 +17,7 @@ InstructionType strToInstructionType(std::string in) {
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;
}
@@ -69,7 +71,9 @@ Value::Value() : valtype(ValueType::Real) {}
Value::Value(InstructionGroup instgroup) : valtype(ValueType::InstructionGroup), instructionGroup(instgroup) {};
Value::Value(const Value& other) : valtype(other.valtype), real(other.real), varName(other.varName), instructionGroup(other.instructionGroup) {
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);
}
@@ -86,6 +90,7 @@ Value& Value::operator=(const Value& other) {
real = other.real;
varName = other.varName;
instructionGroup = other.instructionGroup;
list = other.list;
if (other.processed) {
processed = std::make_unique<Instruction>(*other.processed);
} else {
@@ -113,6 +118,14 @@ std::string Value::toString() const {
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;
@@ -161,6 +174,8 @@ std::vector<Value> split(std::string line) {
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] == '$') {
@@ -170,8 +185,8 @@ std::vector<Value> split(std::string line) {
}
buf = "";
} else if (chr == '(' || chr == '[') {
brackets += 1;
if (brackets == 1) {
if (brackets == 0) {
bracket_type = chr;
if (!buf.empty()) {
splitvals.push_back(Value(buf));
buf = "";
@@ -179,13 +194,20 @@ std::vector<Value> split(std::string line) {
} else {
buf += chr;
}
brackets++;
} else if (chr == ')' || chr == ']') {
brackets -= 1;
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;

View File

@@ -6,11 +6,11 @@
enum class InstructionType {
None, Print, Println, Math, Let, Variable, Exit, If, While, Input, Compare, Function, Return
None, Print, Println, Math, Let, Variable, Exit, If, While, Input, Compare, Function, Return, Concat
};
enum class ValueType {
Real, Processed, Variable, InstructionGroup
Real, Processed, Variable, InstructionGroup, List, Map
};
struct Instruction;
@@ -33,12 +33,14 @@ struct Value {
std::unique_ptr<Instruction> processed;
std::string real = "";
InstructionGroup instructionGroup;
std::vector<Value> list;
bool is_return = false;
std::string toString() const;
Varname varName = Varname();
Value(std::string stringval);
Value(Instruction instval);
Value(InstructionGroup instgroup);
Value(std::vector<Value> listval);
Value(Varname var);
Value();
Value(const Value& other);
@@ -58,4 +60,5 @@ struct Instruction {
std::vector<Value> split(std::string in);
InstructionType strToInstructionType(std::string in);
std::string trim(const std::string& str);
extern bool inReplMode;

View File

@@ -13,6 +13,7 @@
#include "../modules/compare/compare.h"
#include "../modules/input/input.h"
#include "../modules/function/function.h"
#include "../modules/concat/concat.h"
Value execute(Instruction inst) {
// Special cases that need to manage their own argument evaluation
@@ -68,6 +69,9 @@ Value execute(Instruction inst) {
case InstructionType::Exit:
return modules::exit(inst.args);
break;
case InstructionType::Concat:
return modules::concat(inst.args);
break;
case InstructionType::Variable: {
if (!inst.args.empty()) {
const std::string& name = inst.args[0].real;

View File

@@ -0,0 +1,16 @@
#include "concat.h"
#include "../../defs/defs.h"
#include "../../error/error.h"
#include <vector>
Value modules::concat(std::vector<Value> args) {
std::string buf;
for (Value val : args) {
if (val.valtype == ValueType::Real) {
buf += val.real;
} else {
error("Can only concatenate real values");
}
}
return buf;
}

View File

@@ -0,0 +1,8 @@
#pragma once
#include "../../defs/defs.h"
#include <vector>
namespace modules {
Value concat(std::vector<Value> args);
}

View File

@@ -8,7 +8,22 @@
Value modules::print(std::vector<Value> values) {
for (Value value : values) {
if (value.valtype == ValueType::Real) {
std::cout << value.real << " ";
std::cout << value.real;
if (values.size() > 1) {
std::cout << " ";
}
} else if (value.valtype == ValueType::List) {
std::cout << "[";
bool afterfirst = false;
for (Value val : value.list) {
if (afterfirst) {
std::cout << ", ";
} else {
afterfirst = true;
}
print({val});
}
std::cout << "]";
} else {
error("FIXME unprocessed processed (in print module)");
}

View File

@@ -1,18 +1,12 @@
#include "println.h"
#include "../../defs/defs.h"
#include "../../error/error.h"
#include "../print/print.h"
#include <vector>
#include <iostream>
#include <string>
Value modules::println(std::vector<Value> values) {
for (Value value : values) {
if (value.valtype == ValueType::Real) {
std::cout << value.real << " ";
} else {
error("FIXME unprocessed processed (in println module)");
}
}
print(values);
std::cout << "\n";
return Value("");
}

View File

@@ -0,0 +1,8 @@
#include "split.h"
#include "../../defs/defs.h"
#include <vector>
#include <string>
Value modules::split(std::vector<Value> args) {
return Value("Work in progress!");
}

View File

@@ -0,0 +1,8 @@
#pragma once
#include "../../defs/defs.h"
#include <vector>
namespace modules {
Value split(std::vector<Value> args);
}

View File

@@ -3,16 +3,6 @@
#include <string>
#include <vector>
// Helper to trim whitespace
std::string trim(const std::string& str) {
size_t first = str.find_first_not_of(" \t\n\r");
if (std::string::npos == first) {
return str;
}
size_t last = str.find_last_not_of(" \t\n\r");
return str.substr(first, (last - first + 1));
}
std::vector<Instruction> parse(std::string program) {
std::vector<Instruction> instructions;
std::vector<std::string> lines;