mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-25 13:40:12 +01:00
interfaces, impls, and constrained generics (basics) (#1073)
* interfaces, impls, and constrained generics (basics) * separate type checking into declare vs. type check, removing redundancy * external impls * added impl scopes to handle generics calling generics * cleanup * more cleanup * Update executable_semantics/testdata/interface/external_impl_point_vector.carbon Co-authored-by: josh11b <josh11b@users.noreply.github.com> * Update executable_semantics/testdata/interface/generic_call_generic.carbon Co-authored-by: josh11b <josh11b@users.noreply.github.com> * Update executable_semantics/testdata/interface/tuple_vector_add_scale.carbon Co-authored-by: josh11b <josh11b@users.noreply.github.com> * Update executable_semantics/testdata/interface/vector_point_add_scale.carbon Co-authored-by: josh11b <josh11b@users.noreply.github.com> * change ImplementationDeclaration to ImplDeclaration * remove impl_type_value * split NamedEntity into two * changed GetName to be a free function * adding comments * more edits to respond to review * introduce ImplBinding, remove punning on GenericBinding * new test case and some minor edits * refactor GetMember and GetField to move impl logic to interpreter * remove commennt * change EntityView to ImplBinding in FieldAccess... * move ImplBinding * review response * added example to impl_scope.h * minor edits * Update executable_semantics/interpreter/field_path.h Co-authored-by: Geoff Romer <gromer@google.com> * Update executable_semantics/interpreter/value.cpp Co-authored-by: Geoff Romer <gromer@google.com> * Update executable_semantics/interpreter/interpreter.cpp Co-authored-by: Geoff Romer <gromer@google.com> * Update executable_semantics/ast/expression.h Co-authored-by: Geoff Romer <gromer@google.com> * Update executable_semantics/ast/expression.h Co-authored-by: Geoff Romer <gromer@google.com> * Update executable_semantics/ast/generic_binding.h Co-authored-by: Geoff Romer <gromer@google.com> * more edits from review * review response * Update executable_semantics/ast/static_scope.h Co-authored-by: Geoff Romer <gromer@google.com> * remove ImplType, renamed node_view to value_node Co-authored-by: josh11b <josh11b@users.noreply.github.com> Co-authored-by: Geoff Romer <gromer@google.com>
This commit is contained in:
committed by
GitHub
co-authored by
josh11b
Geoff Romer
parent
8f6e42d866
commit
7cce1bd124
@@ -17,6 +17,7 @@
|
||||
#include "executable_semantics/common/arena.h"
|
||||
#include "executable_semantics/common/error.h"
|
||||
#include "executable_semantics/interpreter/action.h"
|
||||
#include "executable_semantics/interpreter/action_stack.h"
|
||||
#include "executable_semantics/interpreter/stack.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
@@ -183,8 +184,8 @@ auto PatternMatch(Nonnull<const Value*> p, Nonnull<const Value*> v,
|
||||
<< "Name bindings are not supported in this context";
|
||||
}
|
||||
const auto& placeholder = cast<BindingPlaceholderValue>(*p);
|
||||
if (placeholder.named_entity().has_value()) {
|
||||
(*bindings)->Initialize(*placeholder.named_entity(), v);
|
||||
if (placeholder.value_node().has_value()) {
|
||||
(*bindings)->Initialize(*placeholder.value_node(), v);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -275,8 +276,8 @@ void Interpreter::StepLvalue() {
|
||||
case ExpressionKind::IdentifierExpression: {
|
||||
// { {x :: C, E, F} :: S, H}
|
||||
// -> { {E(x) :: C, E, F} :: S, H}
|
||||
Nonnull<const Value*> value = todo_.ValueOfName(
|
||||
cast<IdentifierExpression>(exp).named_entity(), exp.source_loc());
|
||||
Nonnull<const Value*> value = todo_.ValueOfNode(
|
||||
cast<IdentifierExpression>(exp).value_node(), exp.source_loc());
|
||||
CHECK(isa<LValue>(value)) << *value;
|
||||
return todo_.FinishAction(value);
|
||||
}
|
||||
@@ -371,6 +372,8 @@ auto Interpreter::Convert(Nonnull<const Value*> value,
|
||||
case Value::Kind::AutoType:
|
||||
case Value::Kind::StructType:
|
||||
case Value::Kind::NominalClassType:
|
||||
case Value::Kind::InterfaceType:
|
||||
case Value::Kind::Witness:
|
||||
case Value::Kind::ChoiceType:
|
||||
case Value::Kind::ContinuationType:
|
||||
case Value::Kind::VariableType:
|
||||
@@ -380,6 +383,7 @@ auto Interpreter::Convert(Nonnull<const Value*> value,
|
||||
case Value::Kind::StringType:
|
||||
case Value::Kind::StringValue:
|
||||
case Value::Kind::TypeOfClassType:
|
||||
case Value::Kind::TypeOfInterfaceType:
|
||||
case Value::Kind::TypeOfChoiceType:
|
||||
// TODO: add `CHECK(TypeEqual(type, value->dynamic_type()))`, once we
|
||||
// have Value::dynamic_type.
|
||||
@@ -497,8 +501,18 @@ void Interpreter::StepExp() {
|
||||
} else {
|
||||
// { { v :: [].f :: C, E, F} :: S, H}
|
||||
// -> { { v_f :: C, E, F} : S, H}
|
||||
return todo_.FinishAction(act.results()[0]->GetField(
|
||||
arena_, FieldPath(access.field()), exp.source_loc()));
|
||||
std::optional<Nonnull<const Witness*>> witness = std::nullopt;
|
||||
if (access.impl().has_value()) {
|
||||
auto witness_addr =
|
||||
todo_.ValueOfNode(*access.impl(), access.source_loc());
|
||||
witness = cast<Witness>(
|
||||
heap_.Read(llvm::cast<LValue>(witness_addr)->address(),
|
||||
access.source_loc()));
|
||||
}
|
||||
FieldPath::Component field(access.field(), witness);
|
||||
Nonnull<const Value*> member = act.results()[0]->GetField(
|
||||
arena_, FieldPath(field), exp.source_loc());
|
||||
return todo_.FinishAction(member);
|
||||
}
|
||||
}
|
||||
case ExpressionKind::IdentifierExpression: {
|
||||
@@ -506,7 +520,7 @@ void Interpreter::StepExp() {
|
||||
const auto& ident = cast<IdentifierExpression>(exp);
|
||||
// { {x :: C, E, F} :: S, H} -> { {H(E(x)) :: C, E, F} :: S, H}
|
||||
Nonnull<const Value*> value =
|
||||
todo_.ValueOfName(ident.named_entity(), ident.source_loc());
|
||||
todo_.ValueOfNode(ident.value_node(), ident.source_loc());
|
||||
if (const auto* lvalue = dyn_cast<LValue>(value)) {
|
||||
value = heap_.Read(lvalue->address(), exp.source_loc());
|
||||
}
|
||||
@@ -567,6 +581,17 @@ void Interpreter::StepExp() {
|
||||
Nonnull<const Value*> converted_args = Convert(
|
||||
act.results()[1], &function.param_pattern().static_type());
|
||||
RuntimeScope function_scope(&heap_);
|
||||
// Bring the impl witness tables into scope.
|
||||
for (const auto& [impl_bind, impl_node] :
|
||||
cast<CallExpression>(exp).impls()) {
|
||||
Nonnull<const Value*> witness =
|
||||
todo_.ValueOfNode(impl_node, exp.source_loc());
|
||||
if (witness->kind() == Value::Kind::LValue) {
|
||||
const LValue& lval = cast<LValue>(*witness);
|
||||
witness = heap_.Read(lval.address(), exp.source_loc());
|
||||
}
|
||||
function_scope.Initialize(impl_bind, witness);
|
||||
}
|
||||
CHECK(PatternMatch(&function.param_pattern().value(),
|
||||
converted_args, exp.source_loc(),
|
||||
&function_scope));
|
||||
@@ -649,7 +674,7 @@ void Interpreter::StepExp() {
|
||||
// -> { fn pt -> rt :: {C, E, F} :: S, H}
|
||||
return todo_.FinishAction(arena_->New<FunctionType>(
|
||||
std::vector<Nonnull<const GenericBinding*>>(), act.results()[0],
|
||||
act.results()[1]));
|
||||
act.results()[1], std::vector<Nonnull<const ImplBinding*>>()));
|
||||
}
|
||||
}
|
||||
case ExpressionKind::ContinuationTypeLiteral: {
|
||||
@@ -963,6 +988,8 @@ void Interpreter::StepDeclaration() {
|
||||
case DeclarationKind::FunctionDeclaration:
|
||||
case DeclarationKind::ClassDeclaration:
|
||||
case DeclarationKind::ChoiceDeclaration:
|
||||
case DeclarationKind::InterfaceDeclaration:
|
||||
case DeclarationKind::ImplDeclaration:
|
||||
// These declarations have no run-time effects.
|
||||
return todo_.FinishAction();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user