Skip to content

Commit 037c99e

Browse files
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 <[email protected]> * Update explorer/testdata/mixin/use-mixin-method-in-class-method.carbon Co-authored-by: josh11b <[email protected]> * Make code review changes Co-authored-by: josh11b <[email protected]>
1 parent 661a3c3 commit 037c99e

30 files changed

+1219
-28
lines changed

common/fuzzing/carbon.proto

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,20 @@ message AliasDeclaration {
389389
optional Expression target = 2;
390390
}
391391

392+
// EXPERIMENTAL MIXIN FEATURE
393+
message MixinDeclaration {
394+
optional string name = 1;
395+
repeated Declaration members = 2;
396+
// Type params not implemented yet
397+
// optional TuplePattern params = 3;
398+
optional GenericBinding self = 4;
399+
}
400+
401+
// EXPERIMENTAL MIXIN FEATURE
402+
message MixDeclaration {
403+
optional Expression mixin = 1;
404+
}
405+
392406
message Declaration {
393407
oneof kind {
394408
FunctionDeclaration function = 1;
@@ -399,6 +413,8 @@ message Declaration {
399413
ImplDeclaration impl = 6;
400414
AliasDeclaration alias = 7;
401415
LetDeclaration let = 8;
416+
MixinDeclaration mixin = 9;
417+
MixDeclaration mix = 10;
402418
}
403419
}
404420

common/fuzzing/proto_to_carbon.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,36 @@ static auto DeclarationToCarbon(const Fuzzing::Declaration& declaration,
721721
break;
722722
}
723723

724+
// EXPERIMENTAL MIXIN FEATURE
725+
case Fuzzing::Declaration::kMixin: {
726+
const auto& mixin_declaration = declaration.mixin();
727+
out << "__mixin ";
728+
IdentifierToCarbon(mixin_declaration.name(), out);
729+
730+
// type params are not implemented yet
731+
// if (mixin_declaration.has_params()) {
732+
// TuplePatternToCarbon(mixin_declaration.params(), out);
733+
//}
734+
735+
out << "{\n";
736+
for (const auto& member : mixin_declaration.members()) {
737+
DeclarationToCarbon(member, out);
738+
out << "\n";
739+
}
740+
out << "}";
741+
// TODO: need to handle interface.self()?
742+
break;
743+
}
744+
745+
// EXPERIMENTAL MIXIN FEATURE
746+
case Fuzzing::Declaration::kMix: {
747+
const auto& mix_declaration = declaration.mix();
748+
out << "__mix ";
749+
ExpressionToCarbon(mix_declaration.mixin(), out);
750+
out << ";";
751+
break;
752+
}
753+
724754
case Fuzzing::Declaration::kChoice: {
725755
const auto& choice = declaration.choice();
726756
out << "choice ";

explorer/ast/ast_rtti.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ abstract class Declaration : AstNode;
1616
class FunctionDeclaration : Declaration;
1717
class SelfDeclaration : Declaration;
1818
class ClassDeclaration : Declaration;
19+
class MixinDeclaration : Declaration;
20+
class MixDeclaration : Declaration;
1921
class ChoiceDeclaration : Declaration;
2022
class VariableDeclaration : Declaration;
2123
class InterfaceDeclaration : Declaration;

explorer/ast/declaration.cpp

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,22 @@ void Declaration::Print(llvm::raw_ostream& out) const {
5252
out << "}\n";
5353
break;
5454
}
55-
55+
case DeclarationKind::MixinDeclaration: {
56+
const auto& mixin_decl = cast<MixinDeclaration>(*this);
57+
PrintID(out);
58+
out << "{\n";
59+
for (Nonnull<Declaration*> m : mixin_decl.members()) {
60+
out << *m;
61+
}
62+
out << "}\n";
63+
break;
64+
}
65+
case DeclarationKind::MixDeclaration: {
66+
const auto& mix_decl = cast<MixDeclaration>(*this);
67+
PrintID(out);
68+
out << mix_decl.mixin() << ";";
69+
break;
70+
}
5671
case DeclarationKind::ChoiceDeclaration: {
5772
const auto& choice = cast<ChoiceDeclaration>(*this);
5873
PrintID(out);
@@ -122,7 +137,18 @@ void Declaration::PrintID(llvm::raw_ostream& out) const {
122137
out << "class " << class_decl.name();
123138
break;
124139
}
125-
140+
case DeclarationKind::MixinDeclaration: {
141+
const auto& mixin_decl = cast<MixinDeclaration>(*this);
142+
out << "__mixin " << mixin_decl.name();
143+
if (mixin_decl.self()->type().kind() != ExpressionKind::TypeTypeLiteral) {
144+
out << " for " << mixin_decl.self()->type();
145+
}
146+
break;
147+
}
148+
case DeclarationKind::MixDeclaration: {
149+
out << "__mix ";
150+
break;
151+
}
126152
case DeclarationKind::ChoiceDeclaration: {
127153
const auto& choice = cast<ChoiceDeclaration>(*this);
128154
out << "choice " << choice.name();
@@ -161,6 +187,12 @@ auto GetName(const Declaration& declaration)
161187
return cast<FunctionDeclaration>(declaration).name();
162188
case DeclarationKind::ClassDeclaration:
163189
return cast<ClassDeclaration>(declaration).name();
190+
case DeclarationKind::MixinDeclaration: {
191+
return cast<MixinDeclaration>(declaration).name();
192+
}
193+
case DeclarationKind::MixDeclaration: {
194+
return std::nullopt;
195+
}
164196
case DeclarationKind::ChoiceDeclaration:
165197
return cast<ChoiceDeclaration>(declaration).name();
166198
case DeclarationKind::InterfaceDeclaration:

explorer/ast/declaration.h

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
namespace Carbon {
2828

29+
class MixinPseudoType;
2930
class ConstraintType;
3031

3132
// Abstract base class of all AST nodes representing patterns.
@@ -233,6 +234,70 @@ class ClassDeclaration : public Declaration {
233234
std::vector<Nonnull<Declaration*>> members_;
234235
};
235236

237+
// EXPERIMENTAL MIXIN FEATURE
238+
class MixinDeclaration : public Declaration {
239+
public:
240+
using ImplementsCarbonValueNode = void;
241+
242+
MixinDeclaration(SourceLocation source_loc, std::string name,
243+
std::optional<Nonnull<TuplePattern*>> params,
244+
Nonnull<GenericBinding*> self,
245+
std::vector<Nonnull<Declaration*>> members)
246+
: Declaration(AstNodeKind::MixinDeclaration, source_loc),
247+
name_(std::move(name)),
248+
params_(std::move(params)),
249+
self_(self),
250+
members_(std::move(members)) {}
251+
252+
static auto classof(const AstNode* node) -> bool {
253+
return InheritsFromMixinDeclaration(node->kind());
254+
}
255+
256+
auto name() const -> const std::string& { return name_; }
257+
auto params() const -> std::optional<Nonnull<const TuplePattern*>> {
258+
return params_;
259+
}
260+
auto params() -> std::optional<Nonnull<TuplePattern*>> { return params_; }
261+
auto self() const -> Nonnull<const GenericBinding*> { return self_; }
262+
auto self() -> Nonnull<GenericBinding*> { return self_; }
263+
auto members() const -> llvm::ArrayRef<Nonnull<Declaration*>> {
264+
return members_;
265+
}
266+
267+
auto value_category() const -> ValueCategory { return ValueCategory::Let; }
268+
269+
private:
270+
std::string name_;
271+
std::optional<Nonnull<TuplePattern*>> params_;
272+
Nonnull<GenericBinding*> self_;
273+
std::vector<Nonnull<Declaration*>> members_;
274+
};
275+
276+
// EXPERIMENTAL MIXIN FEATURE
277+
class MixDeclaration : public Declaration {
278+
public:
279+
MixDeclaration(SourceLocation source_loc,
280+
std::optional<Nonnull<Expression*>> mixin_type)
281+
: Declaration(AstNodeKind::MixDeclaration, source_loc),
282+
mixin_(mixin_type) {}
283+
284+
static auto classof(const AstNode* node) -> bool {
285+
return InheritsFromMixDeclaration(node->kind());
286+
}
287+
288+
auto mixin() const -> const Expression& { return **mixin_; }
289+
auto mixin() -> Expression& { return **mixin_; }
290+
291+
auto mixin_value() const -> const MixinPseudoType& { return *mixin_value_; }
292+
void set_mixin_value(Nonnull<const MixinPseudoType*> mixin_value) {
293+
mixin_value_ = mixin_value;
294+
}
295+
296+
private:
297+
std::optional<Nonnull<Expression*>> mixin_;
298+
Nonnull<const MixinPseudoType*> mixin_value_;
299+
};
300+
236301
class AlternativeSignature : public AstNode {
237302
public:
238303
AlternativeSignature(SourceLocation source_loc, std::string name,

explorer/fuzzing/ast_to_proto.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,29 @@ static auto DeclarationToProto(const Declaration& declaration)
607607
break;
608608
}
609609

610+
case DeclarationKind::MixinDeclaration: {
611+
const auto& mixin = cast<MixinDeclaration>(declaration);
612+
auto* mixin_proto = declaration_proto.mutable_mixin();
613+
mixin_proto->set_name(mixin.name());
614+
for (const auto& member : mixin.members()) {
615+
*mixin_proto->add_members() = DeclarationToProto(*member);
616+
}
617+
// Type params not implemented yet
618+
// if (mixin.params().has_value()) {
619+
// *mixin_proto->mutable_params() =
620+
// TuplePatternToProto(**mixin.params());
621+
//}
622+
*mixin_proto->mutable_self() = GenericBindingToProto(*mixin.self());
623+
break;
624+
}
625+
626+
case DeclarationKind::MixDeclaration: {
627+
const auto& mix = cast<MixDeclaration>(declaration);
628+
auto* mix_proto = declaration_proto.mutable_mix();
629+
*mix_proto->mutable_mixin() = ExpressionToProto(mix.mixin());
630+
break;
631+
}
632+
610633
case DeclarationKind::ChoiceDeclaration: {
611634
const auto& choice = cast<ChoiceDeclaration>(declaration);
612635
auto* choice_proto = declaration_proto.mutable_choice();

explorer/interpreter/interpreter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,7 @@ auto Interpreter::Convert(Nonnull<const Value*> value,
625625
case Value::Kind::PointerType:
626626
case Value::Kind::AutoType:
627627
case Value::Kind::NominalClassType:
628+
case Value::Kind::MixinPseudoType:
628629
case Value::Kind::InterfaceType:
629630
case Value::Kind::ConstraintType:
630631
case Value::Kind::ImplWitness:
@@ -640,6 +641,7 @@ auto Interpreter::Convert(Nonnull<const Value*> value,
640641
case Value::Kind::StringType:
641642
case Value::Kind::StringValue:
642643
case Value::Kind::TypeOfClassType:
644+
case Value::Kind::TypeOfMixinPseudoType:
643645
case Value::Kind::TypeOfInterfaceType:
644646
case Value::Kind::TypeOfConstraintType:
645647
case Value::Kind::TypeOfChoiceType:
@@ -1824,6 +1826,8 @@ auto Interpreter::StepDeclaration() -> ErrorOr<Success> {
18241826
}
18251827
case DeclarationKind::FunctionDeclaration:
18261828
case DeclarationKind::ClassDeclaration:
1829+
case DeclarationKind::MixinDeclaration:
1830+
case DeclarationKind::MixDeclaration:
18271831
case DeclarationKind::ChoiceDeclaration:
18281832
case DeclarationKind::InterfaceDeclaration:
18291833
case DeclarationKind::AssociatedConstantDeclaration:

explorer/interpreter/resolve_control_flow.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,13 @@ auto ResolveControlFlow(Nonnull<Declaration*> declaration) -> ErrorOr<Success> {
154154
}
155155
break;
156156
}
157+
case DeclarationKind::MixinDeclaration: {
158+
auto& mixin_decl = cast<MixinDeclaration>(*declaration);
159+
for (Nonnull<Declaration*> member : mixin_decl.members()) {
160+
CARBON_RETURN_IF_ERROR(ResolveControlFlow(member));
161+
}
162+
break;
163+
}
157164
case DeclarationKind::InterfaceDeclaration: {
158165
auto& iface_decl = cast<InterfaceDeclaration>(*declaration);
159166
for (Nonnull<Declaration*> member : iface_decl.members()) {
@@ -173,6 +180,7 @@ auto ResolveControlFlow(Nonnull<Declaration*> declaration) -> ErrorOr<Success> {
173180
case DeclarationKind::AssociatedConstantDeclaration:
174181
case DeclarationKind::SelfDeclaration:
175182
case DeclarationKind::AliasDeclaration:
183+
case DeclarationKind::MixDeclaration:
176184
// do nothing
177185
break;
178186
}

explorer/interpreter/resolve_names.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,17 @@ static auto AddExposedNames(const Declaration& declaration,
4646
StaticScope::NameStatus::KnownButNotDeclared));
4747
break;
4848
}
49+
case DeclarationKind::MixinDeclaration: {
50+
auto& mixin_decl = cast<MixinDeclaration>(declaration);
51+
CARBON_RETURN_IF_ERROR(
52+
enclosing_scope.Add(mixin_decl.name(), &mixin_decl,
53+
StaticScope::NameStatus::KnownButNotDeclared));
54+
break;
55+
}
56+
case DeclarationKind::MixDeclaration: {
57+
// Nothing to do here
58+
break;
59+
}
4960
case DeclarationKind::ChoiceDeclaration: {
5061
auto& choice = cast<ChoiceDeclaration>(declaration);
5162
CARBON_RETURN_IF_ERROR(
@@ -560,6 +571,26 @@ static auto ResolveNames(Declaration& declaration, StaticScope& enclosing_scope,
560571
ResolveMemberNames(class_decl.members(), class_scope, bodies));
561572
break;
562573
}
574+
case DeclarationKind::MixinDeclaration: {
575+
auto& mixin_decl = cast<MixinDeclaration>(declaration);
576+
StaticScope mixin_scope;
577+
mixin_scope.AddParent(&enclosing_scope);
578+
enclosing_scope.MarkDeclared(mixin_decl.name());
579+
if (mixin_decl.params().has_value()) {
580+
CARBON_RETURN_IF_ERROR(
581+
ResolveNames(**mixin_decl.params(), mixin_scope));
582+
}
583+
enclosing_scope.MarkUsable(mixin_decl.name());
584+
CARBON_RETURN_IF_ERROR(mixin_scope.Add("Self", mixin_decl.self()));
585+
CARBON_RETURN_IF_ERROR(
586+
ResolveMemberNames(mixin_decl.members(), mixin_scope, bodies));
587+
break;
588+
}
589+
case DeclarationKind::MixDeclaration: {
590+
auto& mix_decl = cast<MixDeclaration>(declaration);
591+
CARBON_RETURN_IF_ERROR(ResolveNames(mix_decl.mixin(), enclosing_scope));
592+
break;
593+
}
563594
case DeclarationKind::ChoiceDeclaration: {
564595
auto& choice = cast<ChoiceDeclaration>(declaration);
565596
StaticScope choice_scope;

explorer/interpreter/resolve_unformed.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ static auto ResolveUnformed(Nonnull<const Declaration*> declaration)
294294
break;
295295
}
296296
case DeclarationKind::ClassDeclaration:
297+
case DeclarationKind::MixDeclaration:
298+
case DeclarationKind::MixinDeclaration:
297299
case DeclarationKind::InterfaceDeclaration:
298300
case DeclarationKind::ImplDeclaration:
299301
case DeclarationKind::ChoiceDeclaration:

0 commit comments

Comments
 (0)