From b628c00f9e6c393369cb3b229efda3b49faee4f7 Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Sat, 4 Oct 2025 20:57:16 +1000 Subject: [PATCH] Type assertion and initialization --- src/defs/defs.cpp | 14 ++++++++-- src/defs/defs.h | 5 ++-- src/executor/executor.cpp | 4 +++ src/modules/assert/assert.cpp | 49 +++++++++++++++++++++++++++++++++ src/modules/assert/assert.h | 8 ++++++ src/utils/evaluate/evaluate.cpp | 16 ++++++++++- tests/struct.kyn | 8 +++--- 7 files changed, 94 insertions(+), 10 deletions(-) create mode 100644 src/modules/assert/assert.cpp create mode 100644 src/modules/assert/assert.h diff --git a/src/defs/defs.cpp b/src/defs/defs.cpp index 91f5e21..edd9d6b 100644 --- a/src/defs/defs.cpp +++ b/src/defs/defs.cpp @@ -21,6 +21,7 @@ InstructionType strToInstructionType(std::string in) { else if (in == "split") return InstructionType::Split; else if (in == "file") return InstructionType::File; else if (in == "struct") return InstructionType::Struct; + else if (in == "assert") return InstructionType::Assert; else return InstructionType::Variable; } @@ -70,6 +71,12 @@ Instruction::Instruction(std::vector toks) { Value::Value(std::string stringval) { // This constructor will attempt to parse the string into the most specific type possible. + if (stringval.length() > 2 && stringval.front() == '<' && stringval.back() == '>') { + valtype = ValueType::TypePlaceholder; + type_placeholder_name = stringval.substr(1, stringval.length() - 2); + return; + } + if (stringval.length() >= 2 && stringval.front() == '"' && stringval.back() == '"') { valtype = ValueType::String; string_val = stringval.substr(1, stringval.length() - 2); @@ -120,16 +127,16 @@ Value::Value(std::vector listval) : valtype(ValueType::List), list(std::m Value::Value(std::map mapval) : valtype(ValueType::Map), map(std::move(mapval)) {} +Value::Value(Varname var) : valtype(ValueType::Variable), varName(var) {} + 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) { +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), type_placeholder_name(other.type_placeholder_name), varName(other.varName), fn_val(other.fn_val) { if (other.processed) { processed = std::make_unique(*other.processed); } } -Value::Value(Varname varname) : valtype(ValueType::Variable), varName(varname) {} - Varname::Varname(std::string in) : key(in.substr(1)) {} Varname::Varname() : key("") {} @@ -143,6 +150,7 @@ Value& Value::operator=(const Value& other) { instructionGroup = other.instructionGroup; list = other.list; map = other.map; + type_placeholder_name = other.type_placeholder_name; fn_val = other.fn_val; if (other.processed) { processed = std::make_unique(*other.processed); diff --git a/src/defs/defs.h b/src/defs/defs.h index 51c8157..e318507 100644 --- a/src/defs/defs.h +++ b/src/defs/defs.h @@ -6,11 +6,11 @@ #include enum class InstructionType { - None, Print, Println, Math, Let, Variable, Exit, If, While, Input, Compare, Function, Struct, Return, Concat, Split, File + None, Print, Println, Math, Let, Variable, Exit, If, While, Input, Compare, Function, Struct, Return, Concat, Split, File, Assert }; enum class ValueType { - Processed, Variable, InstructionGroup, List, Map, String, Int, Double, Identifier, Custom + Processed, Variable, InstructionGroup, List, Map, String, Int, Double, Identifier, Custom, TypePlaceholder }; struct Instruction; @@ -37,6 +37,7 @@ struct Value { InstructionGroup instructionGroup; std::vector list; std::map map; + std::string type_placeholder_name; bool is_return = false; std::string toString() const; Varname varName = Varname(); diff --git a/src/executor/executor.cpp b/src/executor/executor.cpp index 1d48ae8..99be250 100644 --- a/src/executor/executor.cpp +++ b/src/executor/executor.cpp @@ -18,6 +18,7 @@ #include "../modules/split/split.h" #include "../modules/concat/concat.h" #include "../modules/file/file.h" +#include "../modules/assert/assert.h" // Forward declaration for mutual recursion Value evaluate(Value val); @@ -39,6 +40,9 @@ Value execute(Instruction inst) { if (inst.instruction == InstructionType::Struct) { return modules::structdef(inst.args); } + if (inst.instruction == InstructionType::Assert) { + return modules::assert(inst.args); + } if (inst.instruction == InstructionType::Variable) { auto& args = inst.args; diff --git a/src/modules/assert/assert.cpp b/src/modules/assert/assert.cpp new file mode 100644 index 0000000..8a2e14d --- /dev/null +++ b/src/modules/assert/assert.cpp @@ -0,0 +1,49 @@ +#include "assert.h" +#include "../../error/error.h" +#include "../../data/data.h" +#include "../../utils/evaluate/evaluate.h" + +Value modules::assert(std::vector args) { + if (args.size() != 3 || args[1].valtype != ValueType::Identifier || args[1].string_val != "is") { + error("Syntax error: assert requires is "); + return Value(); + } + + Value val = evaluate(args[0]); + Value& type = args[2]; + + if (type.valtype != ValueType::TypePlaceholder) { + error("Syntax error: assert expects a type placeholder (e.g., )"); + return Value(); + } + + std::string type_name = type.type_placeholder_name; + bool condition = false; + + if (type_name == "Any") { + condition = true; + } else if (type_name == "String") { + condition = (val.valtype == ValueType::String); + } else if (type_name == "List") { + condition = (val.valtype == ValueType::List); + } else if (type_name == "Int") { + condition = (val.valtype == ValueType::Int); + } else if (type_name == "Double") { + condition = (val.valtype == ValueType::Double); + } else if (type_name == "Bool") { + condition = (val.valtype == ValueType::String && (val.string_val == "true" || val.string_val == "false")); + } else { + // Check for user-defined struct types + if (data::structs.count(type_name)) { + condition = (val.valtype == ValueType::Map && val.map.count("__name__") && val.map.at("__name__").string_val == type_name); + } else { + error("Unknown type for assert: " + type_name); + } + } + + if (!condition) { + error("Assertion failed: value is not of type " + type_name); + } + + return Value(); +} diff --git a/src/modules/assert/assert.h b/src/modules/assert/assert.h new file mode 100644 index 0000000..9a1c32d --- /dev/null +++ b/src/modules/assert/assert.h @@ -0,0 +1,8 @@ +#pragma once + +#include "../../defs/defs.h" +#include + +namespace modules { + Value assert(std::vector args); +} diff --git a/src/utils/evaluate/evaluate.cpp b/src/utils/evaluate/evaluate.cpp index dd5f2b4..727fa24 100644 --- a/src/utils/evaluate/evaluate.cpp +++ b/src/utils/evaluate/evaluate.cpp @@ -17,6 +17,20 @@ Value evaluate(Value val) { return (*it)[val.string_val]; } } + } else if (val.valtype == ValueType::TypePlaceholder) { + if (val.type_placeholder_name == "String") { + return Value(""); + } else if (val.type_placeholder_name == "List") { + return Value(std::vector()); + } else if (val.type_placeholder_name == "Int") { + return Value((long long)0); + } else if (val.type_placeholder_name == "Double") { + return Value((double)0.0); + } else if (val.type_placeholder_name == "Bool") { + return Value("false"); + } else if (val.type_placeholder_name == "Any") { + return Value(""); // Default for Any is an empty string + } } return val; -} +} \ No newline at end of file diff --git a/tests/struct.kyn b/tests/struct.kyn index dd222d6..3b0be29 100644 --- a/tests/struct.kyn +++ b/tests/struct.kyn @@ -1,10 +1,10 @@ struct Data { - status = + status = moreCrap = ["dingus", 32] fun init status moreCrap { - #assert $status is - #assert $morecrap is + assert $status is + assert $moreCrap is println "Initing!" self status = $status self moreCrap = $moreCrap @@ -20,7 +20,7 @@ struct Data { } } -let myData = (Data "true" ["dingus", "dongus", "mingus", "mongus"]) +let myData = (Data 0 ["dingus", "dongus", "mingus", "mongus"]) myData testMemberFn