www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Proposal: __traits(getComment, symbol)

reply FeepingCreature <feepingcreature gmail.com> writes:
I propose a way to get the comment on a symbol at compile time. I 
believe this was already rejected, though I don't know why; I'd 
expect it to be something like "code should not change behavior 
due to a comment." I think that now that we have user-defined 
annotations there is a much lower risk of that.

Why do I want this? Generating special documentation/annotated 
interfaces from D code is a *lot* easier if you can get the 
compiler to do your introspection work for you. I want to 
generate Swagger files documenting our REST services, and I want 
to use D comments to document them. Right now, I will have to do 
a weird hybrid dance where I generate the D type graph on the D 
side with compiletime introspection, output it to a file, 
simultaneously generate the Ddoc JSON file with -D -X to fish out 
the comments, then fuse the two together. There is no need for 
this, but for the absence of __traits(getComment).
Aug 28
next sibling parent reply Eugene Wissner <belka caraus.de> writes:
On Wednesday, 28 August 2019 at 08:51:24 UTC, FeepingCreature 
wrote:
 I propose a way to get the comment on a symbol at compile time. 
 I believe this was already rejected, though I don't know why; 
 I'd expect it to be something like "code should not change 
 behavior due to a comment." I think that now that we have 
 user-defined annotations there is a much lower risk of that.

 Why do I want this? Generating special documentation/annotated 
 interfaces from D code is a *lot* easier if you can get the 
 compiler to do your introspection work for you. I want to 
 generate Swagger files documenting our REST services, and I 
 want to use D comments to document them. Right now, I will have 
 to do a weird hybrid dance where I generate the D type graph on 
 the D side with compiletime introspection, output it to a file, 
 simultaneously generate the Ddoc JSON file with -D -X to fish 
 out the comments, then fuse the two together. There is no need 
 for this, but for the absence of __traits(getComment).
I think the languages that have "comment reflection", use this instead of custom attributes. In PHP for example /** * ORM\Entity(...) */ class MyEntity { ... } Because there are no attributes. Why can't you just use UDAs instead of comments?
Aug 28
next sibling parent reply FeepingCreature <feepingcreature gmail.com> writes:
On Wednesday, 28 August 2019 at 09:04:06 UTC, Eugene Wissner 
wrote:
 Why can't you just use UDAs instead of comments?
Why does D use comments instead of UDAs? Because I *don't* want to change behavior, I want to extract documentation. Comments are for documentation.
Aug 28
parent reply Sebastiaan Koppe <mail skoppe.eu> writes:
On Wednesday, 28 August 2019 at 09:17:02 UTC, FeepingCreature 
wrote:
 On Wednesday, 28 August 2019 at 09:04:06 UTC, Eugene Wissner 
 wrote:
 Why can't you just use UDAs instead of comments?
Why does D use comments instead of UDAs? Because I *don't* want to change behavior, I want to extract documentation. Comments are for documentation.
Swagger for Java uses annotations to describe the endpoints. Just create a Swagger struct (plus helper structs) and use like: ``` Swagger(ApiResponses([ ApiResponse(code = 200, message = "...", response = Entity), ApiResponse(code = 404, message = "listing not found") ]), Put("/entities/{id}"), Consumes([MediaType.APPLICATION_JSON_VALUE]), Produces([MediaType.APPLICATION_JSON_VALUE]) ) Entity endpoint(string id) { ... } ``` I think it beats parsing (or writing) comments...
Aug 28
parent reply Eugene Wissner <belka caraus.de> writes:
On Wednesday, 28 August 2019 at 09:35:54 UTC, Sebastiaan Koppe 
wrote:
 Just create a Swagger struct (plus helper structs) and use like:

 ```
  Swagger(ApiResponses([
     ApiResponse(code = 200, message = "...", response = Entity),
     ApiResponse(code = 404, message = "listing not found")
   ]),
   Put("/entities/{id}"),
   Consumes([MediaType.APPLICATION_JSON_VALUE]),
   Produces([MediaType.APPLICATION_JSON_VALUE])
 )
 Entity endpoint(string id) { ... }
 ```

 I think it beats parsing (or writing) comments...
