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.

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