Re: Annotation of functions
On Thursday, 22 February 2018 at 14:50:37 UTC, Seb wrote: 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: 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. 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/qZsGDD 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.
Re: Annotation of functions
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: 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. 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/qZsGDD
Re: Annotation of functions
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...
Re: Annotation of functions
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 ... */ }
Re: Annotation of functions
On Thursday, 22 February 2018 at 11:32:59 UTC, rjframe wrote: On Thu, 22 Feb 2018 10:41:48 +, psychoticRabbit wrote: 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. They form an array. `[1, 2, 3]` is an array of numbers, and `[{"a":1}, {"b":2}, {"c":3}]` is an array of objects. 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); } ==
Re: Annotation of functions
On Thu, 22 Feb 2018 10:41:48 +, psychoticRabbit wrote: > 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. They form an array. `[1, 2, 3]` is an array of numbers, and `[{"a":1}, {"b":2}, {"c":3}]` is an array of objects.
Re: Annotation of functions
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.
Re: Annotation of functions
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.
Re: Annotation of functions
On Wednesday, 21 February 2018 at 01:53:42 UTC, psychoticRabbit wrote: 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) 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.
Re: Annotation of functions
On 2/20/18 8:53 PM, psychoticRabbit wrote: 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) 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. -Steve
Re: Annotation of functions
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.
Re: Annotation of functions
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)
Re: Annotation of functions
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.
Re: Annotation of functions
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 def foo(): # python 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!
Re: Annotation of functions
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() { }
Re: Annotation of functions
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: > > 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()); 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 Davis
Re: Annotation of functions
On Tuesday, 20 February 2018 at 13:39:17 UTC, bauss wrote: 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: 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 ;-) 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; }"); } } 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); }
Re: Annotation of functions
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: 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 ;-) 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; }"); } }
Re: Annotation of functions
psychoticRabbit wrote: 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? dmd. dmd -X will output alot of interesting info.
Re: Annotation of functions
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 ;-)
Re: Annotation of functions
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());
Re: Annotation of functions
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).
Re: Annotation of functions
On 20/02/2018 12:35 PM, psychoRabbit wrote: 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? 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.
Re: Annotation of functions
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.
Re: Annotation of functions
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.