-
-
Notifications
You must be signed in to change notification settings - Fork 147
Prevent empty statements at the end of --eval or --loop code #303
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,7 +17,7 @@ | |
| import std.algorithm, std.array, core.stdc.stdlib, std.datetime, | ||
| std.digest.md, std.exception, std.file, std.getopt, | ||
| std.parallelism, std.path, std.process, std.range, std.regex, | ||
| std.stdio, std.string, std.typetuple; | ||
| std.stdio, std.string, std.typecons, std.typetuple; | ||
|
|
||
| version (Posix) | ||
| { | ||
|
|
@@ -180,18 +180,14 @@ int main(string[] args) | |
| { | ||
| enforce(programPos == args.length, "Cannot have both --loop and a " ~ | ||
| "program file ('" ~ args[programPos] ~ "')."); | ||
| root = makeEvalFile(importWorld ~ "void main(char[][] args) { " | ||
| ~ "foreach (line; std.stdio.stdin.byLine()) {\n" | ||
| ~ std.string.join(loop, "\n") | ||
| ~ ";\n} }"); | ||
| root = makeEvalFile(makeEvalCode(loop, Yes.loop)); | ||
| argsBeforeProgram ~= "-d"; | ||
| } | ||
| else if (eval.ptr) | ||
| { | ||
| enforce(programPos == args.length, "Cannot have both --eval and a " ~ | ||
| "program file ('" ~ args[programPos] ~ "')."); | ||
| root = makeEvalFile(importWorld ~ "void main(char[][] args) {\n" | ||
| ~ std.string.join(eval, "\n") ~ ";\n}"); | ||
| root = makeEvalFile(makeEvalCode(eval, No.loop)); | ||
| argsBeforeProgram ~= "-d"; | ||
| } | ||
| else if (programPos < args.length) | ||
|
|
@@ -839,6 +835,101 @@ import std.stdio, std.algorithm, std.array, std.ascii, std.base64, | |
| std.zlib; | ||
| "; | ||
|
|
||
| /** | ||
| Joins together the code provided via an `--eval` or `--loop` | ||
| flag, ensuring a trailing `;` is added if not already provided | ||
| by the user | ||
|
|
||
| Params: | ||
| eval = array of strings generated by the `--eval` | ||
| or `--loop` rdmd flags | ||
|
|
||
| Returns: | ||
| string of code to be evaluated, corresponding to the | ||
| inner code of either the program or the loop | ||
| */ | ||
| string innerEvalCode(string[] eval) | ||
| { | ||
| import std.string : join, stripRight; | ||
| // assumeSafeAppend just to avoid unnecessary reallocation | ||
| string code = eval.join("\n").stripRight.assumeSafeAppend; | ||
| if (code.length > 0 && code[$ - 1] != ';') | ||
| code ~= ';'; | ||
| return code; | ||
| } | ||
|
|
||
| unittest | ||
| { | ||
| assert(innerEvalCode([`writeln("Hello!")`]) == `writeln("Hello!");`); | ||
| assert(innerEvalCode([`writeln("Hello!");`]) == `writeln("Hello!");`); | ||
|
|
||
| // test with trailing whitespace | ||
| assert(innerEvalCode([`writeln("Hello!") `]) == `writeln("Hello!");`); | ||
| assert(innerEvalCode([`writeln("Hello!"); `]) == `writeln("Hello!");`); | ||
|
|
||
| // test with multiple entries | ||
| assert(innerEvalCode([`writeln("Hello!"); `, `writeln("You!") `]) | ||
| == "writeln(\"Hello!\"); \nwriteln(\"You!\");"); | ||
| assert(innerEvalCode([`writeln("Hello!"); `, `writeln("You!"); `]) | ||
| == "writeln(\"Hello!\"); \nwriteln(\"You!\");"); | ||
| } | ||
|
|
||
| /** | ||
| Formats the code provided via `--eval` or `--loop` flags into a | ||
| string of complete program code that can be written to a file | ||
| and then compiled | ||
|
|
||
| Params: | ||
| eval = array of strings generated by the `--eval` or | ||
| `--loop` rdmd flags | ||
| loop = set to `Yes.loop` if this code comes from a | ||
| `--loop` flag, `No.loop` if it comes from an | ||
| `--eval` flag | ||
|
|
||
| Returns: | ||
| string of code to be evaluated, corresponding to the | ||
| inner code of either the program or the loop | ||
| */ | ||
| string makeEvalCode(string[] eval, Flag!"loop" loop) | ||
| { | ||
| import std.format : format; | ||
| immutable codeFormat = importWorld | ||
| ~ "void main(char[][] args) {%s%s\n%s}"; | ||
|
|
||
| immutable innerCodeOpening = | ||
| loop ? " foreach (line; std.stdio.stdin.byLine()) {\n" | ||
| : "\n"; | ||
|
|
||
| immutable innerCodeClosing = loop ? "} " : ""; | ||
|
|
||
| return format(codeFormat, | ||
| innerCodeOpening, | ||
| innerEvalCode(eval), | ||
| innerCodeClosing); | ||
| } | ||
|
|
||
| unittest | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could be
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| { | ||
| // innerEvalCode already tests the cases for different | ||
| // contents in `eval` array, so let's focus on testing | ||
| // the difference based on the `loop` flag | ||
| assert(makeEvalCode([`writeln("Hello!") `], No.loop) == | ||
| importWorld | ||
| ~ "void main(char[][] args) {\n" | ||
| ~ "writeln(\"Hello!\");\n}"); | ||
|
|
||
| assert(makeEvalCode([`writeln("What!"); `], No.loop) == | ||
| importWorld | ||
| ~ "void main(char[][] args) {\n" | ||
| ~ "writeln(\"What!\");\n}"); | ||
|
|
||
| assert(makeEvalCode([`writeln("Loop!") ; `], Yes.loop) == | ||
| importWorld | ||
| ~ "void main(char[][] args) { " | ||
| ~ "foreach (line; std.stdio.stdin.byLine()) {\n" | ||
| ~ "writeln(\"Loop!\") ;\n} }"); | ||
| } | ||
|
|
||
| string makeEvalFile(string todo) | ||
| { | ||
| auto pathname = myOwnTmpDir; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Idiomatic D would just use
.byLine- you could use this opportunity to change this bit.