Split code generation from the ui
This commit is contained in:
@ -3,10 +3,23 @@
|
||||
#include <cstdint>
|
||||
#include <unordered_map>
|
||||
#include "elna/source/parser.hpp"
|
||||
#include "elna/result.hpp"
|
||||
|
||||
namespace elna
|
||||
namespace elna::backend
|
||||
{
|
||||
enum class Target
|
||||
{
|
||||
text,
|
||||
high20,
|
||||
lower12i
|
||||
};
|
||||
|
||||
struct Reference
|
||||
{
|
||||
const char* name;
|
||||
std::size_t offset;
|
||||
Target target;
|
||||
};
|
||||
|
||||
enum class XRegister : std::uint8_t
|
||||
{
|
||||
zero = 0,
|
||||
@ -135,8 +148,8 @@ namespace elna
|
||||
Instruction& r(XRegister rd, Funct3 funct3, XRegister rs1, XRegister rs2, Funct7 funct7 = Funct7::none);
|
||||
Instruction& u(XRegister rd, std::uint32_t imm);
|
||||
|
||||
const std::byte *cbegin();
|
||||
const std::byte *cend();
|
||||
const std::byte *cbegin() const;
|
||||
const std::byte *cend() const;
|
||||
|
||||
private:
|
||||
std::uint32_t instruction{ 0 };
|
||||
@ -145,8 +158,7 @@ namespace elna
|
||||
class RiscVVisitor : public source::ParserVisitor
|
||||
{
|
||||
public:
|
||||
Instruction *instructions;
|
||||
std::size_t instructionsLength;
|
||||
std::vector<Instruction> instructions;
|
||||
bool registerInUse{ true };
|
||||
std::uint32_t variableCounter = 1;
|
||||
Reference references[3];
|
||||
@ -155,10 +167,8 @@ namespace elna
|
||||
virtual void visit(source::definition *definition) override;
|
||||
virtual void visit(source::bang_statement *statement) override;
|
||||
virtual void visit(source::block *block) override;
|
||||
virtual void visit(source::variable *variable) override;
|
||||
virtual void visit(source::variable_expression *variable) override;
|
||||
virtual void visit(source::integer_literal *number) override;
|
||||
virtual void visit(source::binary_expression *expression) override;
|
||||
};
|
||||
|
||||
Symbol writeNext(source::block *ast);
|
||||
}
|
7
include/elna/backend/target.hpp
Normal file
7
include/elna/backend/target.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
#include "elna/source/parser.hpp"
|
||||
#include <filesystem>
|
||||
|
||||
namespace elna::backend
|
||||
{
|
||||
void riscv32_elf(source::block *ast, const std::filesystem::path& out_file);
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
namespace elna
|
||||
namespace elna::cli
|
||||
{
|
||||
char *readSource(const char *source);
|
||||
int compile(const std::filesystem::path& in_file, const std::filesystem::path& out_file);
|
@ -1,112 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#include <forward_list>
|
||||
|
||||
namespace elna
|
||||
{
|
||||
namespace source
|
||||
{
|
||||
/**
|
||||
* Position in the source text.
|
||||
*/
|
||||
struct position
|
||||
{
|
||||
/// Line.
|
||||
std::size_t line = 1;
|
||||
|
||||
/// Column.
|
||||
std::size_t column = 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* A compilation error consists of an error message and position.
|
||||
*/
|
||||
struct error
|
||||
{
|
||||
private:
|
||||
char const *message;
|
||||
source::position position;
|
||||
|
||||
public:
|
||||
/**
|
||||
* \param message Error text.
|
||||
* \param position Error position in the source text.
|
||||
*/
|
||||
error(char const *message, const source::position position) noexcept;
|
||||
|
||||
/// Error text.
|
||||
const char *what() const noexcept;
|
||||
|
||||
/// Error line in the source text.
|
||||
std::size_t line() const noexcept;
|
||||
|
||||
/// Error column in the source text.
|
||||
std::size_t column() const noexcept;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct result
|
||||
{
|
||||
using E = std::forward_list<source::error>;
|
||||
|
||||
template<typename... Args>
|
||||
explicit result(Args&&... arguments)
|
||||
: payload(std::forward<Args>(arguments)...)
|
||||
{
|
||||
}
|
||||
|
||||
explicit result(const char *message, const source::position position)
|
||||
: payload(E{ source::error(message, position) })
|
||||
{
|
||||
}
|
||||
|
||||
bool has_errors() const noexcept
|
||||
{
|
||||
return std::holds_alternative<E>(payload);
|
||||
}
|
||||
|
||||
bool is_success() const noexcept
|
||||
{
|
||||
return std::holds_alternative<T>(payload);
|
||||
}
|
||||
|
||||
T& success()
|
||||
{
|
||||
return std::get<T>(payload);
|
||||
}
|
||||
|
||||
E& errors()
|
||||
{
|
||||
return std::get<E>(payload);
|
||||
}
|
||||
|
||||
private:
|
||||
std::variant<T, E> payload;
|
||||
};
|
||||
}
|
||||
|
||||
enum class Target
|
||||
{
|
||||
text,
|
||||
high20,
|
||||
lower12i
|
||||
};
|
||||
|
||||
struct Reference
|
||||
{
|
||||
const char* name;
|
||||
size_t offset;
|
||||
Target target;
|
||||
};
|
||||
|
||||
struct Symbol
|
||||
{
|
||||
Symbol(const char *name);
|
||||
const char *name;
|
||||
std::vector<std::byte> text;
|
||||
Reference symbols[3];
|
||||
};
|
||||
}
|
@ -5,8 +5,8 @@
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
#include "elna/state.hpp"
|
||||
#include "elna/history.hpp"
|
||||
#include "elna/shell/state.hpp"
|
||||
#include "elna/shell/history.hpp"
|
||||
|
||||
#define BOOST_PROCESS_USE_STD_FS
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include "elna/source/parser.hpp"
|
||||
|
||||
namespace elna
|
||||
namespace elna::source
|
||||
{
|
||||
class TransformVisitor final : public source::ParserVisitor
|
||||
{
|
||||
@ -10,7 +10,7 @@ namespace elna
|
||||
void visit(source::bang_statement *statement) override;
|
||||
void visit(source::block *block) override;
|
||||
void visit(source::integer_literal *number) override;
|
||||
void visit(source::variable *variable) override;
|
||||
void visit(source::variable_expression *variable) override;
|
||||
void visit(source::binary_expression *binaryExpression) override;
|
||||
};
|
||||
}
|
@ -2,12 +2,10 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "elna/source/result.hpp"
|
||||
|
||||
#include "elna/result.hpp"
|
||||
|
||||
namespace elna
|
||||
{
|
||||
namespace source
|
||||
namespace elna::source
|
||||
{
|
||||
/**
|
||||
* Range over the source text that keeps track of the current position.
|
||||
@ -113,4 +111,3 @@ namespace source
|
||||
*/
|
||||
elna::source::result<std::vector<token>> lex(const std::string& buffer);
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,7 @@
|
||||
#include <memory>
|
||||
#include <elna/source/lexer.hpp>
|
||||
|
||||
namespace elna
|
||||
{
|
||||
namespace source
|
||||
namespace elna::source
|
||||
{
|
||||
enum class binary_operator
|
||||
{
|
||||
@ -20,7 +18,7 @@ namespace source
|
||||
class bang_statement;
|
||||
class block;
|
||||
class binary_expression;
|
||||
class variable;
|
||||
class variable_expression;
|
||||
class integer_literal;
|
||||
|
||||
struct ParserVisitor
|
||||
@ -29,7 +27,7 @@ namespace source
|
||||
virtual void visit(bang_statement *) = 0;
|
||||
virtual void visit(block *) = 0;
|
||||
virtual void visit(binary_expression *) = 0;
|
||||
virtual void visit(variable *) = 0;
|
||||
virtual void visit(variable_expression *) = 0;
|
||||
virtual void visit(integer_literal *) = 0;
|
||||
};
|
||||
|
||||
@ -104,12 +102,12 @@ namespace source
|
||||
std::int32_t number() const noexcept;
|
||||
};
|
||||
|
||||
class variable : public expression
|
||||
class variable_expression : public expression
|
||||
{
|
||||
std::string m_name;
|
||||
|
||||
public:
|
||||
variable(const std::string& name);
|
||||
variable_expression(const std::string& name);
|
||||
virtual void accept(ParserVisitor *visitor) override;
|
||||
|
||||
const std::string& name() const noexcept;
|
||||
@ -150,4 +148,3 @@ namespace source
|
||||
std::vector<token>::const_iterator end;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
86
include/elna/source/result.hpp
Normal file
86
include/elna/source/result.hpp
Normal file
@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <variant>
|
||||
#include <forward_list>
|
||||
|
||||
namespace elna::source
|
||||
{
|
||||
/**
|
||||
* Position in the source text.
|
||||
*/
|
||||
struct position
|
||||
{
|
||||
/// Line.
|
||||
std::size_t line = 1;
|
||||
|
||||
/// Column.
|
||||
std::size_t column = 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* A compilation error consists of an error message and position.
|
||||
*/
|
||||
struct error
|
||||
{
|
||||
private:
|
||||
char const *message;
|
||||
source::position position;
|
||||
|
||||
public:
|
||||
/**
|
||||
* \param message Error text.
|
||||
* \param position Error position in the source text.
|
||||
*/
|
||||
error(char const *message, const source::position position) noexcept;
|
||||
|
||||
/// Error text.
|
||||
const char *what() const noexcept;
|
||||
|
||||
/// Error line in the source text.
|
||||
std::size_t line() const noexcept;
|
||||
|
||||
/// Error column in the source text.
|
||||
std::size_t column() const noexcept;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct result
|
||||
{
|
||||
using E = std::forward_list<source::error>;
|
||||
|
||||
template<typename... Args>
|
||||
explicit result(Args&&... arguments)
|
||||
: payload(std::forward<Args>(arguments)...)
|
||||
{
|
||||
}
|
||||
|
||||
explicit result(const char *message, const source::position position)
|
||||
: payload(E{ source::error(message, position) })
|
||||
{
|
||||
}
|
||||
|
||||
bool has_errors() const noexcept
|
||||
{
|
||||
return std::holds_alternative<E>(payload);
|
||||
}
|
||||
|
||||
bool is_success() const noexcept
|
||||
{
|
||||
return std::holds_alternative<T>(payload);
|
||||
}
|
||||
|
||||
T& success()
|
||||
{
|
||||
return std::get<T>(payload);
|
||||
}
|
||||
|
||||
E& errors()
|
||||
{
|
||||
return std::get<E>(payload);
|
||||
}
|
||||
|
||||
private:
|
||||
std::variant<T, E> payload;
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user