and provides some static typing, because structs can be used, and probably better error messages than reinventing a Ddoc parser.
Aug 28
parent reply FeepingCreature <feepingcreature gmail.com> writes:
On Wednesday, 28 August 2019 at 09:55:47 UTC, Eugene Wissner 
wrote:
 On Wednesday, 28 August 2019 at 09:35:54 UTC, Sebastiaan Koppe 
 wrote:
 Just create a Swagger struct (plus helper structs) and use 
 like:

 ```
  Swagger(ApiResponses([
     ApiResponse(code = 200, message = "...", response = 
 Entity),
     ApiResponse(code = 404, message = "listing not found")
   ]),
   Put("/entities/{id}"),
   Consumes([MediaType.APPLICATION_JSON_VALUE]),
   Produces([MediaType.APPLICATION_JSON_VALUE])
 )
 Entity endpoint(string id) { ... }
 ```

 I think it beats parsing (or writing) comments...
and provides some static typing, because structs can be used, and probably better error messages than reinventing a Ddoc parser.
Right but also UDAs look terrible as docs. All this is info I already have. The only thing I can't get is the documentation comment on them. How about this: /** * Do a thing. * * Params: * foo = A parameter */ void method(); would get converted by the compiler to (DDoc.Description("Do a thing")) (DDoc.Param!Foo(1, "foo", "A parameter")) void method(); That'd give the best of both worlds.
Aug 28
parent FeepingCreature <feepingcreature gmail.com> writes:
On Wednesday, 28 August 2019 at 10:29:24 UTC, FeepingCreature 
wrote:
  (DDoc.Description("Do a thing"))
  (DDoc.Param!Foo(1, "foo", "A parameter"))
 void method();

 That'd give the best of both worlds.
Sorry, that's a terrible way to do it. I should have written (DDoc.Param("foo", "A parameter")). Carry on.
Aug 28
prev sibling parent reply Per =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Wednesday, 28 August 2019 at 09:04:06 UTC, Eugene Wissner 
wrote:
 I think the languages that have "comment reflection", use this 
 instead of custom attributes. In PHP for example

 /**
  *  ORM\Entity(...)
  */
 class MyEntity { ... }


 Because there are no attributes. Why can't you just use UDAs 
 instead of comments?
We must also take into account differences in compilation time and memory for alternative solutions, in this case __traits vs UDAs.
Aug 28
parent Eugene Wissner <belka caraus.de> writes:
On Wednesday, 28 August 2019 at 10:00:07 UTC, Per Nordlöw wrote:
 On Wednesday, 28 August 2019 at 09:04:06 UTC, Eugene Wissner 
 wrote:
 I think the languages that have "comment reflection", use this 
 instead of custom attributes. In PHP for example

 /**
  *  ORM\Entity(...)
  */
 class MyEntity { ... }


 Because there are no attributes. Why can't you just use UDAs 
 instead of comments?
We must also take into account differences in compilation time and memory for alternative solutions, in this case __traits vs UDAs.
UDAs are already supported. If you want to read the comments at compile-time, as a next step you want to parse them, validate the types and content, generate and write some output...
Aug 28
prev sibling next sibling parent Jacob Carlborg <doob me.com> writes:
On 2019-08-28 10:51, FeepingCreature wrote:
 I propose a way to get the comment on a symbol at compile time. I 
 believe this was already rejected, though I don't know why; I'd expect 
 it to be something like "code should not change behavior due to a 
 comment." I think that now that we have user-defined annotations there 
 is a much lower risk of that.
 
 Why do I want this? Generating special documentation/annotated 
 interfaces from D code is a *lot* easier if you can get the compiler to 
 do your introspection work for you. I want to generate Swagger files 
 documenting our REST services, and I want to use D comments to document 
 them. Right now, I will have to do a weird hybrid dance where I generate 
 the D type graph on the D side with compiletime introspection, output it 
 to a file, simultaneously generate the Ddoc JSON file with -D -X to fish 
 out the comments, then fuse the two together. There is no need for this, 
 but for the absence of __traits(getComment).
 
