|
|
- #pragma once
- #include <string>
- #include <set>
- #include <vector>
- #include <memory>
- #include <optional>
- #include <charconv>
- #include <concepts>
-
- #include "molasses/lexer.h"
-
-
- enum class architecture_t {
- x86_64_linux,
- x86_linux
- };
-
- #if defined(__x86_64__) && __linux__
- constexpr architecture_t architecture = architecture_t::x86_64_linux;
- constexpr size_t architecture_ptr_size = 8;
- #elif defined(__i386) || defined(__i386__) || defined(i386) && __linux__
- constexpr architecture_t architecture = architecture_t::x86_linux;
- constexpr size_t architecture_ptr_size = 4;
- #endif
-
- namespace molasses {
- struct type {
- [[nodiscard]] virtual std::string name() const = 0;
- [[nodiscard]] virtual size_t byte_size() const = 0;
- };
-
- inline auto operator<=>(const type& lhs, const type& rhs) {
- return lhs.name() <=> rhs.name();
- }
-
- struct primitive_type : public type {
- std::string _name;
- size_t _byte_size;
-
- primitive_type(std::string name, size_t byte_size)
- : _name(std::forward<std::string>(name))
- , _byte_size(byte_size)
- {}
-
- [[nodiscard]] std::string name() const final {
- return _name;
- }
- [[nodiscard]] size_t byte_size() const final {
- return _byte_size;
- };
- };
-
- struct parser_context;
-
- struct operation {
- [[nodiscard]] virtual std::string name() const = 0;
- [[nodiscard]] virtual std::vector<std::string> argument_types() const = 0;
- [[nodiscard]] virtual std::vector<std::string> return_types() const = 0;
- [[nodiscard]] virtual std::vector<std::string> generate(const parser_context&, const lexed_output& lexer_data) const = 0;
- [[nodiscard]] virtual std::vector<std::string> emit(const parser_context&) const = 0;
- };
-
- struct primitive_operation : public operation {
- std::string _name;
- std::vector<std::string> _args;
- std::vector<std::string> _rets;
- std::vector<std::string> _instructions;
-
- primitive_operation(std::string name, std::vector<std::string> args, std::vector<std::string> rets, std::vector<std::string> body)
- : _name(std::forward<std::string>(name))
- , _args(std::forward<std::vector<std::string>>(args))
- , _rets(std::forward<std::vector<std::string>>(rets))
- , _instructions(std::forward<std::vector<std::string>>(body))
- {}
-
- [[nodiscard]] std::string name() const final {
- return _name;
- }
- [[nodiscard]] std::vector<std::string> argument_types() const final {
- return _args;
- }
- [[nodiscard]] std::vector<std::string> return_types() const final {
- return _rets;
- }
- [[nodiscard]] std::vector<std::string> generate(const parser_context&, const lexed_output& lexer_data) const final {
- return {};
- }
- [[nodiscard]] std::vector<std::string> emit(const parser_context&) const final {
- return _instructions;
- }
- };
-
- struct procedure_operation : public operation {
- std::string _name;
- std::vector<std::string> _args;
- std::vector<std::string> _rets;
- std::vector<symbol> _body;
-
- procedure_operation(std::string name, std::vector<std::string> args, std::vector<std::string> rets, std::vector<symbol> body)
- : _name(std::forward<std::string>(name))
- , _args(std::forward<std::vector<std::string>>(args))
- , _rets(std::forward<std::vector<std::string>>(rets))
- , _body(std::forward<std::vector<symbol>>(body))
- {}
-
- [[nodiscard]] std::string name() const final {
- return _name;
- }
- [[nodiscard]] std::vector<std::string> argument_types() const final {
- return _args;
- }
- [[nodiscard]] std::vector<std::string> return_types() const final {
- return _rets;
- }
- [[nodiscard]] std::vector<std::string> generate(const parser_context&, const lexed_output& lexer_data) const final;
- [[nodiscard]] std::vector<std::string> emit(const parser_context&) const final;
- };
-
- inline auto operator<=>(const operation& lhs, const operation& rhs) {
- return lhs.name() <=> rhs.name();
- }
-
- struct type_input_error : std::runtime_error {
- type_input_error() : std::runtime_error("Bad type provided") {}
- // TODO: Better error message
- };
- struct value_missing_error : std::runtime_error {
- value_missing_error() : std::runtime_error("Expected value, none provided") {}
- // TODO: Better error message
- };
- struct procedure_stack_error : std::runtime_error {
- procedure_stack_error() : std::runtime_error("Expected the stack to look like the return stack upon completion") {}
- // TODO: Better error message
- };
- struct unexpected_token_error : std::runtime_error {
- unexpected_token_error() : std::runtime_error("An unexpected token has been encountered") {}
- // TODO: Better error message
- };
- struct expecting_token_error : std::runtime_error {
- expecting_token_error() : std::runtime_error("An expected token has not been encountered before the end of the input") {}
- // TODO: Better error message
- };
- struct unknown_token_error : std::runtime_error {
- unknown_token_error() : std::runtime_error("An unknown token has not been encountered") {}
- // TODO: Better error message
- };
- struct type_expected_with_modifier_error : std::runtime_error {
- type_expected_with_modifier_error() : std::runtime_error("A type is expected before a modifier") {}
- // TODO: Better error message
- };
-
- std::vector<std::string> operator>>(std::vector<std::string> current_stack, const operation& next_op);
-
- std::optional<int32_t> try_parse_int32(const std::string& str);
-
- struct parser_context {
- std::vector<std::shared_ptr<type>> types;
- std::vector<std::shared_ptr<operation>> operations;
- std::vector<std::shared_ptr<procedure_operation>> procedures;
-
- [[nodiscard]] std::shared_ptr<type> lookup_type(const std::string&) const;
- [[nodiscard]] std::shared_ptr<operation> lookup_operation(const std::string&) const;
- };
-
- struct generate_context {
- lexed_output lexer;
- parser_context parser;
- std::vector<std::shared_ptr<procedure_operation>> procedures;
- };
-
- generate_context parse(parser_context, const lexed_output&);
- std::vector<std::string> generate(generate_context);
-
- parser_context register_integers(parser_context);
- parser_context register_i32_operations(parser_context);
-
- bool type_check(const parser_context&, const lexed_output&, const std::vector<symbol>&, std::vector<std::string> execution_input, const std::vector<std::string>& execution_output);
- }
-
|