digitalmars.D - Annotation of functions
- psychoticRabbit (14/14) Feb 20 2018 I've noticed that Go and Rust annotate functions.
- rikki cattermole (5/25) Feb 20 2018 You need a fully implemented frontend to get anything proper in terms of...
- psychoRabbit (8/12) Feb 20 2018 Why is the point (about being able to more easily find functions)
- rikki cattermole (7/15) Feb 20 2018 string creater() pure {
- psychoticRabbit (15/22) Feb 20 2018 I think I'd fire anyone that wrote functions in that way ;-)
- psychoticRabbit (11/16) Feb 20 2018 oh... I think I might have misunderstood your point ... due to
- Jonathan M Davis (25/44) Feb 20 2018 mixin takes a string and that string is basically copy-pasted in as code...
- bauss (33/46) Feb 20 2018 Why would you fire someone for writing idiomatic D?
- bauss (16/64) Feb 20 2018 I should probably have put an example usage to show how it's used:
- psychoticRabbit (3/6) Feb 20 2018 This makes we want to go back and program in C again ;-)
- Steven Schveighoffer (28/36) Feb 21 2018 Mixins are one of those things that you need occasionally, but are weird...
- Patrick Schluter (6/13) Feb 21 2018 mixin is equivalent to preprocessor macros but with the benefit
- psychoticRabbit (9/10) Feb 20 2018 ok. I've come around... and the point reall is moot.
- ketmar (3/10) Feb 20 2018 dmd.
- Adam D. Ruppe (11/17) Feb 20 2018 dmd -X spits out the json file with a list of functions and
- psychoticRabbit (2/4) Feb 20 2018 'dmd -X' looks like the perfect solution for my need. thanks.
- Seb (9/16) Feb 22 2018 I don't know what exactly you plan to do, but the AST dump from
- psychoticRabbit (5/22) Feb 22 2018 I want to do some cyber-security related analysis of D code bases
- psychoticRabbit (8/10) Feb 22 2018 do you know why the first and last character of the output from
- rjframe (4/17) Feb 22 2018 They form an array.
- psychoticRabbit (16/35) Feb 22 2018 here is my point though:
- ag0aep6g (15/32) Feb 22 2018 You don't have to remove the brackets. You just have to process the
- psychoticRabbit (5/8) Feb 22 2018 ok. I think I demonstrated that I don't know what I'm doing with
- jmh530 (11/26) Feb 20 2018 If you want to annotate your functions (rather than someone
- Adam D. Ruppe (36/43) Feb 20 2018 A lot of dynamic languages do too
- Tony (16/30) Feb 21 2018 On Tuesday, 20 February 2018 at 12:15:57 UTC, psychoticRabbit
I've noticed that Go and Rust annotate functions. func (in go) fn (in rust) I was kind of wondering why they made that choice, given compilers in many languages do not. Would this be a useful feature in D? Everything else seems to have an annotation (e.g structs, classes.) So why not functions? What are people's thoughts about it? My first thought is to make it an optional annotation, for the benefit of developing source code analysis tools that can 'more easily' find functions in source code (i.e. The D compiler can just strip it off and do nothing with it.). That way programmers that see no benefit in it, don't have to deal with it.
Feb 20 2018
On 20/02/2018 12:15 PM, psychoticRabbit wrote:I've noticed that Go and Rust annotate functions. func (in go) fn (in rust) I was kind of wondering why they made that choice, given compilers in many languages do not. Would this be a useful feature in D? Everything else seems to have an annotation (e.g structs, classes.) So why not functions? What are people's thoughts about it? My first thought is to make it an optional annotation, for the benefit of developing source code analysis tools that can 'more easily' find functions in source code (i.e. The D compiler can just strip it off and do nothing with it.). That way programmers that see no benefit in it, don't have to deal with it.You need a fully implemented frontend to get anything proper in terms of parsing for D. We're not talking about syntax highlighting here. So the point is moot.
Feb 20 2018
On Tuesday, 20 February 2018 at 12:18:47 UTC, rikki cattermole wrote:You need a fully implemented frontend to get anything proper in terms of parsing for D. We're not talking about syntax highlighting here. So the point is moot.Why is the point (about being able to more easily find functions) moot? At the moment, i can't even grep source code for functions. i can for structs. i can for classes. but I can't for functions. if function were annotated, I could grep for that annotation. That's really the only benefit I see in it.
Feb 20 2018
On 20/02/2018 12:35 PM, psychoRabbit wrote:On Tuesday, 20 February 2018 at 12:18:47 UTC, rikki cattermole wrote:string creater() pure { return "void func() {}"; } mixin(creator()); That is why. There are plenty of functions, classes and structs that simply won't exist in the form of syntax until you execute CTFE.You need a fully implemented frontend to get anything proper in terms of parsing for D. We're not talking about syntax highlighting here. So the point is moot.Why is the point (about being able to more easily find functions) moot?
Feb 20 2018
On Tuesday, 20 February 2018 at 12:45:25 UTC, rikki cattermole wrote:string creater() pure { return "void func() {}"; } mixin(creator()); That is why. There are plenty of functions, classes and structs that simply won't exist in the form of syntax until you execute CTFE.I think I'd fire anyone that wrote functions in that way ;-) perhaps what I had in mind was a lot simpler. fn string creater() pure { return "void func() {}"; } so now I'm just looking for lines that begin with fn. the mixin doesn't matter. the only reason I thought of this annotation thing, was so I could grep a source code file and count how many functions it had in it. this seemed the easiest way ;-) at the moment, that's just not possible - as you mentioned, you need a front end to process that kind of information (unless you have an annotation).
Feb 20 2018
On Tuesday, 20 February 2018 at 12:55:31 UTC, psychoticRabbit wrote:fn string creater() pure { return "void func() {}"; } so now I'm just looking for lines that begin with fn. the mixin doesn't matter.oh... I think I might have misunderstood your point ... due to not understanding CTFE. Never used it before - 25+ years programming ;-) what does this code even do? i don't understand it. why does it even compile? string creator() pure { return "void func() {}"; } mixin(creator());
Feb 20 2018
On Tuesday, February 20, 2018 13:04:42 psychoticRabbit via Digitalmars-d wrote:On Tuesday, 20 February 2018 at 12:55:31 UTC, psychoticRabbit wrote:mixin takes a string and that string is basically copy-pasted in as code. So, in that example, you end up with mixin(creator()); being replaced with void func() {} The example shows a really basic example of a string mixin - so basic as to be pointless - but it gives you the basic idea. In general, when string mixins are used, they're actually a lot more complicated, but they can be a very useful tool for code generation. One place where they get used frequently where they actually tend to be simple is for operator overloading. e.g. this is std.datetime.date.DateTime's opBinary: DateTime opBinary(string op)(Duration duration) if (op == "+" || op == "-") { DateTime retval = this; immutable seconds = duration.total!"seconds"; mixin("return retval._addSeconds(" ~ op ~ "seconds);"); } D's overloaded operators were specifically designed to be used with string mixins in order to allow you to use the same function for overloading multiple operators. - Jonathan M Davisfn string creater() pure { return "void func() {}"; } so now I'm just looking for lines that begin with fn. the mixin doesn't matter.oh... I think I might have misunderstood your point ... due to not understanding CTFE. Never used it before - 25+ years programming ;-) what does this code even do? i don't understand it. why does it even compile? string creator() pure { return "void func() {}"; } mixin(creator());
Feb 20 2018
On Tuesday, 20 February 2018 at 12:55:31 UTC, psychoticRabbit wrote:On Tuesday, 20 February 2018 at 12:45:25 UTC, rikki cattermole wrote:Why would you fire someone for writing idiomatic D? It was kind of a bad example given, but there are legitimate reasons to generate functions like that. Ex. mixin template Property(T, string name) { mixin("private T _" ~ name ~ ";"); property { mixin("T " ~ name ~ "() { return _" ~ name ~ "; }"); mixin("void " ~ name ~ "(T newValue) { _" ~ name ~ " = newValue; }"); } } mixin template ReadProperty(T, string name) { mixin("private T _" ~ name ~ ";"); property { mixin("T " ~ name ~ "() { return _" ~ name ~ "; }"); } } mixin template WriteProperty(T, string name) { mixin("private T _" ~ name ~ ";"); property { mixin("void " ~ name ~ "(T newValue) { _" ~ name ~ " = newValue; }"); } }string creater() pure { return "void func() {}"; } mixin(creator()); That is why. There are plenty of functions, classes and structs that simply won't exist in the form of syntax until you execute CTFE.I think I'd fire anyone that wrote functions in that way ;-)
Feb 20 2018
On Tuesday, 20 February 2018 at 13:39:17 UTC, bauss wrote:On Tuesday, 20 February 2018 at 12:55:31 UTC, psychoticRabbit wrote:I should probably have put an example usage to show how it's used: class Foo { mixin Property!(int, "bar"); mixin Property!(string, "baz"); } void main() { auto foo = new Foo; foo.bar = 100; foo.baz = "Hello"; import std.stdio; writeln(foo.bar); writeln(foo.baz); }On Tuesday, 20 February 2018 at 12:45:25 UTC, rikki cattermole wrote:Why would you fire someone for writing idiomatic D? It was kind of a bad example given, but there are legitimate reasons to generate functions like that. Ex. mixin template Property(T, string name) { mixin("private T _" ~ name ~ ";"); property { mixin("T " ~ name ~ "() { return _" ~ name ~ "; }"); mixin("void " ~ name ~ "(T newValue) { _" ~ name ~ " = newValue; }"); } } mixin template ReadProperty(T, string name) { mixin("private T _" ~ name ~ ";"); property { mixin("T " ~ name ~ "() { return _" ~ name ~ "; }"); } } mixin template WriteProperty(T, string name) { mixin("private T _" ~ name ~ ";"); property { mixin("void " ~ name ~ "(T newValue) { _" ~ name ~ " = newValue; }"); } }string creater() pure { return "void func() {}"; } mixin(creator()); That is why. There are plenty of functions, classes and structs that simply won't exist in the form of syntax until you execute CTFE.I think I'd fire anyone that wrote functions in that way ;-)
Feb 20 2018
On Tuesday, 20 February 2018 at 13:40:16 UTC, bauss wrote:I should probably have put an example usage to show how it's used: ....This makes we want to go back and program in C again ;-) (but thanks for taking the time to demo/explain)
Feb 20 2018
On 2/20/18 8:53 PM, psychoticRabbit wrote:On Tuesday, 20 February 2018 at 13:40:16 UTC, bauss wrote:Mixins are one of those things that you need occasionally, but are weird to think about. But it's really akin to the C preprocessor (only better). They can be super-useful and make your life easier. For example: struct MyInt(T) { T t; auto opBinary(string op)(const MyInt other) const { return mixin("MyInt(t " ~ op ~ " other.t)"); } } void main() { import std.stdio; alias mi = MyInt!int; mi i = mi(5); writeln(i + mi(6)); // MyInt!int(11) writeln(i - mi(2)); // MyInt!int(3) writeln(i * mi(4)); // MyInt!int(20) writeln(i / mi(2)); // MyInt!int(2) writeln(i ^ mi(1)); // MyInt!int(4) ... // etc. } The other thing that always gets me are all the different "is" expressions. I never remember those things. -SteveI should probably have put an example usage to show how it's used: ....This makes we want to go back and program in C again ;-) (but thanks for taking the time to demo/explain)
Feb 21 2018
On Wednesday, 21 February 2018 at 01:53:42 UTC, psychoticRabbit wrote:On Tuesday, 20 February 2018 at 13:40:16 UTC, bauss wrote:mixin is equivalent to preprocessor macros but with the benefit that you can build the string/macro using construct of the language and informations the compiler knows. The mixin itself corresponds then to the macro expansion.I should probably have put an example usage to show how it's used: ....This makes we want to go back and program in C again ;-) (but thanks for taking the time to demo/explain)
Feb 21 2018
On Tuesday, 20 February 2018 at 12:18:47 UTC, rikki cattermole wrote:So the point is moot.ok. I've come around... and the point reall is moot. so.. in that case..another idea...how about a compiler option to output a list of functions. (I don't really expect many will warm to that idea.) Does anyone know of any tool that could do such a thing? I just want of a list of functions from a source code file. Who would have thought it would be that hard ;-)
Feb 20 2018
psychoticRabbit wrote:On Tuesday, 20 February 2018 at 12:18:47 UTC, rikki cattermole wrote:dmd. dmd -X will output alot of interesting info.So the point is moot.ok. I've come around... and the point reall is moot. so.. in that case..another idea...how about a compiler option to output a list of functions. (I don't really expect many will warm to that idea.) Does anyone know of any tool that could do such a thing?
Feb 20 2018
On Tuesday, 20 February 2018 at 13:27:08 UTC, psychoticRabbit wrote:so.. in that case..another idea...how about a compiler option to output a list of functions. (I don't really expect many will warm to that idea.) Does anyone know of any tool that could do such a thing? I just want of a list of functions from a source code file. Who would have thought it would be that hard ;-)dmd -X spits out the json file with a list of functions and classes and other stuff. Then you can just filter that. Also try https://github.com/dlang-community/D-Scanner which can output such a list as a "ctags" file, which a lot of editors know how to read for jumping around. You can also use a documentation generator like mine https://github.com/adamdruppe/adrdox if you put doc comments on it and get a html and xml output, though for just finding the list I think dmd -X is going to be easier.
Feb 20 2018
On Tuesday, 20 February 2018 at 15:26:12 UTC, Adam D. Ruppe wrote:dmd -X spits out the json file with a list of functions and classes and other stuff. Then you can just filter that.'dmd -X' looks like the perfect solution for my need. thanks.
Feb 20 2018
On Wednesday, 21 February 2018 at 01:58:17 UTC, psychoticRabbit wrote:On Tuesday, 20 February 2018 at 15:26:12 UTC, Adam D. Ruppe wrote:I don't know what exactly you plan to do, but the AST dump from DScanner is usually also quite handy: https://github.com/dlang-community/D-Scanner#ast-dump In fact, with libdparse, you don't get it as XML, but as AST: https://github.com/dlang-community/libdparse Example: https://run.dlang.io/is/qZsGDDdmd -X spits out the json file with a list of functions and classes and other stuff. Then you can just filter that.'dmd -X' looks like the perfect solution for my need. thanks.
Feb 22 2018
On Thursday, 22 February 2018 at 14:50:37 UTC, Seb wrote:On Wednesday, 21 February 2018 at 01:58:17 UTC, psychoticRabbit wrote:I want to do some cyber-security related analysis of D code bases - so looking for tools that might assist. I'll definately go have a look at dscanner and libdparse too. Thanks for the tip.On Tuesday, 20 February 2018 at 15:26:12 UTC, Adam D. Ruppe wrote:I don't know what exactly you plan to do, but the AST dump from DScanner is usually also quite handy: https://github.com/dlang-community/D-Scanner#ast-dump In fact, with libdparse, you don't get it as XML, but as AST: https://github.com/dlang-community/libdparse Example: https://run.dlang.io/is/qZsGDDdmd -X spits out the json file with a list of functions and classes and other stuff. Then you can just filter that.'dmd -X' looks like the perfect solution for my need. thanks.
Feb 22 2018
On Tuesday, 20 February 2018 at 15:26:12 UTC, Adam D. Ruppe wrote:dmd -X spits out the json file with a list of functions and classes and other stuff. Then you can just filter that.do you know why the first and last character of the output from "dmd -o- -X somefile.d" are [ and ] with all the json inbetween. I'm don't really know json (never had a need to know) but as I try different json parsers, the first thing I have to do (before giving it to the json parser), is strip off the first and last character of that output. so why put them there in the first place, is my question.
Feb 22 2018
On Thu, 22 Feb 2018 10:41:48 +0000, psychoticRabbit wrote:On Tuesday, 20 February 2018 at 15:26:12 UTC, Adam D. Ruppe wrote:They form an array. `[1, 2, 3]` is an array of numbers, and `[{"a":1}, {"b":2}, {"c":3}]` is an array of objects.dmd -X spits out the json file with a list of functions and classes and other stuff. Then you can just filter that.do you know why the first and last character of the output from "dmd -o- -X somefile.d" are [ and ] with all the json inbetween. I'm don't really know json (never had a need to know) but as I try different json parsers, the first thing I have to do (before giving it to the json parser), is strip off the first and last character of that output. so why put them there in the first place, is my question.
Feb 22 2018
On Thursday, 22 February 2018 at 11:32:59 UTC, rjframe wrote:On Thu, 22 Feb 2018 10:41:48 +0000, psychoticRabbit wrote:here is my point though: ============= module test; import std.stdio, std.file, std.json; void main() { string myFile= "source.json"; // a file produced by: dmd -o- -X source.d string js = readText(myFile); JSONValue j = parseJSON( js[1..$-1] ); // why do I have to do this?? writefln("%s = %s", j["kind"].str, j["name"].str); writefln("file = %s", j["file"].str); } ==============On Tuesday, 20 February 2018 at 15:26:12 UTC, Adam D. Ruppe wrote:They form an array. `[1, 2, 3]` is an array of numbers, and `[{"a":1}, {"b":2}, {"c":3}]` is an array of objects.dmd -X spits out the json file with a list of functions and classes and other stuff. Then you can just filter that.do you know why the first and last character of the output from "dmd -o- -X somefile.d" are [ and ] with all the json inbetween. I'm don't really know json (never had a need to know) but as I try different json parsers, the first thing I have to do (before giving it to the json parser), is strip off the first and last character of that output. so why put them there in the first place, is my question.
Feb 22 2018
On 02/22/2018 12:54 PM, psychoticRabbit wrote:module test; import std.stdio, std.file, std.json; void main() { string myFile= "source.json"; // a file produced by: dmd -o- -X source.d string js = readText(myFile); JSONValue j = parseJSON( js[1..$-1] ); // why do I have to do this?? writefln("%s = %s", j["kind"].str, j["name"].str); writefln("file = %s", j["file"].str); }You don't have to remove the brackets. You just have to process the result correctly. It's not an object but an array with an object as its first element. If you're only interested in the first module (e.g. because you know that there is exactly one), you can use `j[0]["kind"]`, `j[0]["name"]`, `j[0]["file"]`. If you want to handle multiple modules, you can loop over the array: ---- foreach (size_t i, item; j) /* It's a bit silly that `foreach (item; j)` doesn't work. */ { /* ... use `item["kind"]` etc. here ... */ } ----
Feb 22 2018
On Thursday, 22 February 2018 at 13:17:42 UTC, ag0aep6g wrote:You don't have to remove the brackets. You just have to process the result correctly. It's not an object but an array with an object as its first element.ok. I think I demonstrated that I don't know what I'm doing with the json ;-) thanks for the tips (I tried it and it worked). Now..I better go off and learn more about parsing json...
Feb 22 2018
On Tuesday, 20 February 2018 at 12:15:57 UTC, psychoticRabbit wrote:I've noticed that Go and Rust annotate functions. func (in go) fn (in rust) I was kind of wondering why they made that choice, given compilers in many languages do not. Would this be a useful feature in D? Everything else seems to have an annotation (e.g structs, classes.) So why not functions? What are people's thoughts about it? My first thought is to make it an optional annotation, for the benefit of developing source code analysis tools that can 'more easily' find functions in source code (i.e. The D compiler can just strip it off and do nothing with it.). That way programmers that see no benefit in it, don't have to deal with it.If you want to annotate your functions (rather than someone elses), you could do something like below. Ideally this would also include a compile-time check that foo is a function. Maybe use Atila's concepts library? enum Function; Function void foo() { } void main() { }
Feb 20 2018
On Tuesday, 20 February 2018 at 12:15:57 UTC, psychoticRabbit wrote:I've noticed that Go and Rust annotate functions. func (in go) fn (in rust) I was kind of wondering why they made that choice, given compilers in many languages do not.A lot of dynamic languages do too function foo() {} // javascript etc. I suspect a good chunk of it is just to make it look more familiar to them. It might also have been so they can hack up "goto definition" features in editors without a real parser...Everything else seems to have an annotation (e.g structs, classes.) So why not functions?The reason is just that we don't need it - the pattern of code makes it quite obvious to the compiler what is and isn't a function. But like someone else said, we can already optionally tag stuff. Two ways: enum Function; Function void foo() or a simple comment: /// function foo void foo() {} We also have various goto definition features from parsers. In fact, I added something for this to my editor just this last saturday. It is a macro that runs "doc2 --locate-symbol=name.here -" and pipes the current source code to it, then goes to the line it returns. There's also `dmd -X` and `dscanner` both of which can read a list of files you give it and find a definition. (mine is different in two ways: 1) it looks up in scope and can do fully-qualified names and 2) it works with pipes instead of written files, so it can parse on demand) $ cat simpledisplay.d | ~/program/d-diff/doc2 --locate-symbol SimpleWindow.impl - 2018 and, of course, 2018 is the line where impl is introduced. impl is a mixin template btw - so the parser approach works on more than just functions!
Feb 20 2018
On Tuesday, 20 February 2018 at 12:15:57 UTC, psychoticRabbit wrote:I've noticed that Go and Rust annotate functions. func (in go) fn (in rust) I was kind of wondering why they made that choice, given compilers in many languages do not.On Tuesday, 20 February 2018 at 12:15:57 UTC, psychoticRabbit wrote:I've noticed that Go and Rust annotate functions. func (in go) fn (in rust) I was kind of wondering why they made that choice, given compilers in many languages do not.I think it is common to have a keyword used in function definition - outside the C-family. The Pascal family has keywords for function and procedure declaration, as does Fortran. It looks like Cobol uses the "function" keyword for when you call a function and "function-id" for when you define it. Perl, Python and Ruby all have a keyword for function definition.Would this be a useful feature in D? Everything else seems to have an annotation (e.g structs, classes.) So why not functions? What are people's thoughts about it?I think keywords for functions may be to avoid or minimize the difficulty C and C++ have with declaring (and deciphering the declarations of) function pointers. Seems it also would have prevented years of C++ having "the most vexing parse", where a class instantiation can be confused with a function declaration.
Feb 21 2018