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:
Jeremy G. Siek
2022-03-02 15:58:45 -05:00
committed by GitHub
co-authored by josh11b Geoff Romer
parent 8f6e42d866
commit 7cce1bd124
43 changed files with 1722 additions and 441 deletions
@@ -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();
}