pattern_match.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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/common/arena.h"
  7. #include "explorer/common/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 pattern " << *p << "\nfrom "
  59. << ExpressionCategoryToString(v.expression_category())
  60. << " expression with value " << *v.value() << "\n";
  61. }
  62. const auto make_expr_result =
  63. [](Nonnull<const Value*> v) -> ExpressionResult {
  64. if (const auto* expr_v = dyn_cast<ReferenceExpressionValue>(v)) {
  65. return ExpressionResult::Reference(expr_v->value(), expr_v->address());
  66. }
  67. return ExpressionResult::Value(v);
  68. };
  69. if (v.value()->kind() == Value::Kind::ReferenceExpressionValue) {
  70. return PatternMatch(p, make_expr_result(v.value()), source_loc, bindings,
  71. generic_args, trace_stream, arena);
  72. }
  73. switch (p->kind()) {
  74. case Value::Kind::BindingPlaceholderValue: {
  75. CARBON_CHECK(bindings.has_value());
  76. const auto& placeholder = cast<BindingPlaceholderValue>(*p);
  77. if (placeholder.value_node().has_value()) {
  78. InitializePlaceholderValue(*placeholder.value_node(), v, *bindings);
  79. }
  80. return true;
  81. }
  82. case Value::Kind::AddrValue: {
  83. const auto& addr = cast<AddrValue>(*p);
  84. CARBON_CHECK(v.value()->kind() == Value::Kind::LocationValue);
  85. const auto& location = cast<LocationValue>(*v.value());
  86. return PatternMatch(
  87. &addr.pattern(),
  88. ExpressionResult::Value(arena->New<PointerValue>(location.address())),
  89. source_loc, bindings, generic_args, trace_stream, arena);
  90. }
  91. case Value::Kind::VariableType: {
  92. const auto& var_type = cast<VariableType>(*p);
  93. generic_args[&var_type.binding()] = v.value();
  94. return true;
  95. }
  96. case Value::Kind::TupleType:
  97. case Value::Kind::TupleValue:
  98. switch (v.value()->kind()) {
  99. case Value::Kind::TupleType:
  100. case Value::Kind::TupleValue: {
  101. const auto& p_tup = cast<TupleValueBase>(*p);
  102. const auto& v_tup = cast<TupleValueBase>(*v.value());
  103. CARBON_CHECK(p_tup.elements().size() == v_tup.elements().size());
  104. for (size_t i = 0; i < p_tup.elements().size(); ++i) {
  105. if (!PatternMatch(p_tup.elements()[i],
  106. make_expr_result(v_tup.elements()[i]), source_loc,
  107. bindings, generic_args, trace_stream, arena)) {
  108. return false;
  109. }
  110. } // for
  111. return true;
  112. }
  113. case Value::Kind::UninitializedValue: {
  114. const auto& p_tup = cast<TupleValueBase>(*p);
  115. for (const auto& ele : p_tup.elements()) {
  116. if (!PatternMatch(ele,
  117. ExpressionResult::Value(
  118. arena->New<UninitializedValue>(ele)),
  119. source_loc, bindings, generic_args, trace_stream,
  120. arena)) {
  121. return false;
  122. }
  123. }
  124. return true;
  125. }
  126. default:
  127. CARBON_FATAL() << "expected a tuple value in pattern, not "
  128. << *v.value();
  129. }
  130. case Value::Kind::StructValue: {
  131. const auto& p_struct = cast<StructValue>(*p);
  132. const auto& v_struct = cast<StructValue>(*v.value());
  133. CARBON_CHECK(p_struct.elements().size() == v_struct.elements().size());
  134. for (size_t i = 0; i < p_struct.elements().size(); ++i) {
  135. CARBON_CHECK(p_struct.elements()[i].name ==
  136. v_struct.elements()[i].name);
  137. if (!PatternMatch(p_struct.elements()[i].value,
  138. ExpressionResult::Value(v_struct.elements()[i].value),
  139. source_loc, bindings, generic_args, trace_stream,
  140. arena)) {
  141. return false;
  142. }
  143. }
  144. return true;
  145. }
  146. case Value::Kind::AlternativeValue:
  147. switch (v.value()->kind()) {
  148. case Value::Kind::AlternativeValue: {
  149. const auto& p_alt = cast<AlternativeValue>(*p);
  150. const auto& v_alt = cast<AlternativeValue>(*v.value());
  151. if (&p_alt.alternative() != &v_alt.alternative()) {
  152. return false;
  153. }
  154. CARBON_CHECK(p_alt.argument().has_value() ==
  155. v_alt.argument().has_value());
  156. if (!p_alt.argument().has_value()) {
  157. return true;
  158. }
  159. return PatternMatch(
  160. *p_alt.argument(), ExpressionResult::Value(*v_alt.argument()),
  161. source_loc, bindings, generic_args, trace_stream, arena);
  162. }
  163. default:
  164. CARBON_FATAL() << "expected a choice alternative in pattern, not "
  165. << *v.value();
  166. }
  167. case Value::Kind::UninitializedValue:
  168. CARBON_FATAL() << "uninitialized value is not allowed in pattern "
  169. << *v.value();
  170. case Value::Kind::FunctionType:
  171. switch (v.value()->kind()) {
  172. case Value::Kind::FunctionType: {
  173. const auto& p_fn = cast<FunctionType>(*p);
  174. const auto& v_fn = cast<FunctionType>(*v.value());
  175. if (!PatternMatch(&p_fn.parameters(),
  176. ExpressionResult::Value(&v_fn.parameters()),
  177. source_loc, bindings, generic_args, trace_stream,
  178. arena)) {
  179. return false;
  180. }
  181. if (!PatternMatch(&p_fn.return_type(),
  182. ExpressionResult::Value(&v_fn.return_type()),
  183. source_loc, bindings, generic_args, trace_stream,
  184. arena)) {
  185. return false;
  186. }
  187. return true;
  188. }
  189. default:
  190. return false;
  191. }
  192. case Value::Kind::AutoType:
  193. // `auto` matches any type, without binding any new names. We rely
  194. // on the typechecker to ensure that `v.value()` is a type.
  195. return true;
  196. case Value::Kind::StaticArrayType: {
  197. switch (v.value()->kind()) {
  198. case Value::Kind::TupleType:
  199. case Value::Kind::TupleValue: {
  200. return true;
  201. }
  202. case Value::Kind::StaticArrayType: {
  203. const auto& v_arr = cast<StaticArrayType>(*v.value());
  204. return v_arr.has_size();
  205. }
  206. default:
  207. return false;
  208. }
  209. }
  210. default:
  211. return ValueEqual(p, v.value(), std::nullopt);
  212. }
  213. }
  214. } // namespace Carbon