Skip to content

Explorer: Mixin phase 1 #2069

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Sep 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions common/fuzzing/carbon.proto
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,20 @@ message AliasDeclaration {
optional Expression target = 2;
}

// EXPERIMENTAL MIXIN FEATURE
message MixinDeclaration {
optional string name = 1;
repeated Declaration members = 2;
// Type params not implemented yet
// optional TuplePattern params = 3;
optional GenericBinding self = 4;
}

// EXPERIMENTAL MIXIN FEATURE
message MixDeclaration {
optional Expression mixin = 1;
}

message Declaration {
oneof kind {
FunctionDeclaration function = 1;
Expand All @@ -399,6 +413,8 @@ message Declaration {
ImplDeclaration impl = 6;
AliasDeclaration alias = 7;
LetDeclaration let = 8;
MixinDeclaration mixin = 9;
MixDeclaration mix = 10;
}
}

Expand Down
30 changes: 30 additions & 0 deletions common/fuzzing/proto_to_carbon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,36 @@ static auto DeclarationToCarbon(const Fuzzing::Declaration& declaration,
break;
}

// EXPERIMENTAL MIXIN FEATURE
case Fuzzing::Declaration::kMixin: {
const auto& mixin_declaration = declaration.mixin();
out << "__mixin ";
IdentifierToCarbon(mixin_declaration.name(), out);

// type params are not implemented yet
// if (mixin_declaration.has_params()) {
// TuplePatternToCarbon(mixin_declaration.params(), out);
//}

out << "{\n";
for (const auto& member : mixin_declaration.members()) {
DeclarationToCarbon(member, out);
out << "\n";
}
out << "}";
// TODO: need to handle interface.self()?
break;
}

// EXPERIMENTAL MIXIN FEATURE
case Fuzzing::Declaration::kMix: {
const auto& mix_declaration = declaration.mix();
out << "__mix ";
ExpressionToCarbon(mix_declaration.mixin(), out);
out << ";";
break;
}

case Fuzzing::Declaration::kChoice: {
const auto& choice = declaration.choice();
out << "choice ";
Expand Down
2 changes: 2 additions & 0 deletions explorer/ast/ast_rtti.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ abstract class Declaration : AstNode;
class FunctionDeclaration : Declaration;
class SelfDeclaration : Declaration;
class ClassDeclaration : Declaration;
class MixinDeclaration : Declaration;
class MixDeclaration : Declaration;
class ChoiceDeclaration : Declaration;
class VariableDeclaration : Declaration;
class InterfaceDeclaration : Declaration;
Expand Down
36 changes: 34 additions & 2 deletions explorer/ast/declaration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,22 @@ void Declaration::Print(llvm::raw_ostream& out) const {
out << "}\n";
break;
}

case DeclarationKind::MixinDeclaration: {
const auto& mixin_decl = cast<MixinDeclaration>(*this);
PrintID(out);
out << "{\n";
for (Nonnull<Declaration*> m : mixin_decl.members()) {
out << *m;
}
out << "}\n";
break;
}
case DeclarationKind::MixDeclaration: {
const auto& mix_decl = cast<MixDeclaration>(*this);
PrintID(out);
out << mix_decl.mixin() << ";";
break;
}
case DeclarationKind::ChoiceDeclaration: {
const auto& choice = cast<ChoiceDeclaration>(*this);
PrintID(out);
Expand Down Expand Up @@ -122,7 +137,18 @@ void Declaration::PrintID(llvm::raw_ostream& out) const {
out << "class " << class_decl.name();
break;
}

case DeclarationKind::MixinDeclaration: {
const auto& mixin_decl = cast<MixinDeclaration>(*this);
out << "__mixin " << mixin_decl.name();
if (mixin_decl.self()->type().kind() != ExpressionKind::TypeTypeLiteral) {
out << " for " << mixin_decl.self()->type();
}
break;
}
case DeclarationKind::MixDeclaration: {
out << "__mix ";
break;
}
case DeclarationKind::ChoiceDeclaration: {
const auto& choice = cast<ChoiceDeclaration>(*this);
out << "choice " << choice.name();
Expand Down Expand Up @@ -161,6 +187,12 @@ auto GetName(const Declaration& declaration)
return cast<FunctionDeclaration>(declaration).name();
case DeclarationKind::ClassDeclaration:
return cast<ClassDeclaration>(declaration).name();
case DeclarationKind::MixinDeclaration: {
return cast<MixinDeclaration>(declaration).name();
}
case DeclarationKind::MixDeclaration: {
return std::nullopt;
}
case DeclarationKind::ChoiceDeclaration:
return cast<ChoiceDeclaration>(declaration).name();
case DeclarationKind::InterfaceDeclaration:
Expand Down
65 changes: 65 additions & 0 deletions explorer/ast/declaration.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

namespace Carbon {

class MixinPseudoType;
class ConstraintType;

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

// EXPERIMENTAL MIXIN FEATURE
class MixinDeclaration : public Declaration {
public:
using ImplementsCarbonValueNode = void;

MixinDeclaration(SourceLocation source_loc, std::string name,
std::optional<Nonnull<TuplePattern*>> params,
Nonnull<GenericBinding*> self,
std::vector<Nonnull<Declaration*>> members)
: Declaration(AstNodeKind::MixinDeclaration, source_loc),
name_(std::move(name)),
params_(std::move(params)),
self_(self),
members_(std::move(members)) {}

static auto classof(const AstNode* node) -> bool {
return InheritsFromMixinDeclaration(node->kind());
}

auto name() const -> const std::string& { return name_; }
auto params() const -> std::optional<Nonnull<const TuplePattern*>> {
return params_;
}
auto params() -> std::optional<Nonnull<TuplePattern*>> { return params_; }
auto self() const -> Nonnull<const GenericBinding*> { return self_; }
auto self() -> Nonnull<GenericBinding*> { return self_; }
auto members() const -> llvm::ArrayRef<Nonnull<Declaration*>> {
return members_;
}

auto value_category() const -> ValueCategory { return ValueCategory::Let; }

private:
std::string name_;
std::optional<Nonnull<TuplePattern*>> params_;
Nonnull<GenericBinding*> self_;
std::vector<Nonnull<Declaration*>> members_;
};

// EXPERIMENTAL MIXIN FEATURE
class MixDeclaration : public Declaration {
public:
MixDeclaration(SourceLocation source_loc,
std::optional<Nonnull<Expression*>> mixin_type)
: Declaration(AstNodeKind::MixDeclaration, source_loc),
mixin_(mixin_type) {}

static auto classof(const AstNode* node) -> bool {
return InheritsFromMixDeclaration(node->kind());
}

auto mixin() const -> const Expression& { return **mixin_; }
auto mixin() -> Expression& { return **mixin_; }

auto mixin_value() const -> const MixinPseudoType& { return *mixin_value_; }
void set_mixin_value(Nonnull<const MixinPseudoType*> mixin_value) {
mixin_value_ = mixin_value;
}

private:
std::optional<Nonnull<Expression*>> mixin_;
Nonnull<const MixinPseudoType*> mixin_value_;
};

class AlternativeSignature : public AstNode {
public:
AlternativeSignature(SourceLocation source_loc, std::string name,
Expand Down
23 changes: 23 additions & 0 deletions explorer/fuzzing/ast_to_proto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,29 @@ static auto DeclarationToProto(const Declaration& declaration)
break;
}

case DeclarationKind::MixinDeclaration: {
const auto& mixin = cast<MixinDeclaration>(declaration);
auto* mixin_proto = declaration_proto.mutable_mixin();
mixin_proto->set_name(mixin.name());
for (const auto& member : mixin.members()) {
*mixin_proto->add_members() = DeclarationToProto(*member);
}
// Type params not implemented yet
// if (mixin.params().has_value()) {
// *mixin_proto->mutable_params() =
// TuplePatternToProto(**mixin.params());
//}
*mixin_proto->mutable_self() = GenericBindingToProto(*mixin.self());
break;
}

case DeclarationKind::MixDeclaration: {
const auto& mix = cast<MixDeclaration>(declaration);
auto* mix_proto = declaration_proto.mutable_mix();
*mix_proto->mutable_mixin() = ExpressionToProto(mix.mixin());
break;
}

case DeclarationKind::ChoiceDeclaration: {
const auto& choice = cast<ChoiceDeclaration>(declaration);
auto* choice_proto = declaration_proto.mutable_choice();
Expand Down
4 changes: 4 additions & 0 deletions explorer/interpreter/interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,7 @@ auto Interpreter::Convert(Nonnull<const Value*> value,
case Value::Kind::PointerType:
case Value::Kind::AutoType:
case Value::Kind::NominalClassType:
case Value::Kind::MixinPseudoType:
case Value::Kind::InterfaceType:
case Value::Kind::ConstraintType:
case Value::Kind::ImplWitness:
Expand All @@ -640,6 +641,7 @@ auto Interpreter::Convert(Nonnull<const Value*> value,
case Value::Kind::StringType:
case Value::Kind::StringValue:
case Value::Kind::TypeOfClassType:
case Value::Kind::TypeOfMixinPseudoType:
case Value::Kind::TypeOfInterfaceType:
case Value::Kind::TypeOfConstraintType:
case Value::Kind::TypeOfChoiceType:
Expand Down Expand Up @@ -1824,6 +1826,8 @@ auto Interpreter::StepDeclaration() -> ErrorOr<Success> {
}
case DeclarationKind::FunctionDeclaration:
case DeclarationKind::ClassDeclaration:
case DeclarationKind::MixinDeclaration:
case DeclarationKind::MixDeclaration:
case DeclarationKind::ChoiceDeclaration:
case DeclarationKind::InterfaceDeclaration:
case DeclarationKind::AssociatedConstantDeclaration:
Expand Down
8 changes: 8 additions & 0 deletions explorer/interpreter/resolve_control_flow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,13 @@ auto ResolveControlFlow(Nonnull<Declaration*> declaration) -> ErrorOr<Success> {
}
break;
}
case DeclarationKind::MixinDeclaration: {
auto& mixin_decl = cast<MixinDeclaration>(*declaration);
for (Nonnull<Declaration*> member : mixin_decl.members()) {
CARBON_RETURN_IF_ERROR(ResolveControlFlow(member));
}
break;
}
case DeclarationKind::InterfaceDeclaration: {
auto& iface_decl = cast<InterfaceDeclaration>(*declaration);
for (Nonnull<Declaration*> member : iface_decl.members()) {
Expand All @@ -173,6 +180,7 @@ auto ResolveControlFlow(Nonnull<Declaration*> declaration) -> ErrorOr<Success> {
case DeclarationKind::AssociatedConstantDeclaration:
case DeclarationKind::SelfDeclaration:
case DeclarationKind::AliasDeclaration:
case DeclarationKind::MixDeclaration:
// do nothing
break;
}
Expand Down
31 changes: 31 additions & 0 deletions explorer/interpreter/resolve_names.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@ static auto AddExposedNames(const Declaration& declaration,
StaticScope::NameStatus::KnownButNotDeclared));
break;
}
case DeclarationKind::MixinDeclaration: {
auto& mixin_decl = cast<MixinDeclaration>(declaration);
CARBON_RETURN_IF_ERROR(
enclosing_scope.Add(mixin_decl.name(), &mixin_decl,
StaticScope::NameStatus::KnownButNotDeclared));
break;
}
case DeclarationKind::MixDeclaration: {
// Nothing to do here
break;
}
case DeclarationKind::ChoiceDeclaration: {
auto& choice = cast<ChoiceDeclaration>(declaration);
CARBON_RETURN_IF_ERROR(
Expand Down Expand Up @@ -560,6 +571,26 @@ static auto ResolveNames(Declaration& declaration, StaticScope& enclosing_scope,
ResolveMemberNames(class_decl.members(), class_scope, bodies));
break;
}
case DeclarationKind::MixinDeclaration: {
auto& mixin_decl = cast<MixinDeclaration>(declaration);
StaticScope mixin_scope;
mixin_scope.AddParent(&enclosing_scope);
enclosing_scope.MarkDeclared(mixin_decl.name());
if (mixin_decl.params().has_value()) {
CARBON_RETURN_IF_ERROR(
ResolveNames(**mixin_decl.params(), mixin_scope));
}
enclosing_scope.MarkUsable(mixin_decl.name());
CARBON_RETURN_IF_ERROR(mixin_scope.Add("Self", mixin_decl.self()));
CARBON_RETURN_IF_ERROR(
ResolveMemberNames(mixin_decl.members(), mixin_scope, bodies));
break;
}
case DeclarationKind::MixDeclaration: {
auto& mix_decl = cast<MixDeclaration>(declaration);
CARBON_RETURN_IF_ERROR(ResolveNames(mix_decl.mixin(), enclosing_scope));
break;
}
case DeclarationKind::ChoiceDeclaration: {
auto& choice = cast<ChoiceDeclaration>(declaration);
StaticScope choice_scope;
Expand Down
2 changes: 2 additions & 0 deletions explorer/interpreter/resolve_unformed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,8 @@ static auto ResolveUnformed(Nonnull<const Declaration*> declaration)
break;
}
case DeclarationKind::ClassDeclaration:
case DeclarationKind::MixDeclaration:
case DeclarationKind::MixinDeclaration:
case DeclarationKind::InterfaceDeclaration:
case DeclarationKind::ImplDeclaration:
case DeclarationKind::ChoiceDeclaration:
Expand Down
Loading