~maelkum/viuavm

f6c8d231573ae3e63d8f44a6756efc388da3141f — Marek Marecki a month ago 4f9e864
Format source code
M new/include/viua/libs/lexer.h => new/include/viua/libs/lexer.h +3 -2
@@ 22,12 22,12 @@

#include <stdint.h>

#include <filesystem>
#include <optional>
#include <set>
#include <string>
#include <string_view>
#include <vector>
#include <filesystem>


namespace viua::libs::lexer {


@@ 264,7 264,8 @@ inline auto const OPCODE_NAMES = std::set<std::string>{
auto lex(std::string_view) -> std::vector<Lexeme>;

namespace stage {
auto lexical_analysis(std::filesystem::path const, std::string_view const) -> std::vector<Lexeme>;
auto lexical_analysis(std::filesystem::path const, std::string_view const)
    -> std::vector<Lexeme>;
}
}  // namespace viua::libs::lexer


M new/include/viua/libs/parser.h => new/include/viua/libs/parser.h +2 -2
@@ 122,8 122,8 @@ auto did_you_mean(viua::libs::errors::compile_time::Error&&, std::string)
auto did_you_mean(viua::libs::errors::compile_time::Error&, std::string)
    -> viua::libs::errors::compile_time::Error&;

auto parse_instruction(
    viua::support::vector_view<viua::libs::lexer::Lexeme>&) -> ast::Instruction;
auto parse_instruction(viua::support::vector_view<viua::libs::lexer::Lexeme>&)
    -> ast::Instruction;
auto parse(viua::support::vector_view<viua::libs::lexer::Lexeme>)
    -> std::vector<std::unique_ptr<ast::Node>>;
}  // namespace viua::libs::parser

M new/include/viua/libs/stage.h => new/include/viua/libs/stage.h +6 -5
@@ 24,8 24,8 @@
#include <sys/types.h>

#include <map>
#include <vector>
#include <string_view>
#include <vector>

#include <viua/libs/errors/compile_time.h>
#include <viua/libs/parser.h>


@@ 50,13 50,14 @@ auto display_error_in_function(std::filesystem::path const source_path,
                               viua::libs::errors::compile_time::Error const& e,
                               std::string_view const fn_name) -> void;

auto save_string(std::vector<uint8_t>&, std::string_view const)
    -> size_t;
auto save_string(std::vector<uint8_t>&, std::string_view const) -> size_t;
auto cook_long_immediates(viua::libs::parser::ast::Instruction,
                          std::vector<uint8_t>&,
                          std::map<std::string, size_t>&) -> std::vector<viua::libs::parser::ast::Instruction>;
                          std::map<std::string, size_t>&)
    -> std::vector<viua::libs::parser::ast::Instruction>;

auto emit_instruction(viua::libs::parser::ast::Instruction const) -> viua::arch::instruction_type;
auto emit_instruction(viua::libs::parser::ast::Instruction const)
    -> viua::arch::instruction_type;
}  // namespace viua::libs::stage

#endif

M new/src/tools/exec/asm.cpp => new/src/tools/exec/asm.cpp +21 -14
@@ 46,11 46,11 @@

#include <viua/arch/arch.h>
#include <viua/arch/ops.h>
#include <viua/libs/stage.h>
#include <viua/libs/assembler.h>
#include <viua/libs/errors/compile_time.h>
#include <viua/libs/lexer.h>
#include <viua/libs/parser.h>
#include <viua/libs/stage.h>
#include <viua/support/string.h>
#include <viua/support/tty.h>
#include <viua/support/vector.h>


@@ 870,7 870,8 @@ auto load_value_labels(std::filesystem::path const source_path,
                                           .add(ct.value.at(i - 2))
                                           .aside("right-hand side must be an "
                                                  "positive integer");
                        viua::libs::stage::display_error_and_exit(source_path, source_text, e);
                        viua::libs::stage::display_error_and_exit(
                            source_path, source_text, e);
                    }

                    auto x = ston<size_t>(next.text);


