digitalmars.D - Using core.reflect to check for unused paramters
- Stefan Koch (66/66) Aug 30 2021 Hi,
- Stefan Koch (35/39) Sep 02 2021 Ah the bugs are biting again.
- user1234 (3/5) Sep 03 2021 BTW, I'm curious to know how this can work. Should not VarExp
- Stefan Koch (5/11) Sep 03 2021 VerExps have a VarDecl member.
- user1234 (4/16) Sep 03 2021 so FuncDeclaration parameters are not visited, that's why that
- Stefan Koch (8/26) Sep 03 2021 Exactly this works because of this line.
- user1234 (6/34) Sep 03 2021 Yes and no. It's better _as example_, so that we can see clearly
Hi, I've just extended core.reflect's reflection to function bodies. Which means you can now do fun things such as checking for unused parameters at compile-time. If you checkout the core.reflect branch from my forks of druntime and dmd you can run the example code below and convince yourself that it works ```d import core.reflect.reflect; import core.reflect.transitiveVisitor; // import core.reflect.nodeToString(); int func(int a, int b) { return a + b; } static assert(!hasUnusedParameters(nodeFromName("func"))); int func2(int a, int b, int c) { return func(a, b); } static assert(hasUnusedParameters(nodeFromName("func2"))); bool hasUnusedParameters(const Node n) { bool result = false; if (auto fd = cast(FunctionDeclaration) n) { result = hasUnusedParameters(fd); } return result; } bool hasUnusedParameters(const FunctionDeclaration fd) { bool[const(VariableDeclaration)] parameterUsageList; foreach(p;fd.parameters) { parameterUsageList[p] = false; } class Marker : TransitiveVisitor { bool[const(VariableDeclaration)]* parameterUsageList; this(bool[const(VariableDeclaration)] *parameterUsageList) { this.parameterUsageList = parameterUsageList; } alias visit = TransitiveVisitor.visit; override void visit(VariableDeclaration vd) { if (auto b = vd in *parameterUsageList) { *b = true; } } } scope marker = new Marker(¶meterUsageList); (cast()fd.fbody).accept(marker); foreach(v, unused; parameterUsageList) { if (!unused) return true; } return false; } ``` I am aware that these block of code posts of mine are not the most appealing. Please wait a little I will have more high-levels descriptions as the core.reflect prototype gets closer to a stable state.
Aug 30 2021
On Monday, 30 August 2021 at 18:13:59 UTC, Stefan Koch wrote:Hi, I've just extended core.reflect's reflection to function bodies. Which means you can now do fun things such as checking for unused parameters at compile-time.Ah the bugs are biting again. if you have played with the code I posted you will have seen that it didn't count parameters which were used as variable initializer i.e. ```d void func(int p) { auto x = p; } ``` would have complained about unused parameters. The reason is that we didn't visit the `_init` field of the `VariableDeclaration`. luckily it's easily fixed. ```d class Marker : TransitiveVisitor { bool[const(VariableDeclaration)]* parameterUsageList; this(bool[const(VariableDeclaration)] *parameterUsageList) { this.parameterUsageList = parameterUsageList; } alias visit = TransitiveVisitor.visit; override void visit(VariableDeclaration vd) { if (auto b = vd in *parameterUsageList) { *b = true; } vd._init.accept(this); } } ``` now this visitor will reliably detect usage of parameters.
Sep 02 2021
On Thursday, 2 September 2021 at 21:27:33 UTC, Stefan Koch wrote:[...] now this visitor will reliably detect usage of parameters.BTW, I'm curious to know how this can work. Should not VarExp (and not VarDecl) be overridden to mark ?
Sep 03 2021
On Friday, 3 September 2021 at 13:02:37 UTC, user1234 wrote:On Thursday, 2 September 2021 at 21:27:33 UTC, Stefan Koch wrote:VerExps have a VarDecl member. which the transitive visitor looks into for you. You could look at VarExps but I chose to look into VarDecls instead.[...] now this visitor will reliably detect usage of parameters.BTW, I'm curious to know how this can work. Should not VarExp (and not VarDecl) be overridden to mark ?
Sep 03 2021
On Friday, 3 September 2021 at 14:45:20 UTC, Stefan Koch wrote:On Friday, 3 September 2021 at 13:02:37 UTC, user1234 wrote:so FuncDeclaration parameters are not visited, that's why that works ? only bodies are visited ?On Thursday, 2 September 2021 at 21:27:33 UTC, Stefan Koch wrote:VerExps have a VarDecl member. which the transitive visitor looks into for you. You could look at VarExps but I chose to look into VarDecls instead.[...] now this visitor will reliably detect usage of parameters.BTW, I'm curious to know how this can work. Should not VarExp (and not VarDecl) be overridden to mark ?
Sep 03 2021
On Friday, 3 September 2021 at 15:32:59 UTC, user1234 wrote:On Friday, 3 September 2021 at 14:45:20 UTC, Stefan Koch wrote:Exactly this works because of this line. `(cast()fd.fbody).accept(marker);` I am starting the visitor at the body of the function. And since there no back-edge to the function declaration it works. If you have a back-edge to the function declaration for example in recursive call it would stop working. So visiting the VarExp is a better idea.On Friday, 3 September 2021 at 13:02:37 UTC, user1234 wrote:so FuncDeclaration parameters are not visited, that's why that works ? only bodies are visited ?On Thursday, 2 September 2021 at 21:27:33 UTC, Stefan Koch wrote:VerExps have a VarDecl member. which the transitive visitor looks into for you. You could look at VarExps but I chose to look into VarDecls instead.[...] now this visitor will reliably detect usage of parameters.BTW, I'm curious to know how this can work. Should not VarExp (and not VarDecl) be overridden to mark ?
Sep 03 2021
On Friday, 3 September 2021 at 15:47:16 UTC, Stefan Koch wrote:On Friday, 3 September 2021 at 15:32:59 UTC, user1234 wrote:indeed I've missed that lineOn Friday, 3 September 2021 at 14:45:20 UTC, Stefan Koch wrote:Exactly this works because of this line. `(cast()fd.fbody).accept(marker);`On Friday, 3 September 2021 at 13:02:37 UTC, user1234 wrote:so FuncDeclaration parameters are not visited, that's why that works ? only bodies are visited ?On Thursday, 2 September 2021 at 21:27:33 UTC, Stefan Koch wrote:VerExps have a VarDecl member. which the transitive visitor looks into for you. You could look at VarExps but I chose to look into VarDecls instead.[...] now this visitor will reliably detect usage of parameters.BTW, I'm curious to know how this can work. Should not VarExp (and not VarDecl) be overridden to mark ?I am starting the visitor at the body of the function. And since there no back-edge to the function declaration it works. If you have a back-edge to the function declaration for example in recursive call it would stop working. So visiting the VarExp is a better idea.Yes and no. It's better _as example_, so that we can see clearly that params are marked on use. Basically my first answer was posted because overridding the visit of VarDecl was confusing. Otherwise that looks like a convincing example.
Sep 03 2021