You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

243 lines
8.5 KiB

1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
  1. #pragma once
  2. #include <charconv>
  3. #include <concepts>
  4. #include <functional>
  5. #include <memory>
  6. #include <optional>
  7. #include <set>
  8. #include <sstream>
  9. #include <stack>
  10. #include <string>
  11. #include <utility>
  12. #include <variant>
  13. #include <vector>
  14. #include "molasses/lexer.h"
  15. enum class architecture_t {
  16. x86_64_linux,
  17. x86_linux
  18. };
  19. #if defined(__x86_64__) && __linux__
  20. constexpr architecture_t architecture = architecture_t::x86_64_linux;
  21. constexpr size_t architecture_ptr_size = 8;
  22. #elif defined(__i386) || defined(__i386__) || defined(i386) && __linux__
  23. constexpr architecture_t architecture = architecture_t::x86_linux;
  24. constexpr size_t architecture_ptr_size = 4;
  25. #endif
  26. namespace molasses {
  27. namespace details {
  28. template<typename ...RestT>
  29. std::string concatenate_builder_impl(std::stringstream& stream)
  30. requires (sizeof...(RestT) == 0)
  31. {
  32. return stream.str();
  33. }
  34. template<typename FirstT, typename ...RestT>
  35. std::string concatenate_builder_impl(std::stringstream& stream, FirstT first, RestT... rest) {
  36. stream << first;
  37. return concatenate_builder_impl(stream, rest...);
  38. }
  39. template<typename ...RestT>
  40. std::string concatenate_builder(RestT... rest) {
  41. std::stringstream stream{};
  42. return concatenate_builder_impl(stream, rest...);
  43. }
  44. }
  45. struct type {
  46. [[nodiscard]] virtual std::string name() const = 0;
  47. [[nodiscard]] virtual size_t byte_size() const = 0;
  48. };
  49. inline auto operator<=>(const type& lhs, const type& rhs) {
  50. return lhs.name() <=> rhs.name();
  51. }
  52. struct primitive_type : public type {
  53. std::string _name;
  54. size_t _byte_size;
  55. primitive_type(std::string name, size_t byte_size)
  56. : _name(std::forward<std::string>(name))
  57. , _byte_size(byte_size)
  58. {}
  59. [[nodiscard]] std::string name() const final {
  60. return _name;
  61. }
  62. [[nodiscard]] size_t byte_size() const final {
  63. return _byte_size;
  64. };
  65. };
  66. struct parser_context;
  67. struct ptr_type{
  68. void* ptr;
  69. std::shared_ptr<type> pointed;
  70. };
  71. using stack_element = std::variant<int32_t, int64_t, ptr_type>;
  72. using interpreter_stack = std::stack<stack_element>;
  73. struct generate_context;
  74. struct operation {
  75. [[nodiscard]] virtual std::string name() const = 0;
  76. [[nodiscard]] virtual std::vector<std::string> argument_types() const = 0;
  77. [[nodiscard]] virtual std::vector<std::string> return_types() const = 0;
  78. [[nodiscard]] virtual std::vector<std::string> generate(const parser_context&, const lexed_output& lexer_data) const = 0;
  79. [[nodiscard]] virtual std::vector<std::string> emit(const parser_context&) const = 0;
  80. virtual void execute(const generate_context&, interpreter_stack&) const = 0;
  81. };
  82. struct primitive_operation : public operation {
  83. std::string _name;
  84. std::vector<std::string> _args;
  85. std::vector<std::string> _rets;
  86. std::vector<std::string> _instructions;
  87. std::function<void(const generate_context&, interpreter_stack&)> _executable;
  88. primitive_operation(std::string name, std::vector<std::string> args, std::vector<std::string> rets, std::vector<std::string> body, std::function<void(const generate_context&,interpreter_stack&)> executable)
  89. : _name(std::forward<std::string>(name))
  90. , _args(std::forward<std::vector<std::string>>(args))
  91. , _rets(std::forward<std::vector<std::string>>(rets))
  92. , _instructions(std::forward<std::vector<std::string>>(body))
  93. , _executable(std::move(executable))
  94. {}
  95. [[nodiscard]] std::string name() const final {
  96. return _name;
  97. }
  98. [[nodiscard]] std::vector<std::string> argument_types() const final {
  99. return _args;
  100. }
  101. [[nodiscard]] std::vector<std::string> return_types() const final {
  102. return _rets;
  103. }
  104. [[nodiscard]] std::vector<std::string> generate(const parser_context&, const lexed_output& lexer_data) const final {
  105. return {};
  106. }
  107. [[nodiscard]] std::vector<std::string> emit(const parser_context&) const final {
  108. return _instructions;
  109. }
  110. void execute(const generate_context& ctx, interpreter_stack& stack) const override {
  111. _executable(ctx, stack);
  112. };
  113. };
  114. struct procedure_operation : public operation {
  115. std::string _name;
  116. std::vector<std::string> _args;
  117. std::vector<std::string> _rets;
  118. std::vector<symbol> _body;
  119. procedure_operation(std::string name, std::vector<std::string> args, std::vector<std::string> rets, std::vector<symbol> body)
  120. : _name(std::forward<std::string>(name))
  121. , _args(std::forward<std::vector<std::string>>(args))
  122. , _rets(std::forward<std::vector<std::string>>(rets))
  123. , _body(std::forward<std::vector<symbol>>(body))
  124. {}
  125. [[nodiscard]] std::string name() const final {
  126. return _name;
  127. }
  128. [[nodiscard]] std::vector<std::string> argument_types() const final {
  129. return _args;
  130. }
  131. [[nodiscard]] std::vector<std::string> return_types() const final {
  132. return _rets;
  133. }
  134. [[nodiscard]] std::vector<std::string> generate(const parser_context&, const lexed_output& lexer_data) const final;
  135. [[nodiscard]] std::vector<std::string> emit(const parser_context&) const final;
  136. void execute(const generate_context&, interpreter_stack&) const final;
  137. };
  138. inline auto operator<=>(const operation& lhs, const operation& rhs) {
  139. return lhs.name() <=> rhs.name();
  140. }
  141. struct parser_error : public std::runtime_error {
  142. explicit parser_error(const std::string& str) : std::runtime_error(str) {}
  143. };
  144. struct type_input_error : public parser_error {
  145. type_input_error() : parser_error("Bad type provided") {}
  146. // TODO: Better error message
  147. };
  148. struct value_missing_error : public parser_error {
  149. value_missing_error() : parser_error("Expected value, none provided") {}
  150. // TODO: Better error message
  151. };
  152. struct procedure_stack_error : public parser_error {
  153. procedure_stack_error() : parser_error("Expected the stack to look like the return stack upon completion\n") {}
  154. // TODO: Better error message
  155. };
  156. struct unexpected_token_error : public parser_error {
  157. unexpected_token_error(const symbol& sym, const std::string& found, const std::string& expected)
  158. : parser_error (
  159. details::concatenate_builder(
  160. "Unexpected token encountered\n",
  161. "\tAt ", sym.file_name,":",sym.line,":",sym.column,"\n",
  162. "\tExpected ", expected, "\n",
  163. "\tFound ", found, "\n"
  164. )
  165. ) {}
  166. };
  167. struct expecting_token_error : public parser_error {
  168. expecting_token_error(const std::string& expected, const std::string& context)
  169. : parser_error(
  170. details::concatenate_builder(
  171. "An expected token has not been encountered before the end of the input\n",
  172. "\tExpected ", expected,"\n",
  173. "\t", context,"\n"
  174. )
  175. )
  176. {}
  177. // TODO: Better error message
  178. };
  179. struct unknown_token_error : public parser_error {
  180. explicit unknown_token_error(const symbol& sym) : parser_error(details::concatenate_builder("An unknown token has been encountered\n", "\tAt ", sym.file_name,":",sym.line,":",sym.column,"\n")) {}
  181. // TODO: Better error message
  182. };
  183. struct type_expected_with_modifier_error : public parser_error {
  184. type_expected_with_modifier_error() : parser_error("A type is expected before a modifier") {}
  185. // TODO: Better error message
  186. };
  187. std::vector<std::string> operator>>(std::vector<std::string> current_stack, const operation& next_op);
  188. std::optional<int32_t> try_parse_int32(const std::string& str);
  189. struct parser_context {
  190. std::vector<std::shared_ptr<type>> types;
  191. std::vector<std::shared_ptr<operation>> operations;
  192. std::vector<std::shared_ptr<procedure_operation>> procedures;
  193. [[nodiscard]] std::shared_ptr<type> lookup_type(const std::string&) const;
  194. [[nodiscard]] std::shared_ptr<operation> lookup_operation(const std::string&) const;
  195. };
  196. struct generate_context {
  197. lexed_output lexer;
  198. parser_context parser;
  199. std::vector<std::shared_ptr<procedure_operation>> procedures;
  200. };
  201. generate_context parse(parser_context, const lexed_output&);
  202. std::vector<std::string> generate(const generate_context&);
  203. parser_context register_integers(parser_context);
  204. template<architecture_t Arch = architecture>
  205. parser_context register_i32_operations(parser_context);
  206. 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);
  207. }