You can try using the compiler as a library [1]. [1] https://code.dlang.org/packages/dmd -- /Jacob Carlborg
Aug 28
prev sibling next sibling parent reply Mike Franklin <slavo5150 yahoo.com> writes:
On Wednesday, 28 August 2019 at 08:51:24 UTC, FeepingCreature 
wrote:
 I propose a way to get the comment on a symbol at compile time. 
 I believe this was already rejected, though I don't know why; 
 I'd expect it to be something like "code should not change 
 behavior due to a comment." I think that now that we have 
 user-defined annotations there is a much lower risk of that.

 Why do I want this? Generating special documentation/annotated 
 interfaces from D code is a *lot* easier if you can get the 
 compiler to do your introspection work for you. I want to 
 generate Swagger files documenting our REST services, and I 
 want to use D comments to document them. Right now, I will have 
 to do a weird hybrid dance where I generate the D type graph on 
 the D side with compiletime introspection, output it to a file, 
 simultaneously generate the Ddoc JSON file with -D -X to fish 
 out the comments, then fuse the two together. There is no need 
 for this, but for the absence of __traits(getComment).
In general, I'm in favor of adding any compiler information to the `__traits` system. This one is particularly interesting though. I once gave a talk at DConf explaining how I copy and pasted register table from a datasheet into an application, and had it spit out D code. I later ported the code to D (https://github.com/JinShil/stm32_datasheet_to_d). With your proposal, I could just paste the text from the datasheet into my DDoc comment and have D generate the code for me. Chuckle, Chuckle. Now think what people more "creative" than I could come up with. :-) I'm not sure if it would be good practice. Mike
Aug 28
next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 8/28/19 5:44 AM, Mike Franklin wrote:
 I once gave a talk at DConf explaining how I copy and pasted register 
 table from a datasheet into an application, and had it spit out D code.  
 I later ported the code to D 
 (https://github.com/JinShil/stm32_datasheet_to_d).  With your proposal, 
 I could just paste the text from the datasheet into my DDoc comment and 
 have D generate the code for me.  Chuckle, Chuckle.
Ahem, I didn't get to it (thanks, fire drill), but your presentation (which is still one of my favorites), was actually referenced in my presentation "extras" ;) Start at page 63: http://dconf.org/2019/talks/schveighoffer.pdf
 Now think what people more "creative" than I could come up with. :-)
 
 I'm not sure if it would be good practice.
I think the idea of using an actual spec to write your register code is insanely useful, even if it takes hours to compile ;) It can't be worse than hours spent realizing you misread something in the spec. -Steve
Aug 28
parent Mike Franklin <slavo5150 yahoo.com> writes:
On Wednesday, 28 August 2019 at 22:07:28 UTC, Steven 
Schveighoffer wrote:

 Ahem, I didn't get to it (thanks, fire drill), but your 
 presentation (which is still one of my favorites), was actually 
 referenced in my presentation "extras" ;)

 Start at page 63: http://dconf.org/2019/talks/schveighoffer.pdf
Wow! Thanks for that. :-)
 Now think what people more "creative" than I could come up 
 with. :-)
 
 I'm not sure if it would be good practice.
I think the idea of using an actual spec to write your register code is insanely useful, even if it takes hours to compile ;) It can't be worse than hours spent realizing you misread something in the spec.
So true. I have to same I'm on the fence with this idea. It is tempting. Mike
Aug 28
prev sibling parent FeepingCreature <feepingcreature gmail.com> writes:
On Wednesday, 28 August 2019 at 09:44:10 UTC, Mike Franklin wrote:
 In general, I'm in favor of adding any compiler information to 
 the `__traits` system.  This one is particularly interesting 
 though.

 I once gave a talk at DConf explaining how I copy and pasted 
 register table from a datasheet into an application, and had it 
 spit out D code.  I later ported the code to D 
 (https://github.com/JinShil/stm32_datasheet_to_d).  With your 
 proposal, I could just paste the text from the datasheet into 
 my DDoc comment and have D generate the code for me.  Chuckle, 
 Chuckle.

 Now think what people more "creative" than I could come up 
 with.  :-)

 I'm not sure if it would be good practice.

 Mike