@@ 907,7 908,8 @@ auto load_function_labels(AST_nodes const& nodes,

auto cook_long_immediates(ast::Instruction insn,
                          std::vector<uint8_t>& strings_table,
                          std::map<std::string, size_t>& var_offsets) -> std::vector<ast::Instruction>
                          std::map<std::string, size_t>& var_offsets)
    -> std::vector<ast::Instruction>
{
    auto cooked = std::vector<ast::Instruction>{};



@@ 1043,8 1045,7 @@ auto cook_long_immediates(ast::Instruction insn,
        cooked.push_back(std::move(insn));
    } else if (insn.opcode == "float" or insn.opcode == "g.float") {
        constexpr auto SIZE_OF_SINGLE_PRECISION_FLOAT = size_t{4};
        auto f =
            std::stof(insn.operands.back().ingredients.front().text);
        auto f = std::stof(insn.operands.back().ingredients.front().text);
        auto s = std::string(SIZE_OF_SINGLE_PRECISION_FLOAT, '\0');
        memcpy(s.data(), &f, SIZE_OF_SINGLE_PRECISION_FLOAT);
        auto const saved_at = save_string(strings_table, s);


@@ 1065,8 1066,7 @@ auto cook_long_immediates(ast::Instruction insn,
        cooked.push_back(std::move(insn));
    } else if (insn.opcode == "double" or insn.opcode == "g.double") {
        constexpr auto SIZE_OF_DOUBLE_PRECISION_FLOAT = size_t{8};
        auto f =
            std::stod(insn.operands.back().ingredients.front().text);
        auto f = std::stod(insn.operands.back().ingredients.front().text);
        auto s = std::string(SIZE_OF_DOUBLE_PRECISION_FLOAT, '\0');
        memcpy(s.data(), &f, SIZE_OF_DOUBLE_PRECISION_FLOAT);
        auto const saved_at = save_string(strings_table, s);


@@ 1110,8 1110,10 @@ auto cook_long_immediates(std::filesystem::path const source_path,
                auto c = cook_long_immediates(insn, strings_table, var_offsets);
                std::copy(c.begin(), c.end(), std::back_inserter(cooked));
            } catch (viua::libs::errors::compile_time::Error const& e) {
                viua::libs::stage::display_error_in_function(source_path, e, fn.name.text);
                viua::libs::stage::display_error_and_exit(source_path, source_text, e);
                viua::libs::stage::display_error_in_function(
                    source_path, e, fn.name.text);
                viua::libs::stage::display_error_and_exit(
                    source_path, source_text, e);
            }
        }
        fn.instructions = std::move(cooked);


@@ 1134,8 1136,10 @@ auto cook_pseudoinstructions(std::filesystem::path const source_path,
            fn.instructions = ::expand_pseudoinstructions(
                std::move(fn.instructions), fn_offsets);
        } catch (viua::libs::errors::compile_time::Error const& e) {
            viua::libs::stage::display_error_in_function(source_path, e, fn.name.text);
            viua::libs::stage::display_error_and_exit(source_path, source_text, e);
            viua::libs::stage::display_error_in_function(
                source_path, e, fn.name.text);
            viua::libs::stage::display_error_and_exit(
                source_path, source_text, e);
        }

        if constexpr (DEBUG_EXPANSION) {


@@ 1171,7 1175,8 @@ auto find_entry_point(std::filesystem::path const source_path,
                        dup.name, Cause::Duplicated_entry_point, dup.name.text}
                        .add(dup.attr("entry_point").value())
                        .note("first entry point was: " + entry_point_fn->text);
                viua::libs::stage::display_error_and_exit(source_path, source_text, e);
                viua::libs::stage::display_error_and_exit(
                    source_path, source_text, e);
            }
            entry_point_fn = static_cast<ast::Fn_def&>(*each).name;
        }


@@ 1242,7 1247,8 @@ auto emit_bytecode(std::filesystem::path const source_path,
        }

        if (fn_name.has_value()) {
            viua::libs::stage::display_error_in_function(source_path, e, *fn_name);
            viua::libs::stage::display_error_in_function(
                source_path, e, *fn_name);
        }
        viua::libs::stage::display_error_and_exit(source_path, source_text, e);
    }


