diff --git a/src/assembler.cpp b/src/assembler.cpp index d0fa34e..96ed892 100644 --- a/src/assembler.cpp +++ b/src/assembler.cpp @@ -49,8 +49,11 @@ Number to_number(std::string_view txt, Base base, int skip = 0) return static_cast(result); } -std::string any_to_string(std::any const& val) +std::string any_to_string(std::any const& val, std::string_view name) { + if (!val.has_value()) { + throw parse_error(fmt::format("Cannot convert 'None' value from Symbol {} to std::string", name)); + } if (auto const* n = std::any_cast(&val)) { auto in = static_cast(*n); if (*n == static_cast(in)) return fmt::format("${:x}", in); @@ -547,8 +550,11 @@ void Assembler::setSym(std::string_view sym, std::any val) syms.set_final(sym); } -AsmValue to_variant(std::any const& a) +AsmValue to_variant(std::any const& a, std::string_view identifier) { + if (!a.has_value()) { + throw parse_error(fmt::format("Cannot convert a 'None' {} value to AsmValue", identifier)); + } if (auto const* n = std::any_cast(&a)) { return *n; @@ -565,7 +571,12 @@ AsmValue to_variant(std::any const& a) { return *vn; } - return {}; + + // not implemented + static_assert(std::variant_size() == 4); + //throw parse_error(fmt::format("No variant conversion available for type {}", a.type().name())); + auto s_err = fmt::format("No AsmValue conversion available for type {} (context: {})", a.type().name(), identifier); + return persist(s_err); } void Assembler::setupRules() @@ -732,8 +743,21 @@ void Assembler::setupRules() } for(auto&& a : meta.args) { - auto v = to_variant(a); - meta.vargs.push_back(v); + auto identifier = fmt::format("MetaBlock::{} -> arg[{}]", meta.name, meta.vargs.size()); + if (a.has_value()) { + auto v = to_variant(a, identifier); + meta.vargs.push_back(v); + if (auto strv = std::get_if(&v)) { + if (strv->starts_with("No AsmValue conversion")) { + LOGD(fmt::format("{}\n", *strv)); + } + } + } else { + // FIXME: keeps existing code intact (can we leave out such values?) + AsmValue v_default; + LOGD(fmt::format("AsmValue cannot hold a 'None' value -> creating value {} (context: {}))", std::get<0>(v_default), identifier)); + meta.vargs.push_back(v_default); + } } @@ -969,7 +993,7 @@ void Assembler::setupRules() auto buildArg = [](SV& sv) -> std::any { auto mode = modeMap.at(std::string(sv.name())); return Instruction{"", mode, - mode == Mode::ACC ? 0 : any_cast(sv[0])}; + mode == Mode::ACC ? 0 : number(sv[0])}; }; for (auto const& [name, _] : modeMap) { parser.after(name.c_str(), buildArg); @@ -978,7 +1002,7 @@ void Assembler::setupRules() parser.after("ZRel", [](SV& sv) -> Instruction { auto v = (number(sv[1]) << 24) | (number(sv[0]) << 16) | number(sv[2]); - return {"", Mode::ZP_REL, static_cast(v)}; + return {"", Mode::ZP_REL, v}; }); parser.after("LabelRef", [this](SV& sv) { @@ -1099,8 +1123,8 @@ void Assembler::setupRules() } auto ope = any_cast(sv[1]); - auto arg1 = to_variant(sv[0]); - auto arg2 = to_variant(sv[2]); + auto arg1 = to_variant(sv[0], fmt::format("Expression2 -> arg[{}]", 0)); + auto arg2 = to_variant(sv[2], fmt::format("Expression2 -> arg[{}]", 2)); try { auto res = operation(ope, arg1, arg2); @@ -1400,7 +1424,7 @@ void Assembler::printSymbols() { syms.forAll([](std::string const& name, std::any const& val) { if (!utils::startsWith(name, "__")) - fmt::print("{} == {}\n", name, any_to_string(val)); + fmt::print("{} == {}\n", name, any_to_string(val, name)); }); } @@ -1411,7 +1435,7 @@ void Assembler::writeSymbols(fs::path const& p) if (!utils::startsWith(name, "__") && (name.find('.') == std::string::npos) && val.type() == typeid(Number)) - fmt::print(f.filePointer(), "{} = {}\n", name, any_to_string(val)); + fmt::print(f.filePointer(), "{} = {}\n", name, any_to_string(val, name)); }); } diff --git a/src/assembler.h b/src/assembler.h index 4c7ca5c..c515fa9 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -14,8 +14,6 @@ class Machine; -using AsmValue = std::variant, std::vector>; - inline void Check(bool v, std::string const& txt) { if (!v) throw parse_error(txt); diff --git a/src/defines.h b/src/defines.h index 2d7cf62..cd3096b 100644 --- a/src/defines.h +++ b/src/defines.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -110,6 +111,7 @@ inline std::string_view operator+(std::string_view sv, std::string_view n) } using Number = double; +using AsmValue = std::variant, std::vector>; inline Num div(Num a, Num b) { @@ -125,12 +127,18 @@ inline Num pow(Num a, Num b) template inline T number(std::any const& v) { - return static_cast(std::any_cast(v)); + if (v.has_value()) { + return static_cast(std::any_cast(v)); + } + throw std::runtime_error(fmt::format("Cannot convert 'None' to arithmetic type '{}'.", typeid(T).name())); } inline Number number(std::any const& v) { - return std::any_cast(v); + if (v.has_value()) { + return std::any_cast(v); + } + throw std::runtime_error(fmt::format("Cannot converted 'None' to Number type ({})", typeid(Number).name())); } template @@ -158,8 +166,8 @@ class assert_error : public std::exception struct Instruction { - Instruction(std::string_view op, sixfive::Mode m, double v) - : opcode(op), mode(m), val(static_cast(v)) + Instruction(std::string_view op, sixfive::Mode m, int32_t v) + : opcode(op), mode(m), val(v) {} std::string opcode; sixfive::Mode mode; @@ -190,7 +198,7 @@ inline std::string getHomeDir() return homeDir; } -std::string any_to_string(std::any const& val); +std::string any_to_string(std::any const& val, std::string_view name); inline void printArg(std::any const& arg) { diff --git a/src/machine.cpp b/src/machine.cpp index 9a6e53a..0274181 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -742,7 +742,7 @@ AsmResult Machine::assemble(Instruction const& instr) // Find a matching addressing mode auto it_op = std::find_if(it_ins->opcodes.begin(), it_ins->opcodes.end(), - [&](auto const& o) { + [&](auto const& o) { return modeMatches(arg.mode, o.mode, small); }); diff --git a/src/parser.cpp b/src/parser.cpp index cd96d0b..bdec4b6 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -263,10 +263,10 @@ std::any Parser::evaluate(AstNode const& node) sv.name(), ast->line, sv.token_view()); for (size_t i = 0; i < sv.size(); i++) { std::any const v = sv[i]; - fmt::print(" {}: {}\n", i, any_to_string(v)); + fmt::print(" {}: {}\n", i, any_to_string(v, sv.name())); } auto ret = callAction(sv, *ast->action); - fmt::print(">> {}\n", any_to_string(ret)); + fmt::print(">> {}\n", any_to_string(ret, sv.name())); return ret; } return callAction(sv, *ast->action); diff --git a/src/parser.h b/src/parser.h index 7e79960..e3c3abe 100644 --- a/src/parser.h +++ b/src/parser.h @@ -67,12 +67,6 @@ class SemanticValues AstNode get_node() const { return ast; } std::string const& file_name() const; - - template - T to(size_t i) const - { - return std::any_cast(operator[](i)); - } }; using ActionFn = std::function; diff --git a/src/symbol_table.h b/src/symbol_table.h index 486e687..5bf7626 100644 --- a/src/symbol_table.h +++ b/src/symbol_table.h @@ -258,6 +258,7 @@ struct SymbolTable } undefined.insert(std::string{name}); if constexpr (std::is_same_v) { + LOGD(fmt::format("Returning zero value for undefined label '{}'\n", name)); return zero; } LOGD("Returning default (%s)", typeid(T{}).name());