I personally feel that with string mixin, CTFE, import() and now UDAs, we have already given the programmer entirely sufficient lengths of rope to hang themselves in whichever way they desire. Adding another length of rope to create an exciting new way to cause self-harm will not at this point increase the death and injury rate an appreciable amount. That ship has sailed, made landfall in the Americas, and is currently on the return trip.
Aug 28
prev sibling next sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Wednesday, August 28, 2019 2:51:24 AM MDT FeepingCreature via 
Digitalmars-d wrote:
 I propose a way to get the comment on a symbol at compile time. I
 believe this was already rejected, though I don't know why; I'd
 expect it to be something like "code should not change behavior
 due to a comment." I think that now that we have user-defined
 annotations there is a much lower risk of that.

 Why do I want this? Generating special documentation/annotated
 interfaces from D code is a *lot* easier if you can get the
 compiler to do your introspection work for you. I want to
 generate Swagger files documenting our REST services, and I want
 to use D comments to document them. Right now, I will have to do
 a weird hybrid dance where I generate the D type graph on the D
 side with compiletime introspection, output it to a file,
 simultaneously generate the Ddoc JSON file with -D -X to fish out
 the comments, then fuse the two together. There is no need for
 this, but for the absence of __traits(getComment).
I confess that I thought that there already was a trait for getting the ddoc comment associated with a symbol, but looking at the documentation, that doesn't appear to be the case. - Jonathan M Davis
Aug 28
prev sibling next sibling parent reply John Colvin <john.loughran.colvin gmail.com> writes:
On Wednesday, 28 August 2019 at 08:51:24 UTC, FeepingCreature 
wrote:
 I propose a way to get the comment on a symbol at compile time. 
 I believe this was already rejected, though I don't know why; 
 I'd expect it to be something like "code should not change 
 behavior due to a comment." I think that now that we have 
 user-defined annotations there is a much lower risk of that.

 Why do I want this? Generating special documentation/annotated 
 interfaces from D code is a *lot* easier if you can get the 
 compiler to do your introspection work for you. I want to 
 generate Swagger files documenting our REST services, and I 
 want to use D comments to document them. Right now, I will have 
 to do a weird hybrid dance where I generate the D type graph on 
 the D side with compiletime introspection, output it to a file, 
 simultaneously generate the Ddoc JSON file with -D -X to fish 
 out the comments, then fuse the two together. There is no need 
 for this, but for the absence of __traits(getComment).
The alternative approach would be to have a UDA that would be treated as ddoc.
Aug 28
parent FeepingCreature <feepingcreature gmail.com> writes:
On Wednesday, 28 August 2019 at 11:26:34 UTC, John Colvin wrote:
 The alternative approach would be to have a UDA that would be 
 treated as ddoc.
Personally speaking, that doesn't buy me anything. The primary concern is having good-looking D comments. The secondary concern is being able to generate Swagger. Generated Ddoc html is a very distant third concern. UDAs that are treated as Ddoc would buy me the second at the cost of completely destroying the first; I might as well just use regular UDAs, as was already proposed.
Aug 28
prev sibling parent reply Manu <turkeyman gmail.com> writes:
On Wed, Aug 28, 2019 at 1:55 AM FeepingCreature via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 I propose a way to get the comment on a symbol at compile time. I
 believe this was already rejected, though I don't know why; I'd
 expect it to be something like "code should not change behavior
 due to a comment." I think that now that we have user-defined
 annotations there is a much lower risk of that.

 Why do I want this? Generating special documentation/annotated
 interfaces from D code is a *lot* easier if you can get the
 compiler to do your introspection work for you. I want to
 generate Swagger files documenting our REST services, and I want
 to use D comments to document them. Right now, I will have to do
 a weird hybrid dance where I generate the D type graph on the D
 side with compiletime introspection, output it to a file,
 simultaneously generate the Ddoc JSON file with -D -X to fish out
 the comments, then fuse the two together. There is no need for
 this, but for the absence of __traits(getComment).
I was really interested in this feature back when it was rejected the first time. My use is in video games, we create high-level gameplay code which plugs itself into the editor environment. This code publishes properties and the things that it can do from an editor perspective, and in the editor, it is very nice to be able to hover over values in property tables, and see the documentation for the values in tooltips, which explains what the values are and how they work. We can do this with UDA's, but it's more natural to write documenting comments with documenting comments. In most cases, values have a UDA with this text, which contains a string which is a cut&paste from the comment immediately above, and it's very easy to amend one and forget to amend the other, and they fall out of sync. As a development workflow feature, having compiler access to symbol comments would be very useful in many cases.
Aug 28
parent reply Max Haughton <maxhaton gmail.com> writes:
On Wednesday, 28 August 2019 at 17:35:56 UTC, Manu wrote:
 As a development workflow feature, having compiler access to 
 symbol comments would be very useful in many cases.
