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-");
43 for (
const auto &[K, V] : YAttrs.Static) {
44 if (XAttrs.Static.contains(K)) {
57 dupAttr(K, V.key().range(), XAttrs.Static.at(K).key().range());
60 XAttrs.Static.insert({K, V});
62 for (
const auto &DAttr : YAttrs.Dynamic) {
63 XAttrs.Dynamic.emplace_back(DAttr);
77 if (!Name->isStatic()) {
79 SA.Dynamic.emplace_back(std::move(Name), std::move(E), Kind);
82 auto &Attrs = SA.Static;
83 std::string StaticName = Name->staticName();
84 if (
auto Nested = Attrs.find(StaticName); Nested != Attrs.end()) {
85 const auto &[K, V] = *Nested;
86 if (V.value() && V.value()->kind() == Node::NK_ExprAttrs && E &&
87 E->kind() == Node::NK_ExprAttrs) {
89 auto *XAttrSet =
static_cast<ExprAttrs *
>(V.value());
90 auto *YAttrSet =
static_cast<ExprAttrs *
>(E.get());
95 dupAttr(StaticName, Name->range(), V.key().range());
100 Attrs.insert({StaticName,
Attribute(std::move(Name), std::move(E), Kind)});
105 const std::vector<std::shared_ptr<AttrName>> &Path) {
106 assert(!Path.empty() &&
"AttrPath has at least 1 name");
110 for (std::size_t I = 0; I + 1 < Path.size(); I++) {
111 const auto &Name = Path[I];
112 assert(Inner &&
"Attr is not null");
117 if (Name->isStatic()) {
118 std::map<std::string, Attribute> &StaticAttrs = Inner->Static;
119 const std::string &StaticName = Name->staticName();
120 if (
auto Nested = StaticAttrs.find(StaticName);
121 Nested != StaticAttrs.end()) {
123 const auto &[K, V] = *Nested;
124 if (V.fromInherit() || !V.value() ||
125 V.value()->kind() != Node::NK_ExprAttrs) {
126 dupAttr(StaticName, Name->range(), V.key().range());
129 Inner = &
static_cast<ExprAttrs *
>(V.value())->SA;
134 auto NewNested = std::make_shared<ExprAttrs>(
135 Name->range(),
nullptr,
nullptr,
SemaAttrs(
nullptr));
136 Inner = &NewNested->SA;
138 {StaticName,
Attribute(Name, std::move(NewNested),
143 std::vector<Attribute> &DynamicAttrs = Inner->Dynamic;
144 auto NewNested = std::make_shared<ExprAttrs>(
145 Name->range(),
nullptr,
nullptr,
SemaAttrs(
nullptr));
146 Inner = &NewNested->SA;
147 DynamicAttrs.emplace_back(Name,
148 std::shared_ptr<Expr>(std::move(NewNested)),
156 std::shared_ptr<Expr> E) {
163 std::shared_ptr<AttrName> Name = Path.names().back();
166 insertAttr(*Inner, std::move(Name), std::move(E),
176 if (Rm != FV.begin() || Rm + 1 == FV.end())
179 Formal &SecondF = **(Rm + 1);
188 Formal &LastF = *FV.back().get();
190 for (
auto It = FV.begin(); It + 1 != FV.end(); It++) {
198 Diags.emplace_back(Diagnostic::DK_FormalExtraEllipsis, CurF.
range());
201 Diagnostic &D = Diags.emplace_back(Diagnostic::DK_FormalMisplacedEllipsis,
203 Fix &Fx = D.
fix(
"move ellipsis to the tail");
205 std::string NewText(CurF.
src(Src));
209 NewText = std::string(
", ").append(NewText);
218 for (
auto It = FV.begin(); It != FV.end(); It++) {
221 if (It != FV.begin() && !F.
comma()) {
223 Diags.emplace_back(Diagnostic::DK_FormalMissingComma, F.
range());
230 for (
auto It = FV.cbegin(); It != FV.cend(); It++) {
234 if (It + 1 == FV.cend())
237 const std::shared_ptr<Formal> &FPtr = *It;
243 Diagnostic &D = Diags.emplace_back(Diagnostic::DK_EmptyFormal, F.
range());
253 for (
const std::shared_ptr<Formal> &FPtr : FV) {
258 if (Dedup.contains(ID.
name())) {
264 Diags.emplace_back(Diagnostic::DK_DuplicatedFormal, ID.
range());
265 D.
note(Note::NK_DuplicateFormal, DupID.
range());
267 Dedup[ID.
name()] = &F;
274 std::map<std::string, const Formal *> Dedup;
279 return std::make_shared<Formals>(Range, std::move(FV), std::move(Dedup));
283 std::shared_ptr<Expr> E,
288 if (!Name->isStatic()) {
291 Diags.emplace_back(Diagnostic::DK_DynamicInherit, Name->range());
297 if (SA.Static.contains(Name->staticName())) {
298 dupAttr(Name->staticName(), Name->range(),
299 SA.Static.at(Name->staticName()).key().range());
303 std::string StaticName = Name->staticName();
305 {StaticName,
Attribute(std::move(Name), std::move(E), InheritKind)});
309 for (
const std::shared_ptr<AttrName> &Name :
Inherit.
names()) {
317 for (
const std::shared_ptr<Node> &Bind : B.
bindings()) {
318 assert(Bind &&
"Bind is not null");
319 switch (Bind->kind()) {
320 case Node::NK_Inherit: {
321 auto *N =
static_cast<Inherit *
>(Bind.get());
325 case Node::NK_Binding: {
326 auto *B =
static_cast<Binding *
>(Bind.get());
327 addAttr(SA, B->path(), B->value());
331 assert(
false &&
"Bind should be either Inherit or Binding");
338 std::shared_ptr<Expr> E) {
339 auto Range = Name->range();
341 return {std::make_shared<ExprVar>(Range, Name->id()),
344 auto Path = std::make_shared<AttrPath>(
345 Range, std::vector<std::shared_ptr<AttrName>>{std::move(Name)},
346 std::vector<std::shared_ptr<Dot>>{});
347 return {std::make_shared<ExprSelect>(Range, std::move(E), std::move(Path),
353 std::shared_ptr<Binds>
Binds,
354 std::shared_ptr<Misc> Rec) {
358 return std::make_shared<ExprAttrs>(Range, std::move(
Binds), std::move(Rec),
363 std::shared_ptr<Identifier> ID,
364 std::shared_ptr<Formals> F) {
368 if (F->dedup().contains(ID->name())) {
371 Diags.emplace_back(Diagnostic::DK_DuplicatedFormalToArg, ID->range());
372 D.
note(Note::NK_DuplicateFormal, F->dedup().at(ID->name())->range());
375 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)