Basic support for parameterized interfaces. (#1220)

To make this work, introduce impl bindings into scope immediately when type-checking. We may rely on their existence before we finish type-checking the enclosing pattern.
This commit is contained in:
Richard Smith
2022-04-29 12:42:15 -07:00
committed by GitHub
parent b9538129a2
commit 3b58a1bf48
15 changed files with 513 additions and 197 deletions
@@ -633,20 +633,37 @@ auto Interpreter::CallFunction(const CallExpression& call,
const ClassDeclaration& class_decl = class_type.declaration();
RuntimeScope type_params_scope(&heap_);
BindingMap generic_args;
if (class_decl.type_params().has_value()) {
CHECK(PatternMatch(&(*class_decl.type_params())->value(), arg,
call.source_loc(), &type_params_scope, generic_args,
trace_stream_));
switch (phase()) {
case Phase::RunTime:
return todo_.FinishAction(arena_->New<NominalClassType>(
&class_type.declaration(), generic_args, witnesses));
case Phase::CompileTime:
return todo_.FinishAction(arena_->New<NominalClassType>(
&class_type.declaration(), generic_args, call.impls()));
}
} else {
FATAL() << "instantiation of non-generic class " << class_type;
CHECK(class_decl.type_params().has_value())
<< "instantiation of non-generic class " << class_type;
CHECK(PatternMatch(&(*class_decl.type_params())->value(), arg,
call.source_loc(), &type_params_scope, generic_args,
trace_stream_));
switch (phase()) {
case Phase::RunTime:
return todo_.FinishAction(arena_->New<NominalClassType>(
&class_decl, generic_args, witnesses));
case Phase::CompileTime:
return todo_.FinishAction(arena_->New<NominalClassType>(
&class_decl, generic_args, call.impls()));
}
}
case Value::Kind::InterfaceType: {
const InterfaceType& iface_type = cast<InterfaceType>(*fun);
const InterfaceDeclaration& iface_decl = iface_type.declaration();
RuntimeScope params_scope(&heap_);
BindingMap generic_args;
CHECK(iface_decl.params().has_value())
<< "call of unparameterized interface " << iface_type;
CHECK(PatternMatch(&(*iface_decl.params())->value(), arg,
call.source_loc(), &params_scope, generic_args,
trace_stream_));
switch (phase()) {
case Phase::RunTime:
return todo_.FinishAction(
arena_->New<InterfaceType>(&iface_decl, generic_args, witnesses));
case Phase::CompileTime:
return todo_.FinishAction(arena_->New<InterfaceType>(
&iface_decl, generic_args, call.impls()));
}
}
default: