pattern_match.cpp 10 KB

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