Skip to content

Commit

Permalink
libnixf: split sema-unused-def into let, arg and formal
Browse files Browse the repository at this point in the history
  • Loading branch information
Aleksanaa committed Aug 1, 2024
1 parent 5c3f5ca commit 37d18c1
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 18 deletions.
5 changes: 4 additions & 1 deletion libnixf/include/nixf/Sema/VariableLookup.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,12 @@ class Definition {
/// \brief From lambda formal, e.g. { a }: a + 1
DS_LambdaFormal,

/// \brief From lambda arg with formal, e.g. { foo, bar }@a: a + 1
/// \brief From lambda arg with formal, e.g. `a` in `{ foo }@a: foo + 1`
DS_LambdaArgWithFormal,

/// \brief From lambda formal with arg, e.g. `foo` in `{ foo }@a: foo + 1`
DS_LambdaFormalWithArg,

/// \brief From recursive attribute set. e.g. rec { }
DS_Rec,

Expand Down
24 changes: 21 additions & 3 deletions libnixf/src/Basic/diagnostic.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,28 @@ class Diagnostic(TypedDict):
"message": "undefined variable `{}`",
},
{
"sname": "sema-def-not-used",
"cname": "DefinitionNotUsed",
"sname": "sema-unused-def-let",
"cname": "UnusedDefLet",
"severity": "Warning",
"message": "variable `{}` in let-expression is not used",
},
{
"sname": "sema-unused-def-formal",
"cname": "UnusedDefFormal",
"severity": "Warning",
"message": "attribute `{}` of argument is not used",
},
{
"sname": "sema-unused-def-arg-with-formal",
"cname": "UnusedDefArgWithFormal",
"severity": "Warning",
"message": "argument `{}` in `@`-pattern is not used",
},
{
"sname": "sema-unused-def-formal-with-arg",
"cname": "UnusedDefFormalWithArg",
"severity": "Hint",
"message": "definition `{}` is not used",
"message": "attribute `{}` of `@`-pattern argument is not used, but may be referenced from the argument",
},
{
"sname": "sema-extra-rec",
Expand Down
34 changes: 27 additions & 7 deletions libnixf/src/Sema/VariableLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,24 @@ void VariableLookupAnalysis::emitEnvLivenessWarning(
if (!Def->syntax())
continue;
if (Def->uses().empty()) {
Diagnostic &D = Diags.emplace_back(Diagnostic::DK_DefinitionNotUsed,
Def->syntax()->range());
Diagnostic::DiagnosticKind kind;
switch (Def->source()) {
case Definition::DS_Let:
kind = Diagnostic::DK_UnusedDefLet;
break;
case Definition::DS_LambdaFormal:
kind = Diagnostic::DK_UnusedDefFormal;
break;
case Definition::DS_LambdaFormalWithArg:
kind = Diagnostic::DK_UnusedDefFormalWithArg;
break;
case Definition::DS_LambdaArgWithFormal:
kind = Diagnostic::DK_UnusedDefArgWithFormal;
break;
default:
break;
}
Diagnostic &D = Diags.emplace_back(kind, Def->syntax()->range());
D << Name;
D.tag(DiagnosticTag::Faded);
}
Expand Down Expand Up @@ -128,6 +144,9 @@ void VariableLookupAnalysis::dfs(const ExprLambda &Lambda,

// foo: body
// ^~~<------- add function argument.
// { foo, bar, ... } : body
// ^~~~~~~~~<-------------- add function formals.

if (Arg.id()) {
if (!Arg.formals()) {
ToDef.insert_or_assign(Arg.id(), DBuilder.add(Arg.id()->name(), Arg.id(),
Expand All @@ -138,16 +157,17 @@ void VariableLookupAnalysis::dfs(const ExprLambda &Lambda,
ToDef.insert_or_assign(Arg.id(),
DBuilder.add(Arg.id()->name(), Arg.id(),
Definition::DS_LambdaArgWithFormal));
for (const auto &[Name, Formal] : Arg.formals()->dedup())
ToDef.insert_or_assign(
Formal->id(), DBuilder.add(Name, Formal->id(),
Definition::DS_LambdaFormalWithArg));
}
}

// { foo, bar, ... } : body
/// ^~~~~~~~~<-------------- add function formals.
if (Arg.formals())
} else if (Arg.formals()) {
for (const auto &[Name, Formal] : Arg.formals()->dedup())
ToDef.insert_or_assign(
Formal->id(),
DBuilder.add(Name, Formal->id(), Definition::DS_LambdaFormal));
}

auto NewEnv = std::make_shared<EnvNode>(Env, DBuilder.finish(), &Lambda);

Expand Down
25 changes: 18 additions & 7 deletions libnixf/test/Sema/VariableLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,29 +135,27 @@ TEST_F(VLATest, LivenessRec) {
ASSERT_EQ(Diags[0].kind(), Diagnostic::DK_ExtraRecursive);
}

TEST_F(VLATest, LivenessArg) {
TEST_F(VLATest, LivenessFormal) {
std::shared_ptr<Node> AST = parse("{ foo }: 1", Diags);
VariableLookupAnalysis VLA(Diags);
VLA.runOnAST(*AST);

ASSERT_EQ(Diags.size(), 1);

ASSERT_EQ(Diags[0].kind(), Diagnostic::DK_DefinitionNotUsed);
ASSERT_EQ(Diags[0].kind(), Diagnostic::DK_UnusedDefFormal);
ASSERT_EQ(Diags[0].tags().size(), 1);
ASSERT_EQ(Diags[0].tags()[0], DiagnosticTag::Faded);
}

TEST_F(VLATest, LivenessNested) {
TEST_F(VLATest, LivenessLet) {
std::shared_ptr<Node> AST = parse("let y = 1; in x: y: x + y", Diags);
VariableLookupAnalysis VLA(Diags);
VLA.runOnAST(*AST);

ASSERT_EQ(Diags.size(), 1);

ASSERT_EQ(Diags[0].kind(), Diagnostic::DK_DefinitionNotUsed);
ASSERT_EQ(Diags[0].kind(), Diagnostic::DK_UnusedDefLet);
ASSERT_EQ(Diags[0].range().lCur().column(), 4);
ASSERT_EQ(Diags[0].tags().size(), 1);
ASSERT_EQ(Diags[0].tags()[0], DiagnosticTag::Faded);
}

TEST_F(VLATest, LivenessDupSymbol) {
Expand All @@ -179,12 +177,25 @@ TEST_F(VLATest, LivenessArgWithFormal) {

ASSERT_EQ(Diags.size(), 1);

ASSERT_EQ(Diags[0].kind(), Diagnostic::DK_DefinitionNotUsed);
ASSERT_EQ(Diags[0].kind(), Diagnostic::DK_UnusedDefArgWithFormal);
ASSERT_EQ(Diags[0].range().lCur().column(), 8);
ASSERT_EQ(Diags[0].tags().size(), 1);
}

TEST_F(VLATest, LivenessFormalWithArg) {
std::shared_ptr<Node> AST = parse("{ foo }@bar: bar", Diags);
VariableLookupAnalysis VLA(Diags);
VLA.runOnAST(*AST);

ASSERT_EQ(Diags.size(), 1);

ASSERT_EQ(Diags[0].kind(), Diagnostic::DK_UnusedDefFormalWithArg);
ASSERT_EQ(Diags[0].range().lCur().column(), 2);
ASSERT_EQ(Diags[0].tags().size(), 1);
ASSERT_EQ(Diags[0].tags()[0], DiagnosticTag::Faded);
}


TEST_F(VLATest, ToDefAttrs) {
std::shared_ptr<Node> AST = parse("rec { x = 1; y = x; z = x; }", Diags);
VariableLookupAnalysis VLA(Diags);
Expand Down

0 comments on commit 37d18c1

Please sign in to comment.