pattern_match.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "explorer/interpreter/pattern_match.h"
  5. #include <algorithm>
  6. #include "explorer/ast/value.h"
  7. #include "explorer/base/arena.h"
  8. #include "explorer/base/trace_stream.h"
  9. #include "explorer/interpreter/action.h"
  10. #include "explorer/interpreter/type_utils.h"
  11. #include "llvm/Support/Casting.h"
  12. using llvm::cast;
  13. using llvm::dyn_cast;
  14. namespace Carbon {
  15. static auto InitializePlaceholderValue(const ValueNodeView& value_node,
  16. ExpressionResult v,
  17. Nonnull<RuntimeScope*> bindings) {
  18. switch (value_node.expression_category()) {
  19. case ExpressionCategory::Reference:
  20. if (v.expression_category() == ExpressionCategory::Value ||
  21. v.expression_category() == ExpressionCategory::Reference) {
  22. // Build by copying from value or reference expression.
  23. bindings->Initialize(value_node, v.value());
  24. } else {
  25. // Location initialized by initializing expression, bind node to
  26. // address.
  27. CARBON_CHECK(v.address())
  28. << "Missing location from initializing expression";
  29. bindings->Bind(value_node, *v.address());
  30. }
  31. break;
  32. case ExpressionCategory::Value:
  33. if (v.expression_category() == ExpressionCategory::Value) {
  34. // We assume values are strictly nested for now.
  35. bindings->BindValue(value_node, v.value());
  36. } else if (v.expression_category() == ExpressionCategory::Reference) {
  37. // Bind the reference expression value directly.
  38. CARBON_CHECK(v.address())
  39. << "Missing location from reference expression";
  40. bindings->BindAndPin(value_node, *v.address());
  41. } else {
  42. // Location initialized by initializing expression, bind node to
  43. // address.
  44. CARBON_CHECK(v.address())
  45. << "Missing location from initializing expression";
  46. bindings->Bind(value_node, *v.address());
  47. }
  48. break;
  49. case ExpressionCategory::Initializing:
  50. CARBON_FATAL() << "Cannot pattern match an initializing expression";
  51. break;
  52. }
  53. }
  54. auto PatternMatch(Nonnull<const Value*> p, ExpressionResult v,
  55. SourceLocation source_loc,
  56. std::optional<Nonnull<RuntimeScope*>> bindings,
  57. BindingMap& generic_args, Nonnull<TraceStream*> trace_stream,
  58. Nonnull<Arena*> arena) -> bool {
  59. if (trace_stream->is_enabled()) {
  60. trace_stream->Match() << "match pattern `" << *p << "`\n";
  61. trace_stream->Indent() << "from "
  62. << ExpressionCategoryToString(
  63. v.expression_category())
  64. << " expression with value `" << *v.value() << "`\n";
  65. }
  66. const auto make_expr_result =
  67. [](Nonnull<const Value*> v) -> ExpressionResult {
  68. if (const auto* expr_v = dyn_cast<ReferenceExpressionValue>(v)) {
  69. return ExpressionResult::Reference(expr_v->value(), expr_v->address());
  70. }
  71. return ExpressionResult::Value(v);
  72. };
  73. if (v.value()->kind() == Value::Kind::ReferenceExpressionValue) {
  74. return PatternMatch(p, make_expr_result(v.value()), source_loc, bindings,
  75. generic_args, trace_stream, arena);
  76. }
  77. switch (p->kind()) {
  78. case Value::Kind::BindingPlaceholderValue: {
  79. CARBON_CHECK(bindings.has_value());
  80. const auto& placeholder = cast<BindingPlaceholderValue>(*p);
  81. if (placeholder.value_node().has_value()) {
  82. InitializePlaceholderValue(*placeholder.value_node(), v, *bindings);
  83. }
  84. return true;
  85. }
  86. case Value::Kind::AddrValue: {
  87. const auto& addr = cast<AddrValue>(*p);
  88. CARBON_CHECK(v.value()->kind() == Value::Kind::LocationValue);
  89. const auto& location = cast<LocationValue>(*v.value());
  90. return PatternMatch(
  91. &addr.pattern(),
  92. ExpressionResult::Value(arena->New<PointerValue>(location.address())),
  93. source_loc, bindings, generic_args, trace_stream, arena);
  94. }
  95. case Value::Kind::VariableType: {
  96. const auto& var_type = cast<VariableType>(*p);
  97. generic_args[&var_type.binding()] = v.value();
  98. return true;
  99. }
  100. case Value::Kind::TupleType:
  101. case Value::Kind::TupleValue:
  102. switch (v.value()->kind()) {
  103. case Value::Kind::TupleType:
  104. case Value::Kind::TupleValue: {
  105. const auto& p_tup = cast<TupleValueBase>(*p);
  106. const auto& v_tup = cast<TupleValueBase>(*v.value());
  107. CARBON_CHECK(p_tup.elements().size() == v_tup.elements().size());
  108. for (size_t i = 0; i < p_tup.elements().size(); ++i) {
  109. if (!PatternMatch(p_tup.elements()[i],
  110. make_expr_result(v_tup.elements()[i]), source_loc,
  111. bindings, generic_args, trace_stream, arena)) {
  112. return false;
  113. }
  114. } // for
  115. return true;
  116. }
  117. case Value::Kind::UninitializedValue: {
  118. const auto& p_tup = cast<TupleValueBase>(*p);
  119. for (const auto& ele : p_tup.elements()) {
  120. if (!PatternMatch(ele,
  121. ExpressionResult::Value(
  122. arena->New<UninitializedValue>(ele)),
  123. source_loc, bindings, generic_args, trace_stream,
  124. arena)) {
  125. return false;
  126. }
  127. }
  128. return true;
  129. }
  130. default:
  131. CARBON_FATAL() << "expected a tuple value in pattern, not "
  132. << *v.value();
  133. }
  134. case Value::Kind::StructValue: {
  135. const auto& p_struct = cast<StructValue>(*p);
  136. const auto& v_struct = cast<StructValue>(*v.value());
  137. CARBON_CHECK(p_struct.elements().size() == v_struct.elements().size());
  138. for (size_t i = 0; i < p_struct.elements().size(); ++i) {
  139. CARBON_CHECK(p_struct.elements()[i].name ==
  140. v_struct.elements()[i].name);
  141. if (!PatternMatch(p_struct.elements()[i].value,
  142. ExpressionResult::Value(v_struct.elements()[i].value),
  143. source_loc, bindings, generic_args, trace_stream,
  144. arena)) {
  145. return false;
  146. }
  147. }
  148. return true;
  149. }
  150. case Value::Kind::AlternativeValue:
  151. switch (v.value()->kind()) {
  152. case Value::Kind::AlternativeValue: {
  153. const auto& p_alt = cast<AlternativeValue>(*p);
  154. const auto& v_alt = cast<AlternativeValue>(*v.value());
  155. if (&p_alt.alternative() != &v_alt.alternative()) {
  156. return false;
  157. }
  158. CARBON_CHECK(p_alt.argument().has_value() ==
  159. v_alt.argument().has_value());
  160. if (!p_alt.argument().has_value()) {
  161. return true;
  162. }
  163. return PatternMatch(
  164. *p_alt.argument(), ExpressionResult::Value(*v_alt.argument()),
  165. source_loc, bindings, generic_args, trace_stream, arena);
  166. }
  167. default:
  168. CARBON_FATAL() << "expected a choice alternative in pattern, not "
  169. << *v.value();
  170. }
  171. case Value::Kind::UninitializedValue:
  172. CARBON_FATAL() << "uninitialized value is not allowed in pattern "
  173. << *v.value();
  174. case Value::Kind::FunctionType:
  175. switch (v.value()->kind()) {
  176. case Value::Kind::FunctionType: {
  177. const auto& p_fn = cast<FunctionType>(*p);
  178. const auto& v_fn = cast<FunctionType>(*v.value());
  179. if (!PatternMatch(&p_fn.parameters(),
  180. ExpressionResult::Value(&v_fn.parameters()),
  181. source_loc, bindings, generic_args, trace_stream,
  182. arena)) {
  183. return false;
  184. }
  185. if (!PatternMatch(&p_fn.return_type(),
  186. ExpressionResult::Value(&v_fn.return_type()),
  187. source_loc, bindings, generic_args, trace_stream,
  188. arena)) {
  189. return false;
  190. }
  191. return true;
  192. }
  193. default:
  194. return false;
  195. }
  196. case Value::Kind::AutoType:
  197. // `auto` matches any type, without binding any new names. We rely
  198. // on the typechecker to ensure that `v.value()` is a type.
  199. return true;
  200. case Value::Kind::StaticArrayType: {
  201. const auto& p_arr = cast<StaticArrayType>(*p);
  202. switch (v.value()->kind()) {
  203. case Value::Kind::TupleType:
  204. case Value::Kind::TupleValue: {
  205. const auto& v_tup = cast<TupleValueBase>(*v.value());
  206. if (v_tup.elements().empty()) {
  207. return !TypeIsDeduceable(&p_arr.element_type());
  208. }
  209. std::vector<Nonnull<const Value*>> deduced_types;
  210. deduced_types.reserve(v_tup.elements().size());
  211. for (const auto& tup_elem : v_tup.elements()) {
  212. if (!PatternMatch(&p_arr.element_type(), make_expr_result(tup_elem),
  213. source_loc, bindings, generic_args, trace_stream,
  214. arena)) {
  215. return false;
  216. }
  217. deduced_types.emplace_back(
  218. DeducePatternType(&p_arr.element_type(), tup_elem, arena));
  219. } // for
  220. return std::adjacent_find(deduced_types.begin(), deduced_types.end(),
  221. [](const auto& lhs, const auto& rhs) {
  222. return !TypeEqual(lhs, rhs, std::nullopt);
  223. }) == deduced_types.end();
  224. }
  225. case Value::Kind::StaticArrayType: {
  226. const auto& v_arr = cast<StaticArrayType>(*v.value());
  227. if (!v_arr.has_size()) {
  228. return false;
  229. }
  230. return PatternMatch(
  231. &p_arr.element_type(), make_expr_result(&v_arr.element_type()),
  232. source_loc, bindings, generic_args, trace_stream, arena);
  233. }
  234. default:
  235. return false;
  236. }
  237. }
  238. default:
  239. return ValueEqual(p, v.value(), std::nullopt);
  240. }
  241. }
  242. } // namespace Carbon