#pragma once #include #include #include #include #include #include #include #include "molasses/lexer.h" 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 TypeInputError : std::runtime_error { TypeInputError() : std::runtime_error("Bad type provided") {} // TODO: Better error message }; struct ValueMissingError : std::runtime_error { ValueMissingError() : std::runtime_error("Expected value, none provided") {} // TODO: Better error message }; struct ProcedureStackError : std::runtime_error { ProcedureStackError() : std::runtime_error("Expected the stack to look like the return stack upon completion") {} // TODO: Better error message }; struct UnexpectedTokenError : std::runtime_error { UnexpectedTokenError() : std::runtime_error("An unexpected token has been encountered") {} // TODO: Better error message }; struct ExpectingTokenError : std::runtime_error { ExpectingTokenError() : std::runtime_error("An expected token has not been encountered before the end of the input") {} // TODO: Better error message }; struct UnknownTokenError : std::runtime_error { UnknownTokenError() : std::runtime_error("An unknown token has not been encountered") {} // 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; [[nodiscard]] std::shared_ptr lookup_type(const std::string&) const; [[nodiscard]] std::shared_ptr lookup_operation(const std::string&) const; }; parser_context parse(parser_context, const lexed_output&); 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); }