Speaking of which, has anyone tried/discussed giving access to a frozen version of the AST through (say) __traits(getAST, symbol)? I'd try it myself but I haven't spent the time learning how dmd works.
Aug 28
next sibling parent reply RazvanN <razvan.nitu1305 gmail.com> writes:
On Wednesday, 28 August 2019 at 22:18:28 UTC, Max Haughton wrote:
 On Wednesday, 28 August 2019 at 17:35:56 UTC, Manu wrote:
 As a development workflow feature, having compiler access to 
 symbol comments would be very useful in many cases.
Speaking of which, has anyone tried/discussed giving access to a frozen version of the AST through (say) __traits(getAST, symbol)? I'd try it myself but I haven't spent the time learning how dmd works.
Whatever you want to do with traits(getAST) would likely be a job for dmd as a library.
Aug 29
next sibling parent Petar Kirov [ZombineDev] <petar.p.kirov gmail.com> writes:
On Thursday, 29 August 2019 at 10:20:28 UTC, RazvanN wrote:
 On Wednesday, 28 August 2019 at 22:18:28 UTC, Max Haughton 
 wrote:
 On Wednesday, 28 August 2019 at 17:35:56 UTC, Manu wrote:
 As a development workflow feature, having compiler access to 
 symbol comments would be very useful in many cases.
Speaking of which, has anyone tried/discussed giving access to a frozen version of the AST through (say) __traits(getAST, symbol)? I'd try it myself but I haven't spent the time learning how dmd works.
Whatever you want to do with traits(getAST) would likely be a job for dmd as a library.
The use cases for traits(getAST) are CTFE-only by definition (think implementing AST-macros), so using dmd as a library is not an option. See for example: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/expression-trees/ https://doc.rust-lang.org/reference/procedural-macros.html https://doc.rust-lang.org/1.30.0/book/2018-edition/appendix-04-macros.html https://nim-lang.github.io/Nim/tut3.html https://nim-lang.org/blog/2018/06/07/create-a-simple-macro.html https://nim-lang.github.io/Nim/manual.html#macros BTW, we had a long discussion about that on Slack a while ago: https://dlang.slack.com/archives/C1ZDHBB2S/p1511992601000433
Aug 29
prev sibling next sibling parent reply Petar Kirov [ZombineDev] <petar.p.kirov gmail.com> writes:
On Thursday, 29 August 2019 at 10:20:28 UTC, RazvanN wrote:
 Whatever you want to do with traits(getAST) would likely be a 
 job for dmd as a library.
BTW, the argument "<..> is a job for the compiler as a library" is what languages like Go use as an excuse for why they don't have neither templates, nor even generics. And if you want type-safety, you would use build-time (not compile-time) code-generation tools like this: https://godoc.org/github.com/searKing/golang/tools/cmd/go-syncmap https://godoc.org/github.com/searKing/golang/tools/cmd/go-syncpool https://github.com/ChimeraCoder/gojson In D such tools are completely replaces by templates (modulo compilation time trade off). If you have experience with languages that have some sort of AST macros, you start to think of languages that don't, just as we think of languages without templates or generics, like Go. See also https://web.archive.org/web/20190622093122/http://wiki.c2.com/?BlubParadox ;)
Aug 29
parent reply Jacob Carlborg <doob me.com> writes:
On 2019-08-29 13:24, Petar Kirov [ZombineDev] wrote:

 BTW, the argument "<..> is a job for the compiler as a library" is what 
 languages like Go use as an excuse for why they don't have neither 
 templates, nor even generics. And if you want type-safety, you would use 
 build-time (not compile-time) code-generation tools like this:
 
 https://godoc.org/github.com/searKing/golang/tools/cmd/go-syncmap
 https://godoc.org/github.com/searKing/golang/tools/cmd/go-syncpool
 https://github.com/ChimeraCoder/gojson
 
 In D such tools are completely replaces by templates (modulo compilation 
 time trade off). If you have experience with languages that have some 
 sort of AST macros, you start to think of languages that don't, just as 
 we think of languages without templates or generics, like Go.
 
 See also 
 https://web.archive.org/web/20190622093122/http://wiki.c2.com/?BlubParadox 
 ;)
