17 auto &Diag = Diags.emplace_back(Diagnostic::DK_DuplicatedAttrName, Range);
18 Diag << std::move(Name);
19 Diag.note(Note::NK_PrevDeclared, Prev);
26 if (XAttrsRec == YAttrsRec)
30 const Misc *Pointer = XAttrsRec ? XAttrs.
rec() : YAttrs.
rec();
31 auto &D = Diags.emplace_back(Diagnostic::DK_MergeDiffRec, Pointer->
range());
33 auto XRange = XAttrsRec ? XAttrs.
rec()->
range() : XAttrs.
range();
34 D.note(Note::NK_ThisRecursive, XRange) << (XAttrsRec ?
"" :
"non-");
36 auto YRange = YAttrsRec ? YAttrs.
rec()->
range() : YAttrs.
range();
37 D.note(Note::NK_RecConsider, YRange)
38 << (YAttrsRec ?
"" :
"non-")
39 << (XAttrsRec ?
"" :
"non-");
42bool Sema::tryMergeAttrs(
Expr *X,
Expr *Y) {
43 if (!X || X->
kind() != Node::NK_ExprAttrs || !Y ||
44 Y->
kind() != Node::NK_ExprAttrs)
47 auto *XAttrs =
static_cast<ExprAttrs *
>(X);
48 auto *YAttrs =
static_cast<ExprAttrs *
>(Y);
55 for (
const auto &[K, Y] : YAttrs.Static) {
56 auto [It, Inserted] = XAttrs.Static.insert({K, Y});
60 const auto &[_, X] = *It;
61 if (!tryMergeAttrs(X.value(), Y.value()))
64 for (
const auto &DAttr : YAttrs.Dynamic) {
65 XAttrs.Dynamic.emplace_back(DAttr);
79 if (!Name->isStatic()) {
81 SA.Dynamic.emplace_back(std::move(Name), std::move(E), Kind);
84 auto &Attrs = SA.Static;
85 std::string StaticName = Name->staticName();
86 if (
auto Nested = Attrs.find(StaticName); Nested != Attrs.end()) {
87 const auto &[K, V] = *Nested;
88 if (!tryMergeAttrs(V.value(), E.get()))
89 dupAttr(StaticName, Name->range(), V.key().range());
94 Attrs.insert({StaticName,
Attribute(std::move(Name), std::move(E), Kind)});
99 const std::vector<std::shared_ptr<AttrName>> &Path) {
100 assert(!Path.empty() &&
"AttrPath has at least 1 name");
104 for (std::size_t I = 0; I + 1 < Path.size(); I++) {
105 const auto &Name = Path[I];
106 assert(Inner &&
"Attr is not null");
111 if (Name->isStatic()) {
112 std::map<std::string, Attribute> &StaticAttrs = Inner->Static;
113 const std::string &StaticName = Name->staticName();
114 if (
auto Nested = StaticAttrs.find(StaticName);
115 Nested != StaticAttrs.end()) {
117 const auto &[K, V] = *Nested;
118 if (V.fromInherit() || !V.value() ||
119 V.value()->kind() != Node::NK_ExprAttrs) {
120 dupAttr(StaticName, Name->range(), V.key().range());
123 Inner = &
static_cast<ExprAttrs *
>(V.value())->SA;
128 auto NewNested = std::make_shared<ExprAttrs>(
129 Name->range(),
nullptr,
nullptr,
SemaAttrs(
nullptr));
130 Inner = &NewNested->SA;
132 {StaticName,
Attribute(Name, std::move(NewNested),
137 std::vector<Attribute> &DynamicAttrs = Inner->Dynamic;
138 auto NewNested = std::make_shared<ExprAttrs>(
139 Name->range(),
nullptr,
nullptr,
SemaAttrs(
nullptr));
140 Inner = &NewNested->SA;
141 DynamicAttrs.emplace_back(Name,
142 std::shared_ptr<Expr>(std::move(NewNested)),
150 std::shared_ptr<Expr> E) {
157 std::shared_ptr<AttrName> Name = Path.names().back();
160 insertAttr(*Inner, std::move(Name), std::move(E),
170 if (Rm != FV.begin() || Rm + 1 == FV.end())
173 Formal &SecondF = **(Rm + 1);
182 Formal &LastF = *FV.back().get();
184 for (
auto It = FV.begin(); It + 1 != FV.end(); It++) {
192 Diags.emplace_back(Diagnostic::DK_FormalExtraEllipsis, CurF.
range());
195 Diagnostic &D = Diags.emplace_back(Diagnostic::DK_FormalMisplacedEllipsis,
197 Fix &Fx = D.
fix(
"move ellipsis to the tail");
199 std::string NewText(CurF.
src(Src));
203 NewText = std::string(
", ").append(NewText);
212 for (
auto It = FV.begin(); It != FV.end(); It++) {
215 if (It != FV.begin() && !F.
comma()) {
217 Diags.emplace_back(Diagnostic::DK_FormalMissingComma, F.
range());
224 for (
auto It = FV.cbegin(); It != FV.cend(); It++) {
228 if (It + 1 == FV.cend())
231 const std::shared_ptr<Formal> &FPtr = *It;
237 Diagnostic &D = Diags.emplace_back(Diagnostic::DK_EmptyFormal, F.
range());
247 for (
const std::shared_ptr<Formal> &FPtr : FV) {
252 if (Dedup.contains(ID.
name())) {
258 Diags.emplace_back(Diagnostic::DK_DuplicatedFormal, ID.
range());
259 D.
note(Note::NK_DuplicateFormal, DupID.
range());
261 Dedup[ID.
name()] = &F;
268 std::map<std::string, const Formal *> Dedup;
273 return std::make_shared<Formals>(Range, std::move(FV), std::move(Dedup));
277 std::shared_ptr<Expr> E,
282 if (!Name->isStatic()) {
285 Diags.emplace_back(Diagnostic::DK_DynamicInherit, Name->range());
291 if (SA.Static.contains(Name->staticName())) {
292 dupAttr(Name->staticName(), Name->range(),
293 SA.Static.at(Name->staticName()).key().range());
297 std::string StaticName = Name->staticName();
299 {StaticName,
Attribute(std::move(Name), std::move(E), InheritKind)});
303 for (
const std::shared_ptr<AttrName> &Name :
Inherit.
names()) {
311 for (
const std::shared_ptr<Node> &Bind : B.
bindings()) {
312 assert(Bind &&
"Bind is not null");
313 switch (Bind->kind()) {
314 case Node::NK_Inherit: {
315 auto *N =
static_cast<Inherit *
>(Bind.get());
319 case Node::NK_Binding: {
320 auto *B =
static_cast<Binding *
>(Bind.get());
321 addAttr(SA, B->path(), B->value());
325 assert(
false &&
"Bind should be either Inherit or Binding");
332 std::shared_ptr<Expr> E) {
333 auto Range = Name->range();
335 return {std::make_shared<ExprVar>(Range, Name->id()),
338 auto Path = std::make_shared<AttrPath>(
339 Range, std::vector<std::shared_ptr<AttrName>>{std::move(Name)},
340 std::vector<std::shared_ptr<Dot>>{});
341 return {std::make_shared<ExprSelect>(Range, std::move(E),
nullptr,
342 std::move(Path),
nullptr, E.get()),
347 std::shared_ptr<Binds>
Binds,
348 std::shared_ptr<Misc> Rec) {
352 return std::make_shared<ExprAttrs>(Range, std::move(
Binds), std::move(Rec),
357 std::shared_ptr<Identifier> ID,
358 std::shared_ptr<Formals> F) {
362 if (F->dedup().contains(ID->name())) {
365 Diags.emplace_back(Diagnostic::DK_DuplicatedFormalToArg, ID->range());
366 D.
note(Note::NK_DuplicateFormal, F->dedup().at(ID->name())->range());
369 return std::make_shared<LambdaArg>(Range, std::move(ID), std::move(F));
Semantic Actions while building the AST.
@ InheritFrom
inherit (expr) a b c
const std::vector< std::shared_ptr< Node > > & bindings() const
Note & note(Note::NoteKind Kind, LexerCursorRange Range)
Fix & fix(std::string Message)
Fix & edit(TextEdit Edit)
Identifier. Variable names, attribute names, etc.
const std::string & name() const
const std::shared_ptr< Expr > & expr() const
const std::vector< std::shared_ptr< AttrName > > & names() const
Misc node, used for parentheses, keywords, etc.
std::string_view src(std::string_view Src) const
LexerCursorRange range() const
void tag(DiagnosticTag Tag)
Attribute set after deduplication.
SemaAttrs * selectOrCreate(SemaAttrs &SA, const std::vector< std::shared_ptr< AttrName > > &Path)
void insertAttr(SemaAttrs &SA, std::shared_ptr< AttrName > Name, std::shared_ptr< Expr > E, Attribute::AttributeKind Kind)
void lowerInherit(SemaAttrs &Attr, const Inherit &Inherit)
std::shared_ptr< ExprAttrs > onExprAttrs(LexerCursorRange Range, std::shared_ptr< Binds > Binds, std::shared_ptr< Misc > Rec)
std::shared_ptr< LambdaArg > onLambdaArg(LexerCursorRange Range, std::shared_ptr< Identifier > ID, std::shared_ptr< Formals > F)
void dedupFormal(std::map< std::string, const Formal * > &Dedup, const FormalVector &FV)
Deduplicate formals.
void lowerInheritName(SemaAttrs &SA, std::shared_ptr< AttrName > Name, std::shared_ptr< Expr > E, Attribute::AttributeKind InheritKind)
void mergeAttrSets(SemaAttrs &XAttrs, const SemaAttrs &YAttrs)
Perform attrsets merging while duplicated fields are both attrsets.
void checkFormalEllipsis(const FormalVector &FV)
Check if ellipsis "...".
void lowerBinds(SemaAttrs &SA, const Binds &B)
void addAttr(SemaAttrs &Attr, const AttrPath &Path, std::shared_ptr< Expr > E)
Insert the binding: AttrPath = E; into Attr.
void checkFormalSep(const FormalVector &FV)
Check if there is a seperator "," between formals.
void dupAttr(std::string Name, LexerCursorRange Range, LexerCursorRange Prev)
Formals::FormalVector FormalVector
void checkAttrRecursiveForMerge(const ExprAttrs &XAttrs, const ExprAttrs &YAttrs)
Check if these two attrsets has the same "recursive" modifier.
void checkFormalEmpty(const FormalVector &FV)
Diagnose empty formal i.e. single comma.
std::shared_ptr< Formals > onFormals(LexerCursorRange Range, FormalVector FV)
static void removeFormal(Fix &F, const FormalVector::const_iterator &Rm, const FormalVector &FV)
Make text edits to remove a formal.
static std::pair< std::shared_ptr< Expr >, Attribute::AttributeKind > desugarInheritExpr(std::shared_ptr< AttrName > Name, std::shared_ptr< Expr > E)
Desugar inherit (expr) a, inherit a, into select, or variable.
static TextEdit mkRemoval(LexerCursorRange RemovingRange)
static TextEdit mkInsertion(LexerCursor P, std::string NewText)