@@ 1718,7 1724,8 @@ auto main(int argc, char* argv[]) -> int
     * processing later. The first point at which errors are detected eg, if
     * illegal characters are used, strings are unclosed, etc.
     */
    auto lexemes = viua::libs::lexer::stage::lexical_analysis(source_path, source_text);
    auto lexemes =
        viua::libs::lexer::stage::lexical_analysis(source_path, source_text);
    if constexpr (DEBUG_LEX) {
        std::cerr << lexemes.size() << " raw lexeme(s)\n";
        for (auto const& each : lexemes) {

M new/src/tools/exec/repl.cpp => new/src/tools/exec/repl.cpp +6 -5
@@ 32,12 32,12 @@

#include <viua/arch/ins.h>
#include <viua/arch/ops.h>
#include <viua/libs/parser.h>
#include <viua/libs/stage.h>
#include <viua/support/fdstream.h>
#include <viua/support/tty.h>
#include <viua/vm/core.h>
#include <viua/vm/ins.h>
#include <viua/libs/stage.h>
#include <viua/libs/parser.h>


struct Global_state {


@@ 351,14 351,15 @@ auto load_module(std::string_view const name, std::filesystem::path elf_path)
auto evaluate_asm_expression(std::string const asm_text) -> void
{
    auto lexemes = viua::libs::lexer::stage::lexical_analysis("-", asm_text);
    lexemes = viua::libs::parser::ast::remove_noise(std::move(lexemes));
    lexemes      = viua::libs::parser::ast::remove_noise(std::move(lexemes));

    auto lv = viua::support::vector_view{lexemes};
    auto p = viua::libs::parser::parse_instruction(lv);
    auto p  = viua::libs::parser::parse_instruction(lv);

    auto strings_table = std::vector<uint8_t>{};
    auto var_offsets   = std::map<std::string, size_t>{};
    auto const cooked = viua::libs::stage::cook_long_immediates(p, strings_table, var_offsets);
    auto const cooked =
        viua::libs::stage::cook_long_immediates(p, strings_table, var_offsets);

    auto proc = REPL_STATE->core.find(*REPL_STATE->selected_pid);
    for (auto const& each : cooked) {

M new/src/tools/libs/lexer.cpp => new/src/tools/libs/lexer.cpp +1 -1
@@ 467,5 467,5 @@ auto lexical_analysis(std::filesystem::path const source_path,
        viua::libs::stage::display_error_and_exit(source_path, source_text, e);
    }
}
}
}  // namespace stage
}  // namespace viua::libs::lexer

M new/src/tools/libs/parser.cpp => new/src/tools/libs/parser.cpp +9 -12
@@ 261,7 261,8 @@ auto parse_attr_list(
    return attrs;
}
auto parse_instruction(
    viua::support::vector_view<viua::libs::lexer::Lexeme>& lexemes) -> ast::Instruction
    viua::support::vector_view<viua::libs::lexer::Lexeme>& lexemes)
    -> ast::Instruction
{
    auto instruction = ast::Instruction{};



@@ 281,8 282,8 @@ auto parse_instruction(
        }

        using viua::support::string::levenshtein_best;
        auto best_candidate = levenshtein_best(
            e.text, misspell_candidates, (e.text.size() / 2));
        auto best_candidate =
            levenshtein_best(e.text, misspell_candidates, (e.text.size() / 2));
        if (best_candidate.second == e.text) {
            throw;
        }


@@ 350,9 351,8 @@ auto parse_instruction(
                using viua::libs::errors::compile_time::Error;
                throw Error{index, Cause::Invalid_register_access}
                    .add(access)
                    .aside(
                        "register index range is 0-"
                        + std::to_string(viua::arch::MAX_REGISTER_INDEX));
                    .aside("register index range is 0-"
                           + std::to_string(viua::arch::MAX_REGISTER_INDEX));
            }
            operand.ingredients.push_back(access);
            operand.ingredients.push_back(index);


@@ 381,16 381,13 @@ auto parse_instruction(
                consume_token_of(TOKEN::LITERAL_INTEGER, lexemes);
            operand.ingredients.push_back(value);
        } else if (lexemes.front() == TOKEN::LITERAL_FLOAT) {
            auto const value =
                consume_token_of(TOKEN::LITERAL_FLOAT, lexemes);
            auto const value = consume_token_of(TOKEN::LITERAL_FLOAT, lexemes);
            operand.ingredients.push_back(value);
        } else if (lexemes.front() == TOKEN::LITERAL_STRING) {
            auto const value =
                consume_token_of(TOKEN::LITERAL_STRING, lexemes);
            auto const value = consume_token_of(TOKEN::LITERAL_STRING, lexemes);
            operand.ingredients.push_back(value);
        } else if (lexemes.front() == TOKEN::LITERAL_ATOM) {
            auto const value =
                consume_token_of(TOKEN::LITERAL_ATOM, lexemes);
            auto const value = consume_token_of(TOKEN::LITERAL_ATOM, lexemes);
            operand.ingredients.push_back(value);
        } else {
            using viua::libs::errors::compile_time::Cause;

M new/src/tools/libs/stage.cpp => new/src/tools/libs/stage.cpp +38 -39
@@ 361,7 361,8 @@ auto save_string(std::vector<uint8_t>& strings, std::string_view const data)
}
auto cook_long_immediates(viua::libs::parser::ast::Instruction insn,
                          std::vector<uint8_t>& strings_table,
                          std::map<std::string, size_t>& var_offsets) -> std::vector<viua::libs::parser::ast::Instruction>
                          std::map<std::string, size_t>& var_offsets)
    -> std::vector<viua::libs::parser::ast::Instruction>
{
    auto cooked = std::vector<viua::libs::parser::ast::Instruction>{};



@@ 397,7 398,8 @@ auto cook_long_immediates(viua::libs::parser::ast::Instruction insn,
                                         misspell_candidates,
                                         (label.text.size() / 2));
                    if (best_candidate.second != label.text) {
                        viua::libs::parser::did_you_mean(e, best_candidate.second);
                        viua::libs::parser::did_you_mean(e,
                                                         best_candidate.second);
                    }
                }