True, although I think there are use cases for both AST macros/`__traits(getAST)` and using the compiler as a library. Something like inspecting the AST of all source files of a project and do something seems a bit difficult to do with AST macros/`__traits(getAST)`. -- /Jacob Carlborg
Aug 29
parent Petar Kirov [ZombineDev] <petar.p.kirov gmail.com> writes:
On Thursday, 29 August 2019 at 12:27:33 UTC, Jacob Carlborg wrote:
 True, although I think there are use cases for both AST 
 macros/`__traits(getAST)` and using the compiler as a library.

 Something like inspecting the AST of all source files of a 
 project and do something seems a bit difficult to do with AST 
 macros/`__traits(getAST)`.
Yes of course, I'm just saying that __traits(getAST) is definitely a necessary feature, just like templates are today for D. That doesn't exclude all the other valid reasons for using the compiler as a library.
Aug 29
prev sibling parent Max Haughton <maxhaton gmail.com> writes:
On Thursday, 29 August 2019 at 10:20:28 UTC, RazvanN wrote:
 On Wednesday, 28 August 2019 at 22:18:28 UTC, Max Haughton 
 wrote:
 On Wednesday, 28 August 2019 at 17:35:56 UTC, Manu wrote:
 As a development workflow feature, having compiler access to 
 symbol comments would be very useful in many cases.
Speaking of which, has anyone tried/discussed giving access to a frozen version of the AST through (say) __traits(getAST, symbol)? I'd try it myself but I haven't spent the time learning how dmd works.
Whatever you want to do with traits(getAST) would likely be a job for dmd as a library.
I know but I had a idea to generate instruction selection trees based on D code and a theorem prover which would be very nice to do actually at compile time. Inefficient but very cool You also can't get a list of template constraints from traits, I don't think.
Aug 29
prev sibling next sibling parent Jacob Carlborg <doob me.com> writes:
On 2019-08-29 00:18, Max Haughton wrote:

 Speaking of which, has anyone tried/discussed giving access to a frozen 
 version of the AST through (say) __traits(getAST, symbol)? I'd try it 
 myself but I haven't spent the time learning how dmd works.
Yes, it's been discussed. Also AST macros which are related has been discussed quite a lot. I've worked a bit on the compiler to implement AST macros [1]. `__traits(getAST)` would be half of what's required for AST macros. It's pretty easy to do, just a bit tedious. [1] https://github.com/jacob-carlborg/dmd/tree/macro -- /Jacob Carlborg
Aug 29
prev sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Wednesday, August 28, 2019 4:18:28 PM MDT Max Haughton via Digitalmars-d 
wrote:
 On Wednesday, 28 August 2019 at 17:35:56 UTC, Manu wrote:
 As a development workflow feature, having compiler access to
 symbol comments would be very useful in many cases.
Speaking of which, has anyone tried/discussed giving access to a frozen version of the AST through (say) __traits(getAST, symbol)? I'd try it myself but I haven't spent the time learning how dmd works.
Walter has made it quite clear that he has no interest in exposing the AST to the program or in having something like AST macros in the language. It's come up time and time again, and it's always rejected. - Jonathan M Davis
Aug 29
parent Jacob Carlborg <doob me.com> writes:
On 2019-08-30 07:41, Jonathan M Davis wrote:

 Walter has made it quite clear that he has no interest in exposing the AST
 to the program or in having something like AST macros in the language. It's
 come up time and time again, and it's always rejected.
Copy constructors and binding rvalues to references have come up several times throughout the years and has always been rejected. Now we have copy constructors in the language and most likely binding rvalues to references soon. The funny thing though, is that at the first D conference Walter presented a talk about D2 (if I recall correctly) that included AST macros as one of the features. Not sure what or who changed his mind about that. -- /Jacob Carlborg
Aug 31