Skip to content

Commit

Permalink
Separate value provider (WIP) implementation from current code
Browse files Browse the repository at this point in the history
  • Loading branch information
antis81 committed Jul 12, 2023
1 parent 5f8eb3f commit 6f24b42
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 86 deletions.
104 changes: 21 additions & 83 deletions src/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,99 +166,37 @@ class assert_error : public std::exception
std::string msg;
};

template <typename T>
class ValueProvider {
protected:
std::any val; // TODO: change to std::optional<T>

public:
const std::string_view __owner_classname__;

explicit ValueProvider(std::string const& owner_classname)
: __owner_classname__(owner_classname)
{}
explicit ValueProvider(T const& v, std::string const& owner_classname)
: val(v)
, __owner_classname__(persist(owner_classname))
{}
virtual ~ValueProvider() = default;

inline bool hasValue() const { return val.has_value(); }
inline constexpr auto type() const {
// NOTE: Contrary to std::any the typeid is always known.
return typeid(T);
}

inline T getValue() const {
if (val.has_value()) {
return std::any_cast<T>(val);
} else {
throw std::runtime_error(fmt::format("{} holds a 'None' value.", __owner_classname__));
}
}

inline void setValue(T const& newVal) {
if (val.has_value() && std::any_cast<T>(val) != newVal) {
fmt::print("Changing {} value from {} to {}\n", __owner_classname__, std::any_cast<T>(val), newVal);
// throw?
}
val = newVal;
}
};

template <typename T = AsmValue>
class MultiValueProvider {
protected:
std::map<std::string_view, std::optional<T>> vals;
#if 0
#include "valueprovider.h"
#endif

public:
const std::string_view __owner_classname__;
#ifdef USE_BASS_VALUEPROVIDER
struct Instruction : public ValueProvider<int32_t>
{
std::string opcode;
sixfive::Mode mode;

explicit MultiValueProvider(std::string const& owner_classname)
: __owner_classname__(persist(owner_classname))
Instruction(std::string_view op, sixfive::Mode m, int32_t v)
: ValueProvider(v, "Instruction"), opcode(op), mode(m)
{}
virtual ~MultiValueProvider() = default;

inline bool hasValue(std::string_view key) {
return vals[key].has_value();
}

inline bool hasAllValues() const {
for (auto const& val : vals) {
if (!val.has_value()) {
return false;
}
if ((*val).valueless_by_exception()) {
return false;
}
}

// all values are defined
return true;
}

inline void setValue(std::string_view key, T const& val) {
persist(key);
vals[key] = val;
}

inline T& getValue(std::string_view key) {
return *vals[key];
}

inline std::optional<T>& getOptional(std::string_view key) {
return vals[key];
}
};

struct Instruction : public ValueProvider<int32_t>
#else
struct Instruction
{
Instruction(std::string_view op, sixfive::Mode m, int32_t v)
: ValueProvider(v, "Instruction"), opcode(op), mode(m)
: opcode(op), mode(m), val(static_cast<int32_t>(v))
{}

inline auto getValue() const {return val;}
inline void setValue(int32_t v) {val = v;}

std::string opcode;
sixfive::Mode mode;

private:
int32_t val;
};
#endif

inline std::string getHomeDir()
{
Expand Down
6 changes: 3 additions & 3 deletions src/machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -722,12 +722,12 @@ AsmResult Machine::assemble(Instruction const& instr)
auto const& instructions =
sixfive::Machine<EmuPolicy>::getInstructions(cpu65C02);

auto small = (arg.val >= 0 && arg.val <= 0xff);
auto small = (arg.getValue() >= 0 && arg.getValue() <= 0xff);

if (arg.mode == Mode::ZP_REL) {
// Handle 65c02 bbrX & rmbX opcodes
auto bit = arg.val >> 24;
arg.val &= 0xffffff;
auto bit = arg.getValue() >> 24;
arg.setValue(arg.getValue() & 0xffffff);
arg.opcode = arg.opcode + std::to_string(bit);
}

Expand Down
96 changes: 96 additions & 0 deletions src/valueprovider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#pragma once

#ifndef USE_BASS_VALUEPROVIDER
#define USE_BASS_VALUEPROVIDER
#endif

#include "defines.h"

#include <map>
#include <optional>


template <typename T>
class ValueProvider {
protected:
std::any val; // TODO: change to std::optional<T>

public:
const std::string_view __owner_classname__;

explicit ValueProvider(std::string const& owner_classname)
: __owner_classname__(owner_classname)
{}
explicit ValueProvider(T const& v, std::string const& owner_classname)
: val(v)
, __owner_classname__(persist(owner_classname))
{}
virtual ~ValueProvider() = default;

inline bool hasValue() const { return val.has_value(); }
inline constexpr auto type() const {
// NOTE: Contrary to std::any the typeid is always known.
return typeid(T);
}

inline T getValue() const {
if (val.has_value()) {
return std::any_cast<T>(val);
} else {
throw std::runtime_error(fmt::format("{} holds a 'None' value.", __owner_classname__));
}
}

inline void setValue(T const& newVal) {
if (val.has_value() && std::any_cast<T>(val) != newVal) {
fmt::print("Changing {} value from {} to {}\n", __owner_classname__, std::any_cast<T>(val), newVal);
// throw?
}
val = newVal;
}
};

template <typename T = AsmValue>
class MultiValueProvider {
protected:
std::map<std::string_view, std::optional<T>> vals;

public:
const std::string_view __owner_classname__;

explicit MultiValueProvider(std::string const& owner_classname)
: __owner_classname__(persist(owner_classname))
{}
virtual ~MultiValueProvider() = default;

inline bool hasValue(std::string_view key) {
return vals[key].has_value();
}

inline bool hasAllValues() const {
for (auto const& val : vals) {
if (!val.has_value()) {
return false;
}
if ((*val).valueless_by_exception()) {
return false;
}
}

// all values are defined
return true;
}

inline void setValue(std::string_view key, T const& val) {
persist(key);
vals[key] = val;
}

inline T& getValue(std::string_view key) {
return *vals[key];
}

inline std::optional<T>& getOptional(std::string_view key) {
return vals[key];
}
};

0 comments on commit 6f24b42

Please sign in to comment.