@@ 461,7 463,8 @@ auto cook_long_immediates(viua::libs::parser::ast::Instruction insn,
                                         misspell_candidates,
                                         (label.text.size() / 2));
                    if (best_candidate.second != label.text) {
                        viua::libs::parser::did_you_mean(e, best_candidate.second);
                        viua::libs::parser::did_you_mean(e,
                                                         best_candidate.second);
                    }
                }



@@ 497,8 500,7 @@ auto cook_long_immediates(viua::libs::parser::ast::Instruction insn,
        cooked.push_back(std::move(insn));
    } else if (insn.opcode == "float" or insn.opcode == "g.float") {
        constexpr auto SIZE_OF_SINGLE_PRECISION_FLOAT = size_t{4};
        auto f =
            std::stof(insn.operands.back().ingredients.front().text);
        auto f = std::stof(insn.operands.back().ingredients.front().text);
        auto s = std::string(SIZE_OF_SINGLE_PRECISION_FLOAT, '\0');
        memcpy(s.data(), &f, SIZE_OF_SINGLE_PRECISION_FLOAT);
        auto const saved_at = save_string(strings_table, s);


@@ 519,8 521,7 @@ auto cook_long_immediates(viua::libs::parser::ast::Instruction insn,
        cooked.push_back(std::move(insn));
    } else if (insn.opcode == "double" or insn.opcode == "g.double") {
        constexpr auto SIZE_OF_DOUBLE_PRECISION_FLOAT = size_t{8};
        auto f =
            std::stod(insn.operands.back().ingredients.front().text);
        auto f = std::stod(insn.operands.back().ingredients.front().text);
        auto s = std::string(SIZE_OF_DOUBLE_PRECISION_FLOAT, '\0');
        memcpy(s.data(), &f, SIZE_OF_DOUBLE_PRECISION_FLOAT);
        auto const saved_at = save_string(strings_table, s);


@@ 546,7 547,8 @@ auto cook_long_immediates(viua::libs::parser::ast::Instruction insn,
    return cooked;
}

auto operand_or_throw(viua::libs::parser::ast::Instruction const& insn, size_t const index)
auto operand_or_throw(viua::libs::parser::ast::Instruction const& insn,
                      size_t const index)
    -> viua::libs::parser::ast::Operand const&
{
    try {


@@ 559,7 561,8 @@ auto operand_or_throw(viua::libs::parser::ast::Instruction const& insn, size_t c
                    ("operand " + std::to_string(index) + " not found")};
    }
}
auto emit_instruction(viua::libs::parser::ast::Instruction const insn) -> viua::arch::instruction_type
auto emit_instruction(viua::libs::parser::ast::Instruction const insn)
    -> viua::arch::instruction_type
{
    using viua::arch::opcode_type;
    using viua::arch::ops::FORMAT;


@@ 581,35 584,32 @@ auto emit_instruction(viua::libs::parser::ast::Instruction const insn) -> viua::
        return static_cast<uint64_t>(opcode);
    case FORMAT::T:
        return viua::arch::ops::T{opcode,
                               operand_or_throw(insn, 0).make_access(),
                               operand_or_throw(insn, 1).make_access(),
                               operand_or_throw(insn, 2).make_access()}
                .encode();
                                  operand_or_throw(insn, 0).make_access(),
                                  operand_or_throw(insn, 1).make_access(),
                                  operand_or_throw(insn, 2).make_access()}
            .encode();
    case FORMAT::D:
        return viua::arch::ops::D{opcode,
                               operand_or_throw(insn, 0).make_access(),
                               operand_or_throw(insn, 1).make_access()}
                .encode();
                                  operand_or_throw(insn, 0).make_access(),
                                  operand_or_throw(insn, 1).make_access()}
            .encode();
    case FORMAT::S:
                return
            viua::arch::ops::S{opcode,
                               operand_or_throw(insn, 0).make_access()}
                .encode();
        return viua::arch::ops::S{opcode,
                                  operand_or_throw(insn, 0).make_access()}
            .encode();
    case FORMAT::F:
        return uint64_t{0};  // FIXME
    case FORMAT::E:
        return
            viua::arch::ops::E{
                opcode,
                operand_or_throw(insn, 0).make_access(),
                std::stoull(
                    operand_or_throw(insn, 1).ingredients.front().text)}
                .encode();
        return viua::arch::ops::E{
            opcode,
            operand_or_throw(insn, 0).make_access(),
            std::stoull(operand_or_throw(insn, 1).ingredients.front().text)}
            .encode();
    case FORMAT::R:
    {
        auto const imm = insn.operands.back().ingredients.front();
        auto const is_unsigned = (static_cast<opcode_type>(opcode)
                                  & viua::arch::ops::UNSIGNED);
        auto const is_unsigned =
            (static_cast<opcode_type>(opcode) & viua::arch::ops::UNSIGNED);
        if (is_unsigned and imm.text.at(0) == '-'
            and (imm.text != "-1" and imm.text != "-1u")) {
            using viua::libs::errors::compile_time::Cause;


@@ 630,15 630,13 @@ auto emit_instruction(viua::libs::parser::ast::Instruction const insn) -> viua::
                        "unsigned integer used for signed immediate"};
        }
        try {
            return
                viua::arch::ops::R{
                    opcode,
                    insn.operands.at(0).make_access(),
                    insn.operands.at(1).make_access(),
                    (is_unsigned
                         ? static_cast<uint32_t>(std::stoul(imm.text))
                         : static_cast<uint32_t>(std::stoi(imm.text)))}
                    .encode();
            return viua::arch::ops::R{
                opcode,
                insn.operands.at(0).make_access(),
                insn.operands.at(1).make_access(),
                (is_unsigned ? static_cast<uint32_t>(std::stoul(imm.text))
                             : static_cast<uint32_t>(std::stoi(imm.text)))}
                .encode();
        } catch (std::invalid_argument const&) {
            using viua::libs::errors::compile_time::Cause;
            using viua::libs::errors::compile_time::Error;


@@ 652,7 650,8 @@ auto emit_instruction(viua::libs::parser::ast::Instruction const insn) -> viua::
    default:
        using viua::libs::errors::compile_time::Cause;
        using viua::libs::errors::compile_time::Error;
        throw Error{insn.opcode, Cause::Unknown_opcode, "cannot emit instruction"};
        throw Error{
            insn.opcode, Cause::Unknown_opcode, "cannot emit instruction"};
    }
}
}  // namespace viua::libs::stage