Skip to content

Commit

Permalink
rename m_fragments to m_instructions and make it non-optional
Browse files Browse the repository at this point in the history
  • Loading branch information
bbrk24 committed Oct 20, 2024
1 parent 4d72d79 commit fd7b2ed
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 19 deletions.
32 changes: 19 additions & 13 deletions src/assembly_scanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,11 @@ using std::string_view_literals::operator""sv;
exit(EXIT_FAILURE);
}

const std::vector<instruction>& assembly_scanner::get_fragments() {
if (m_fragments.has_value()) {
return *m_fragments;
const std::vector<instruction>& assembly_scanner::get_instructions() {
if (!m_instructions.empty()) {
return m_instructions;
}

m_fragments.emplace(std::vector<instruction>());

// We need to do two passes: one to resolve labels, and one to assign targets to jumps. During the first pass, the
// fragments are actually constructed. However, jumps may not have valid targets yet, so we need some way to store
// the label's name inside an IP. This code relies on the following assumption:
Expand Down Expand Up @@ -89,7 +87,7 @@ const std::vector<instruction>& assembly_scanner::get_fragments() {
string label(curr_line.substr(0, i));

[[maybe_unused]] auto _0 = label_names.insert(label);
auto [_, inserted] = m_label_locations.insert({ label, m_fragments->size() });
auto [_, inserted] = m_label_locations.insert({ label, m_instructions.size() });

if (!inserted) {
cerr << "Label '" << label << "' appears twice" << endl;
Expand Down Expand Up @@ -125,7 +123,7 @@ const std::vector<instruction>& assembly_scanner::get_fragments() {
instruction::argument arg;
string label(curr_line.substr(label_start));
arg.next = { SIZE_C(0), label_to_fake_location(label) };
m_fragments->push_back({ opcode, arg });
m_instructions.push_back({ opcode, arg });
m_slices.push_back(curr_line);
break;
}
Expand All @@ -134,8 +132,8 @@ const std::vector<instruction>& assembly_scanner::get_fragments() {
size_t label_start = curr_line.find_first_not_of(WHITESPACE, 3);
instruction::argument arg;
string label(curr_line.substr(label_start));
arg.choice = { { SIZE_C(0), m_fragments->size() + 1 }, { SIZE_C(0), label_to_fake_location(label) } };
m_fragments->push_back({ opcode, arg });
arg.choice = { { SIZE_C(0), m_instructions.size() + 1 }, { SIZE_C(0), label_to_fake_location(label) } };
m_instructions.push_back({ opcode, arg });
m_slices.push_back(curr_line);
break;
}
Expand Down Expand Up @@ -188,27 +186,35 @@ const std::vector<instruction>& assembly_scanner::get_fragments() {

instruction::argument arg;
arg.number = arg_value;
m_fragments->push_back({ opcode, arg });
m_instructions.push_back({ opcode, arg });
m_slices.push_back(curr_line);
break;
}
default:
m_fragments->push_back({ opcode, instruction::argument() });
m_instructions.push_back({ opcode, instruction::argument() });
m_slices.push_back(curr_line);
break;
}
}

if (!m_instructions.empty()) {
const auto& last_instr = m_instructions.back();
if (!(last_instr.is_exit() || last_instr.m_op == instruction::operation::JMP)) {
cerr << "Program does not end in an exit instruction or loop" << endl;
exit(EXIT_FAILURE);
}
}

// Second pass
for (auto& instr : *m_fragments) {
for (auto& instr : m_instructions) {
if (instr.m_op == instruction::operation::JMP) {
fake_location_to_real(instr.m_arg.next);
} else if (instr.m_op == instruction::operation::TSP || instr.m_op == instruction::operation::BNG) {
fake_location_to_real(instr.m_arg.choice.second);
}
}

return *m_fragments;
return m_instructions;
}

void assembly_scanner::advance(IP& ip, std::function<bool()> go_left) {
Expand Down
10 changes: 5 additions & 5 deletions src/assembly_scanner.hh
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,24 @@ public:
using IP = size_t;

inline assembly_scanner(const std::string& program) :
m_label_locations(), m_program(program), m_fragments(std::nullopt), m_slices{} {}
m_label_locations(), m_program(program), m_instructions{}, m_slices{} {}

const std::vector<instruction>& get_fragments();
const std::vector<instruction>& get_instructions();

void advance(IP& ip, std::function<bool()> go_left);

inline std::string raw_at(const IP& ip) {
[[maybe_unused]] auto _ = get_fragments();
[[maybe_unused]] auto _ = get_instructions();
return std::string(m_slices[ip]);
}
inline std::pair<size_t, size_t> get_coords(const IP& ip) const { return { SIZE_C(0), ip }; }
inline instruction at(const IP& ip) { return get_fragments()[ip]; }
inline instruction at(const IP& ip) { return get_instructions()[ip]; }
private:
void fake_location_to_real(std::pair<size_t, size_t>& p) const;
static instruction::operation opcode_for_name(const std::string_view& name) noexcept;

std::unordered_map<std::string, IP> m_label_locations;
std::string m_program;
std::optional<std::vector<instruction>> m_fragments;
std::vector<instruction> m_instructions;
std::vector<std::string_view> m_slices;
};
2 changes: 1 addition & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ inline void execute(const std::string& prg, flags f) {

if (f.assembly) {
assembly_scanner as(prg);
if (as.get_fragments().size() == 0) {
if (as.get_instructions().size() == 0) {
empty_program();
}
interpreter i(as, f);
Expand Down

0 comments on commit fd7b2ed

Please sign in to comment.