impl_scope.h 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  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. #ifndef EXECUTABLE_SEMANTICS_AST_IMPL_SCOPE_H_
  5. #define EXECUTABLE_SEMANTICS_AST_IMPL_SCOPE_H_
  6. #include "executable_semantics/ast/declaration.h"
  7. namespace Carbon {
  8. class Value;
  9. // The `ImplScope` class is responsible for mapping a type and
  10. // interface to the location of the witness table for the `impl` for
  11. // that type and interface. A scope may have parent scopes, whose
  12. // impls will also be visible in the child scope.
  13. //
  14. // There is typically one instance of `ImplScope` class per scope
  15. // because the impls that are visible for a given type and interface
  16. // can vary from scope to scope. For example, consider the `bar` and
  17. // `baz` methods in the following class C and nested class D.
  18. //
  19. // class C(U:! Type, T:! Type) {
  20. // class D(V:! Type where U is Fooable(T)) {
  21. // fn bar[me: Self](x: U, y : T) -> T{
  22. // return x.foo(y)
  23. // }
  24. // }
  25. // fn baz[me: Self](x: U, y : T) -> T {
  26. // return x.foo(y);
  27. // }
  28. // }
  29. //
  30. // The call to `x.foo` in `bar` is valid because the `U is Fooable(T)`
  31. // impl is visible in the body of `bar`. In contrast, the call to
  32. // `x.foo` in `baz` is not valid because there is no visible impl for
  33. // `U` and `Fooable` in that scope.
  34. class ImplScope {
  35. public:
  36. // Associates `iface` and `type` with the `impl` in this scope.
  37. void Add(Nonnull<const Value*> iface, Nonnull<const Value*> type,
  38. ValueNodeView impl);
  39. // Make `parent` a parent of this scope.
  40. // REQUIRES: `parent` is not already a parent of this scope.
  41. void AddParent(Nonnull<const ImplScope*> parent);
  42. // Returns the associated impl for the given `iface` and `type` in
  43. // the ancestor graph of this scope, or reports a compilation error
  44. // at `source_loc` there isn't exactly one matching impl.
  45. auto Resolve(Nonnull<const Value*> iface, Nonnull<const Value*> type,
  46. SourceLocation source_loc) const -> ValueNodeView;
  47. private:
  48. auto TryResolve(Nonnull<const Value*> iface_type, Nonnull<const Value*> type,
  49. SourceLocation source_loc) const
  50. -> std::optional<ValueNodeView>;
  51. auto ResolveHere(Nonnull<const Value*> iface_type,
  52. Nonnull<const Value*> impl_type,
  53. SourceLocation source_loc) const
  54. -> std::optional<ValueNodeView>;
  55. // The `Impl` struct is a key-value pair where the key is the
  56. // combination of a type and an interface, e.g., `List` and `Container`,
  57. // and the value is the result of statically resolving to the `impl`
  58. // for `List` as `Container`, which is an `ValueNodeView`. The generality
  59. // of `ValueNodeView` is needed (not just `ImplDeclaration`) because
  60. // inside a generic, we need to map, e.g., from `T` and `Container` to the
  61. // witness table that is passed into the generic.
  62. struct Impl {
  63. Nonnull<const Value*> interface;
  64. Nonnull<const Value*> type;
  65. ValueNodeView impl;
  66. };
  67. std::vector<Impl> impls_;
  68. std::vector<Nonnull<const ImplScope*>> parent_scopes_;
  69. };
  70. } // namespace Carbon
  71. #endif // EXECUTABLE_SEMANTICS_AST_IMPL_SCOPE_H_