pattern_match.cpp 8.8 KB

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