Explorer: Mixin phase 1 (#2069)

* Replay changes from pre-force-push mixin branch

* Base MixinPseudoType off of the new InterfaceType

* Add more test cases.

Also removed an unnecessary check that would have already been
handled by the parser.

* WIP detect member clashes during mixing mixins

* Implement fuzzer changes

* Implement member name clash check when mixing mixins

* Modify parser and lexer for experimental mixin feature

* Add comments

* Update explorer/testdata/mixin/simple-mix-in-mixin.carbon

Co-authored-by: josh11b <josh11b@users.noreply.github.com>

* Update explorer/testdata/mixin/use-mixin-method-in-class-method.carbon

Co-authored-by: josh11b <josh11b@users.noreply.github.com>

* Make code review changes

Co-authored-by: josh11b <josh11b@users.noreply.github.com>
This commit is contained in:
Darshal Shetty
2022-09-06 17:08:05 -04:00
committed by GitHub
co-authored by josh11b
parent 661a3c3907
commit 037c99e2fb
30 changed files with 1219 additions and 28 deletions
+63
View File
@@ -400,6 +400,20 @@ void Value::Print(llvm::raw_ostream& out) const {
}
break;
}
case Value::Kind::MixinPseudoType: {
const auto& mixin_type = cast<MixinPseudoType>(*this);
out << "mixin ";
PrintNameWithBindings(out, &mixin_type.declaration(), mixin_type.args());
if (!mixin_type.witnesses().empty()) {
out << " witnesses ";
llvm::ListSeparator sep;
for (const auto& [impl_bind, witness] : mixin_type.witnesses()) {
out << sep << *witness;
}
}
// TODO: print the import interface
break;
}
case Value::Kind::InterfaceType: {
const auto& iface_type = cast<InterfaceType>(*this);
out << "interface ";
@@ -491,6 +505,14 @@ void Value::Print(llvm::raw_ostream& out) const {
case Value::Kind::TypeOfClassType:
out << "typeof(" << cast<TypeOfClassType>(*this).class_type() << ")";
break;
case Value::Kind::TypeOfMixinPseudoType:
out << "typeof("
<< cast<TypeOfMixinPseudoType>(*this)
.mixin_type()
.declaration()
.name()
<< ")";
break;
case Value::Kind::TypeOfInterfaceType:
out << "typeof("
<< cast<TypeOfInterfaceType>(*this)
@@ -731,6 +753,8 @@ auto TypeEqual(Nonnull<const Value*> t1, Nonnull<const Value*> t2,
case Value::Kind::MemberName:
case Value::Kind::TypeOfParameterizedEntityName:
case Value::Kind::TypeOfMemberName:
case Value::Kind::MixinPseudoType:
case Value::Kind::TypeOfMixinPseudoType:
CARBON_FATAL() << "TypeEqual used to compare non-type values\n"
<< *t1 << "\n"
<< *t2;
@@ -830,6 +854,7 @@ auto ValueStructurallyEqual(
case Value::Kind::AutoType:
case Value::Kind::StructType:
case Value::Kind::NominalClassType:
case Value::Kind::MixinPseudoType:
case Value::Kind::InterfaceType:
case Value::Kind::ConstraintType:
case Value::Kind::ImplWitness:
@@ -839,6 +864,7 @@ auto ValueStructurallyEqual(
case Value::Kind::VariableType:
case Value::Kind::StringType:
case Value::Kind::TypeOfClassType:
case Value::Kind::TypeOfMixinPseudoType:
case Value::Kind::TypeOfInterfaceType:
case Value::Kind::TypeOfConstraintType:
case Value::Kind::TypeOfChoiceType:
@@ -950,6 +976,43 @@ auto NominalClassType::FindFunction(std::string_view name) const
-> std::optional<Nonnull<const FunctionValue*>> {
for (const auto& member : declaration().members()) {
switch (member->kind()) {
case DeclarationKind::MixDeclaration: {
const auto& mix_decl = cast<MixDeclaration>(*member);
Nonnull<const MixinPseudoType*> mixin = &mix_decl.mixin_value();
const auto res = mixin->FindFunction(name);
if (res.has_value()) {
return res;
}
break;
}
case DeclarationKind::FunctionDeclaration: {
const auto& fun = cast<FunctionDeclaration>(*member);
if (fun.name() == name) {
return &cast<FunctionValue>(**fun.constant_value());
}
break;
}
default:
break;
}
}
return std::nullopt;
}
// TODO: Find out a way to remove code duplication
auto MixinPseudoType::FindFunction(const std::string_view& name) const
-> std::optional<Nonnull<const FunctionValue*>> {
for (const auto& member : declaration().members()) {
switch (member->kind()) {
case DeclarationKind::MixDeclaration: {
const auto& mix_decl = cast<MixDeclaration>(*member);
Nonnull<const MixinPseudoType*> mixin = &mix_decl.mixin_value();
const auto res = mixin->FindFunction(name);
if (res.has_value()) {
return res;
}
break;
}
case DeclarationKind::FunctionDeclaration: {
const auto& fun = cast<FunctionDeclaration>(*member);
if (fun.name() == name) {