#pragma once #include #include #include #include #include #include #include #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(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 argument_types() const = 0; [[nodiscard]] virtual std::vector return_types() const = 0; [[nodiscard]] virtual std::vector generate(const parser_context&, const lexed_output& lexer_data) const = 0; [[nodiscard]] virtual std::vector emit(const parser_context&) const = 0; }; struct primitive_operation : public operation { std::string _name; std::vector _args; std::vector _rets; std::vector _instructions; primitive_operation(std::string name, std::vector args, std::vector rets, std::vector body) : _name(std::forward(name)) , _args(std::forward>(args)) , _rets(std::forward>(rets)) , _instructions(std::forward>(body)) {} [[nodiscard]] std::string name() const final { return _name; } [[nodiscard]] std::vector argument_types() const final { return _args; } [[nodiscard]] std::vector return_types() const final { return _rets; } [[nodiscard]] std::vector generate(const parser_context&, const lexed_output& lexer_data) const final { return {}; } [[nodiscard]] std::vector emit(const parser_context&) const final { return _instructions; } }; struct procedure_operation : public operation { std::string _name; std::vector _args; std::vector _rets; std::vector _body; procedure_operation(std::string name, std::vector args, std::vector rets, std::vector body) : _name(std::forward(name)) , _args(std::forward>(args)) , _rets(std::forward>(rets)) , _body(std::forward>(body)) {} [[nodiscard]] std::string name() const final { return _name; } [[nodiscard]] std::vector argument_types() const final { return _args; } [[nodiscard]] std::vector return_types() const final { return _rets; } [[nodiscard]] std::vector generate(const parser_context&, const lexed_output& lexer_data) const final; [[nodiscard]] std::vector 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 operator>>(std::vector current_stack, const operation& next_op); std::optional try_parse_int32(const std::string& str); struct parser_context { std::vector> types; std::vector> operations; std::vector> procedures; [[nodiscard]] std::shared_ptr lookup_type(const std::string&) const; [[nodiscard]] std::shared_ptr lookup_operation(const std::string&) const; }; struct generate_context { lexed_output lexer; parser_context parser; std::vector> procedures; }; generate_context parse(parser_context, const lexed_output&); std::vector 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&, std::vector execution_input, const std::vector& execution_output); }