Structs (IN BETA)
This commit is contained in:
@@ -9,6 +9,7 @@
|
|||||||
namespace data {
|
namespace data {
|
||||||
std::vector<std::map<std::string, Value>> scopes;
|
std::vector<std::map<std::string, Value>> scopes;
|
||||||
std::map<std::string, Function> functions;
|
std::map<std::string, Function> functions;
|
||||||
|
std::map<std::string, Struct> structs;
|
||||||
|
|
||||||
void initScopes() {
|
void initScopes() {
|
||||||
scopes.clear();
|
scopes.clear();
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
namespace data {
|
namespace data {
|
||||||
extern std::vector<std::map<std::string, Value>> scopes;
|
extern std::vector<std::map<std::string, Value>> scopes;
|
||||||
extern std::map<std::string, Function> functions;
|
extern std::map<std::string, Function> functions;
|
||||||
|
extern std::map<std::string, Struct> structs;
|
||||||
void modifyValue(std::string key, Value value);
|
void modifyValue(std::string key, Value value);
|
||||||
Value getValue(std::string key);
|
Value getValue(std::string key);
|
||||||
void pushScope();
|
void pushScope();
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include "../datatypes/lists/lists.h"
|
#include "../datatypes/lists/lists.h"
|
||||||
#include "../utils/trim/trim.h"
|
|
||||||
|
|
||||||
InstructionType strToInstructionType(std::string in) {
|
InstructionType strToInstructionType(std::string in) {
|
||||||
if (in == "println") return InstructionType::Println;
|
if (in == "println") return InstructionType::Println;
|
||||||
@@ -21,6 +20,7 @@ InstructionType strToInstructionType(std::string in) {
|
|||||||
else if (in == "concat") return InstructionType::Concat;
|
else if (in == "concat") return InstructionType::Concat;
|
||||||
else if (in == "split") return InstructionType::Split;
|
else if (in == "split") return InstructionType::Split;
|
||||||
else if (in == "file") return InstructionType::File;
|
else if (in == "file") return InstructionType::File;
|
||||||
|
else if (in == "struct") return InstructionType::Struct;
|
||||||
else return InstructionType::Variable;
|
else return InstructionType::Variable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,7 +118,11 @@ Value::Value(InstructionGroup instgroup) : valtype(ValueType::InstructionGroup),
|
|||||||
|
|
||||||
Value::Value(std::vector<Value> listval) : valtype(ValueType::List), list(std::move(listval)) {}
|
Value::Value(std::vector<Value> listval) : valtype(ValueType::List), list(std::move(listval)) {}
|
||||||
|
|
||||||
Value::Value(const Value& other) : valtype(other.valtype), string_val(other.string_val), int_val(other.int_val), double_val(other.double_val), instructionGroup(other.instructionGroup), list(other.list), varName(other.varName) {
|
Value::Value(std::map<std::string, Value> mapval) : valtype(ValueType::Map), map(std::move(mapval)) {}
|
||||||
|
|
||||||
|
Value::Value(Function func) : fn_val(func) {};
|
||||||
|
|
||||||
|
Value::Value(const Value& other) : valtype(other.valtype), string_val(other.string_val), int_val(other.int_val), double_val(other.double_val), instructionGroup(other.instructionGroup), list(other.list), map(other.map), varName(other.varName), fn_val(other.fn_val) {
|
||||||
if (other.processed) {
|
if (other.processed) {
|
||||||
processed = std::make_unique<Instruction>(*other.processed);
|
processed = std::make_unique<Instruction>(*other.processed);
|
||||||
}
|
}
|
||||||
@@ -138,6 +142,8 @@ Value& Value::operator=(const Value& other) {
|
|||||||
varName = other.varName;
|
varName = other.varName;
|
||||||
instructionGroup = other.instructionGroup;
|
instructionGroup = other.instructionGroup;
|
||||||
list = other.list;
|
list = other.list;
|
||||||
|
map = other.map;
|
||||||
|
fn_val = other.fn_val;
|
||||||
if (other.processed) {
|
if (other.processed) {
|
||||||
processed = std::make_unique<Instruction>(*other.processed);
|
processed = std::make_unique<Instruction>(*other.processed);
|
||||||
} else {
|
} else {
|
||||||
@@ -182,6 +188,18 @@ std::string Value::toString() const {
|
|||||||
out += "])";
|
out += "])";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ValueType::Map: {
|
||||||
|
if (map.count("__name__")) {
|
||||||
|
out += "Struct<" + map.at("__name__").string_val + ">, members: {";
|
||||||
|
} else {
|
||||||
|
out += "Map, items: {";
|
||||||
|
}
|
||||||
|
for (const auto& pair : map) {
|
||||||
|
out += pair.first + ": " + pair.second.toString() + ", ";
|
||||||
|
}
|
||||||
|
out += "})";
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
out += "FIXME)";
|
out += "FIXME)";
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
enum class InstructionType {
|
enum class InstructionType {
|
||||||
None, Print, Println, Math, Let, Variable, Exit, If, While, Input, Compare, Function, Return, Concat, Split, File
|
None, Print, Println, Math, Let, Variable, Exit, If, While, Input, Compare, Function, Struct, Return, Concat, Split, File
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ValueType {
|
enum class ValueType {
|
||||||
Processed, Variable, InstructionGroup, List, Map, String, Int, Double, Identifier
|
Processed, Variable, InstructionGroup, List, Map, String, Int, Double, Identifier, Custom
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Instruction;
|
struct Instruction;
|
||||||
@@ -36,16 +36,20 @@ struct Value {
|
|||||||
double double_val = 0.0;
|
double double_val = 0.0;
|
||||||
InstructionGroup instructionGroup;
|
InstructionGroup instructionGroup;
|
||||||
std::vector<Value> list;
|
std::vector<Value> list;
|
||||||
|
std::map<std::string, Value> map;
|
||||||
bool is_return = false;
|
bool is_return = false;
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
Varname varName = Varname();
|
Varname varName = Varname();
|
||||||
|
Function fn_val;
|
||||||
Value(std::string stringval);
|
Value(std::string stringval);
|
||||||
Value(long long intval);
|
Value(long long intval);
|
||||||
Value(double doubleval);
|
Value(double doubleval);
|
||||||
Value(Instruction instval);
|
Value(Instruction instval);
|
||||||
Value(InstructionGroup instgroup);
|
Value(InstructionGroup instgroup);
|
||||||
Value(std::vector<Value> listval);
|
Value(std::vector<Value> listval);
|
||||||
|
Value(std::map<std::string, Value> mapval);
|
||||||
Value(Varname var);
|
Value(Varname var);
|
||||||
|
Value(Function func);
|
||||||
Value();
|
Value();
|
||||||
Value(const Value& other);
|
Value(const Value& other);
|
||||||
Value& operator=(const Value& other);
|
Value& operator=(const Value& other);
|
||||||
@@ -53,6 +57,11 @@ struct Value {
|
|||||||
Value& operator=(Value&& other) = default;
|
Value& operator=(Value&& other) = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Struct {
|
||||||
|
std::map<std::string, Value> values;
|
||||||
|
std::map<std::string, Function> functions;
|
||||||
|
};
|
||||||
|
|
||||||
struct Instruction {
|
struct Instruction {
|
||||||
InstructionType instruction = InstructionType::None;
|
InstructionType instruction = InstructionType::None;
|
||||||
std::vector<Value> args;
|
std::vector<Value> args;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "../modules/compare/compare.h"
|
#include "../modules/compare/compare.h"
|
||||||
#include "../modules/input/input.h"
|
#include "../modules/input/input.h"
|
||||||
#include "../modules/function/function.h"
|
#include "../modules/function/function.h"
|
||||||
|
#include "../modules/struct/struct.h"
|
||||||
#include "../modules/split/split.h"
|
#include "../modules/split/split.h"
|
||||||
#include "../modules/concat/concat.h"
|
#include "../modules/concat/concat.h"
|
||||||
#include "../modules/file/file.h"
|
#include "../modules/file/file.h"
|
||||||
@@ -35,6 +36,9 @@ Value execute(Instruction inst) {
|
|||||||
if (inst.instruction == InstructionType::Function) {
|
if (inst.instruction == InstructionType::Function) {
|
||||||
return modules::fndef(inst.args);
|
return modules::fndef(inst.args);
|
||||||
}
|
}
|
||||||
|
if (inst.instruction == InstructionType::Struct) {
|
||||||
|
return modules::structdef(inst.args);
|
||||||
|
}
|
||||||
if (inst.instruction == InstructionType::Variable) {
|
if (inst.instruction == InstructionType::Variable) {
|
||||||
auto& args = inst.args;
|
auto& args = inst.args;
|
||||||
|
|
||||||
@@ -68,6 +72,48 @@ Value execute(Instruction inst) {
|
|||||||
return return_val;
|
return return_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Struct instantiation
|
||||||
|
if (args[0].valtype == ValueType::Identifier && data::structs.count(args[0].string_val)) {
|
||||||
|
std::string struct_name = args[0].string_val;
|
||||||
|
const auto& struct_def = data::structs.at(struct_name);
|
||||||
|
|
||||||
|
Value instance{std::map<std::string, Value>()};
|
||||||
|
instance.valtype = ValueType::Map;
|
||||||
|
instance.map["__name__"] = Value(struct_name);
|
||||||
|
|
||||||
|
for (const auto& pair : struct_def.values) {
|
||||||
|
instance.map[pair.first] = pair.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (struct_def.functions.count("init")) {
|
||||||
|
const auto& init_func = struct_def.functions.at("init");
|
||||||
|
if (init_func.arg_names.size() != args.size() - 1) {
|
||||||
|
error("Struct " + struct_name + " init expects " + std::to_string(init_func.arg_names.size()) + " arguments, but got " + std::to_string(args.size() - 1));
|
||||||
|
return Value();
|
||||||
|
}
|
||||||
|
data::pushScope();
|
||||||
|
data::scopes.back()["self"] = instance;
|
||||||
|
for (size_t i = 0; i < init_func.arg_names.size(); ++i) {
|
||||||
|
Value arg_val = evaluate(args[i+1]);
|
||||||
|
data::scopes.back()[init_func.arg_names[i]] = arg_val;
|
||||||
|
}
|
||||||
|
Value return_val;
|
||||||
|
for (const auto& body_inst : init_func.body) {
|
||||||
|
return_val = execute(body_inst);
|
||||||
|
if (return_val.is_return) {
|
||||||
|
break; // Should not happen in init
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// After init, self might have been modified.
|
||||||
|
instance = data::scopes.back()["self"];
|
||||||
|
data::popScope();
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Indexed assignment: $var index = value
|
// Indexed assignment: $var index = value
|
||||||
if (args.size() == 4 && args[2].valtype == ValueType::Identifier && args[2].string_val == "=") {
|
if (args.size() == 4 && args[2].valtype == ValueType::Identifier && args[2].string_val == "=") {
|
||||||
std::string var_name;
|
std::string var_name;
|
||||||
@@ -84,8 +130,18 @@ Value execute(Instruction inst) {
|
|||||||
return handleListOp(args);
|
return handleListOp(args);
|
||||||
} else if (subject.valtype == ValueType::String) { // strings are Real
|
} else if (subject.valtype == ValueType::String) { // strings are Real
|
||||||
return handleStringOp(args);
|
return handleStringOp(args);
|
||||||
|
} else if (subject.valtype == ValueType::Map) {
|
||||||
|
if (args[1].valtype != ValueType::Identifier) {
|
||||||
|
error("Struct member name must be an identifier.");
|
||||||
|
return Value();
|
||||||
|
}
|
||||||
|
std::string member_name = args[1].string_val;
|
||||||
|
Value new_val = evaluate(args[3]);
|
||||||
|
subject.map[member_name] = new_val;
|
||||||
|
data::modifyValue(var_name, subject);
|
||||||
|
return Value();
|
||||||
} else {
|
} else {
|
||||||
error("Indexed assignment is only for lists and strings.");
|
error("Indexed assignment is only for lists, strings and struct members.");
|
||||||
return Value();
|
return Value();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,7 +179,52 @@ Value execute(Instruction inst) {
|
|||||||
if (subject.valtype == ValueType::List) {
|
if (subject.valtype == ValueType::List) {
|
||||||
return handleListGet(subject, op_args);
|
return handleListGet(subject, op_args);
|
||||||
} else if (subject.valtype == ValueType::String) {
|
} else if (subject.valtype == ValueType::String) {
|
||||||
return handleStringGet(subject, op_args); }
|
return handleStringGet(subject, op_args);
|
||||||
|
} else if (subject.valtype == ValueType::Map) {
|
||||||
|
if (op_args.empty()) {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
if (op_args[0].valtype != ValueType::Identifier) {
|
||||||
|
error("Struct member name must be an identifier.");
|
||||||
|
return Value();
|
||||||
|
}
|
||||||
|
std::string member_name = op_args[0].string_val;
|
||||||
|
|
||||||
|
// Check for member variable
|
||||||
|
if (subject.map.count(member_name)) {
|
||||||
|
return subject.map.at(member_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for member function
|
||||||
|
std::string struct_name = subject.map.at("__name__").string_val;
|
||||||
|
if (data::structs.count(struct_name) && data::structs.at(struct_name).functions.count(member_name)) {
|
||||||
|
const auto& func = data::structs.at(struct_name).functions.at(member_name);
|
||||||
|
std::vector<Value> func_args(op_args.begin() + 1, op_args.end());
|
||||||
|
if (func.arg_names.size() != func_args.size()) {
|
||||||
|
error("Struct function " + member_name + " expects " + std::to_string(func.arg_names.size()) + " arguments, but got " + std::to_string(func_args.size()));
|
||||||
|
return Value();
|
||||||
|
}
|
||||||
|
data::pushScope();
|
||||||
|
data::scopes.back()["self"] = subject;
|
||||||
|
for (size_t i = 0; i < func.arg_names.size(); ++i) {
|
||||||
|
data::scopes.back()[func.arg_names[i]] = evaluate(func_args[i]);
|
||||||
|
}
|
||||||
|
Value return_val;
|
||||||
|
for (const auto& body_inst : func.body) {
|
||||||
|
return_val = execute(body_inst);
|
||||||
|
if (return_val.is_return) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
subject = data::scopes.back()["self"];
|
||||||
|
data::popScope();
|
||||||
|
return_val.is_return = false;
|
||||||
|
return return_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
error("Struct " + struct_name + " does not have member or method " + member_name);
|
||||||
|
return Value();
|
||||||
|
}
|
||||||
|
|
||||||
error("Unknown variable or function call: " + args[0].toString());
|
error("Unknown variable or function call: " + args[0].toString());
|
||||||
return Value();
|
return Value();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include "../../error/error.h"
|
#include "../../error/error.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
Value modules::fndef(std::vector<Value> args) {
|
Value modules::fndef(std::vector<Value> args, bool inStruct) {
|
||||||
if (args.size() < 2) { // At least a name and a body
|
if (args.size() < 2) { // At least a name and a body
|
||||||
error("Syntax error: function statement requires a name and a body");
|
error("Syntax error: function statement requires a name and a body");
|
||||||
return Value();
|
return Value();
|
||||||
@@ -40,6 +40,10 @@ Value modules::fndef(std::vector<Value> args) {
|
|||||||
new_func.arg_names = arg_names;
|
new_func.arg_names = arg_names;
|
||||||
new_func.body = body_val.instructionGroup;
|
new_func.body = body_val.instructionGroup;
|
||||||
|
|
||||||
|
if (inStruct) {
|
||||||
|
return Value(new_func);
|
||||||
|
}
|
||||||
|
|
||||||
data::functions[func_name] = new_func;
|
data::functions[func_name] = new_func;
|
||||||
|
|
||||||
return Value("");
|
return Value("");
|
||||||
|
|||||||
@@ -4,5 +4,5 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
Value fndef(std::vector<Value> args);
|
Value fndef(std::vector<Value> args, bool inStruct = false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "print.h"
|
#include "print.h"
|
||||||
#include "../../defs/defs.h"
|
#include "../../defs/defs.h"
|
||||||
#include "../../error/error.h"
|
#include "../../error/error.h"
|
||||||
|
#include "../../data/data.h"
|
||||||
|
#include "../../executor/executor.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -21,7 +23,7 @@ Value modules::print(std::vector<Value> values) {
|
|||||||
case ValueType::List: {
|
case ValueType::List: {
|
||||||
std::cout << "[";
|
std::cout << "[";
|
||||||
bool afterfirst = false;
|
bool afterfirst = false;
|
||||||
for (Value val : value.list) {
|
for (const auto& val : value.list) {
|
||||||
if (afterfirst) {
|
if (afterfirst) {
|
||||||
std::cout << ", ";
|
std::cout << ", ";
|
||||||
}
|
}
|
||||||
@@ -33,6 +35,42 @@ Value modules::print(std::vector<Value> values) {
|
|||||||
std::cout << "]";
|
std::cout << "]";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ValueType::Map: {
|
||||||
|
if (value.map.count("__name__")) {
|
||||||
|
std::string struct_name = value.map.at("__name__").string_val;
|
||||||
|
if (data::structs.count(struct_name) && data::structs.at(struct_name).functions.count("toString")) {
|
||||||
|
// Call toString method
|
||||||
|
data::pushScope();
|
||||||
|
data::scopes.back()["self"] = value;
|
||||||
|
Value result;
|
||||||
|
for (const auto& inst : data::structs.at(struct_name).functions.at("toString").body) {
|
||||||
|
result = execute(inst);
|
||||||
|
if (result.is_return) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data::popScope();
|
||||||
|
result.is_return = false;
|
||||||
|
print({result});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fallback to printing members
|
||||||
|
std::cout << "{";
|
||||||
|
bool afterfirst = false;
|
||||||
|
for (const auto& pair : value.map) {
|
||||||
|
if (pair.first == "__name__") continue;
|
||||||
|
if (afterfirst) {
|
||||||
|
std::cout << ", ";
|
||||||
|
} else {
|
||||||
|
afterfirst = true;
|
||||||
|
}
|
||||||
|
std::cout << pair.first << ": ";
|
||||||
|
print({pair.second});
|
||||||
|
}
|
||||||
|
std::cout << "}";
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
error("FIXME: Unhandled type in print module.\nDebug info: \n" + value.toString());
|
error("FIXME: Unhandled type in print module.\nDebug info: \n" + value.toString());
|
||||||
break;
|
break;
|
||||||
|
|||||||
56
src/modules/struct/struct.cpp
Normal file
56
src/modules/struct/struct.cpp
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#include "struct.h"
|
||||||
|
#include "../../defs/defs.h"
|
||||||
|
#include "../../error/error.h"
|
||||||
|
#include "../../data/data.h"
|
||||||
|
#include "../function/function.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
Value modules::structdef(std::vector<Value> args) {
|
||||||
|
if (args.size() < 2) { // At least a name and a body
|
||||||
|
error("Syntax error: struct statement requires a name and a body");
|
||||||
|
return Value();
|
||||||
|
}
|
||||||
|
|
||||||
|
// First arg is the name
|
||||||
|
Value name_val = args[0];
|
||||||
|
if (name_val.valtype != ValueType::Identifier) {
|
||||||
|
error("Syntax error: struct name must be an identifier");
|
||||||
|
return Value();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second arg is the body
|
||||||
|
Value body_val = args[1];
|
||||||
|
if (body_val.valtype != ValueType::InstructionGroup) {
|
||||||
|
error("Syntax error: struct body must be an instruction group");
|
||||||
|
return Value();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string structName = name_val.string_val;
|
||||||
|
InstructionGroup insts = body_val.instructionGroup;
|
||||||
|
|
||||||
|
Struct newStruct;
|
||||||
|
|
||||||
|
for (Instruction inst : insts) {
|
||||||
|
if (inst.args.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (inst.instruction == InstructionType::Function) {
|
||||||
|
newStruct.functions[inst.args[0].string_val] = fndef(inst.args, true).fn_val;
|
||||||
|
} else if (inst.args[0].valtype == ValueType::Identifier) {
|
||||||
|
if (inst.args.size() < 3) {
|
||||||
|
error("Syntax error: struct definition must have identifier, assignment and value");
|
||||||
|
return Value();
|
||||||
|
}
|
||||||
|
if (inst.args[1].valtype == ValueType::Identifier && inst.args[1].string_val == "=") {
|
||||||
|
newStruct.values[inst.args[0].string_val] = inst.args[2];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error("Only member definitions allowed in struct");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data::structs[structName] = newStruct;
|
||||||
|
|
||||||
|
return Value("");
|
||||||
|
|
||||||
|
}
|
||||||
8
src/modules/struct/struct.h
Normal file
8
src/modules/struct/struct.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../../defs/defs.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace modules {
|
||||||
|
Value structdef(std::vector<Value> args);
|
||||||
|
}
|
||||||
@@ -175,6 +175,48 @@ std::vector<Instruction> parse(std::string program) {
|
|||||||
std::string then_content = line.substr(block_start + 1, block_end - block_start - 1);
|
std::string then_content = line.substr(block_start + 1, block_end - block_start - 1);
|
||||||
function_inst.args.push_back(Value(parse(then_content))); // Recursive call
|
function_inst.args.push_back(Value(parse(then_content))); // Recursive call
|
||||||
instructions.push_back(function_inst);
|
instructions.push_back(function_inst);
|
||||||
|
} else if (line.rfind("struct", 0) == 0) {
|
||||||
|
Instruction struct_inst;
|
||||||
|
struct_inst.instruction = InstructionType::Struct;
|
||||||
|
|
||||||
|
size_t block_start = line.find('{');
|
||||||
|
if (block_start == std::string::npos) {
|
||||||
|
error("Expected '{' for struct statement");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. Struct name
|
||||||
|
std::string signature_str = line.substr(6, block_start - 6);
|
||||||
|
std::vector<Value> signature_parts = split(trim(signature_str));
|
||||||
|
|
||||||
|
if (signature_parts.empty()) {
|
||||||
|
error("Struct definition is missing a name.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const auto& part : signature_parts) {
|
||||||
|
struct_inst.args.push_back(part);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Find 'then' block
|
||||||
|
size_t block_end = 0;
|
||||||
|
int brace_level = 0;
|
||||||
|
for (size_t i = block_start; i < line.length(); ++i) {
|
||||||
|
if (line[i] == '{') brace_level++;
|
||||||
|
else if (line[i] == '}') brace_level--;
|
||||||
|
if (brace_level == 0) {
|
||||||
|
block_end = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (block_end == 0) {
|
||||||
|
error("Mismatched braces in struct statement");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string then_content = line.substr(block_start + 1, block_end - block_start - 1);
|
||||||
|
struct_inst.args.push_back(Value(parse(then_content))); // Recursive call
|
||||||
|
instructions.push_back(struct_inst);
|
||||||
} else {
|
} else {
|
||||||
instructions.push_back(Instruction(split(line)));
|
instructions.push_back(Instruction(split(line)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,13 @@ Value evaluate(Value val) {
|
|||||||
}
|
}
|
||||||
} else if (val.valtype == ValueType::Variable) {
|
} else if (val.valtype == ValueType::Variable) {
|
||||||
return data::getValue(val.varName.key);
|
return data::getValue(val.varName.key);
|
||||||
|
} else if (val.valtype == ValueType::Identifier) {
|
||||||
|
// Check if it's a variable that doesn't start with $
|
||||||
|
for (auto it = data::scopes.rbegin(); it != data::scopes.rend(); ++it) {
|
||||||
|
if (it->count(val.string_val)) {
|
||||||
|
return (*it)[val.string_val];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|||||||
27
tests/struct.kyn
Normal file
27
tests/struct.kyn
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
struct Data {
|
||||||
|
status = <Bool>
|
||||||
|
moreCrap = ["dingus", 32]
|
||||||
|
|
||||||
|
fun init status moreCrap {
|
||||||
|
#assert $status is <Bool>
|
||||||
|
#assert $morecrap is <List>
|
||||||
|
println "Initing!"
|
||||||
|
self status = $status
|
||||||
|
self moreCrap = $moreCrap
|
||||||
|
println "Done!"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toString {
|
||||||
|
return (concat "Status: " (self status))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testMemberFn {
|
||||||
|
println "This is from the test member function! Yay!"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let myData = (Data "true" ["dingus", "dongus", "mingus", "mongus"])
|
||||||
|
|
||||||
|
myData testMemberFn
|
||||||
|
|
||||||
|
println $myData
|
||||||
Reference in New Issue
Block a user