Skip to content

Commit

Permalink
Don't add explicit returns in do blocks (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
fredrikekre authored Oct 20, 2024
1 parent fcc4611 commit 65f4cc3
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 22 deletions.
15 changes: 4 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -411,9 +411,8 @@ x = a + b *
### Explicit `return`
Explicit `return` statements are ensured in function/macro definitions as well as in
`do`-blocks by adding `return` in front of the last expression, with some exceptions listed
below.
Explicit `return` statements are ensured in function and macro definitions by adding
`return` in front of the last expression, with some exceptions listed below.
- If the last expression is a `for` or `while` loop (which both always evaluate to
`nothing`) `return` is added *after* the loop.
Expand All @@ -423,6 +422,8 @@ below.
there is no `return` inside the block.
- If the last expression is a macro call, the `return` is only added in case there is no
`return` inside the macro.
- No `return` is added in short form functions (`f(...) = ...`), short form anonymous
functions (`(...) -> ...`), and `do`-blocks (`f(...) do ...; ...; end`).
- If the last expression is a function call, and the function name is (or contains) `throw`
or `error`, no `return` is added. This is because it is already obvious that these calls
terminate the function and don't return any value.
Expand All @@ -449,14 +450,6 @@ Examples:
- :(generate_expr(args...))
+ return :(generate_expr(args...))
end
function g()
- open("/dev/random", "r") do f
- read(f, 8)
+ return open("/dev/random", "r") do f
+ return read(f, 8)
end
end
```
#### Potential changes
Expand Down
2 changes: 1 addition & 1 deletion src/runestone.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3584,7 +3584,7 @@ function explicit_return_block(ctx, node)
end

function explicit_return(ctx::Context, node::Node)
if !(!is_leaf(node) && kind(node) in KSet"function macro do")
if !(!is_leaf(node) && kind(node) in KSet"function macro")
return nothing
end
if !safe_to_insert_return(ctx, node)
Expand Down
20 changes: 10 additions & 10 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -487,9 +487,9 @@ end
@test format_string("try\nerror()\ncatch$(sp)e\nend") == "try\n error()\ncatch e\nend"
@test format_string("A$(sp)where$(sp){T}") == "A where {T}"
@test format_string("A$(sp)where$(sp){T}$(sp)where$(sp){S}") == "A where {T} where {S}"
@test format_string("f()$(sp)do$(sp)x\ny\nend") == "f() do x\n return y\nend"
@test format_string("f()$(sp)do\ny\nend") == "f() do\n return y\nend"
@test format_string("f()$(sp)do; y end") == "f() do;\n return y\nend"
@test format_string("f()$(sp)do$(sp)x\ny\nend") == "f() do x\n y\nend"
@test format_string("f()$(sp)do\ny\nend") == "f() do\n y\nend"
@test format_string("f()$(sp)do; y end") == "f() do;\n y\nend"
# After `where` (anywhere else?) a newline can be used instead of a space
@test format_string("A$(sp)where$(sp)\n{A}") == "A where\n{A}"
end
Expand Down Expand Up @@ -647,8 +647,8 @@ end
"try\n$(sp)x\n$(sp)catch err\n$(sp)y\n$(sp)else\n$(sp)z\n$(sp)finally\n$(sp)z\n$(sp)end"
) == "try\n x\ncatch err\n y\nelse\n z\nfinally\n z\nend"
# do-end
@test format_string("open() do\n$(sp)a\n$(sp)end") == "open() do\n return a\nend"
@test format_string("open() do io\n$(sp)a\n$(sp)end") == "open() do io\n return a\nend"
@test format_string("open() do\n$(sp)a\n$(sp)end") == "open() do\n a\nend"
@test format_string("open() do io\n$(sp)a\n$(sp)end") == "open() do io\n a\nend"
# module-end, baremodule-end
for b in ("", "bare")
# Just a module
Expand Down Expand Up @@ -1082,11 +1082,11 @@ end
@test format_string("try$(d)x$(d)catch err$(d)y$(d)else$(d)z$(d)finally$(d)z$(d)end") ==
"try\n x\ncatch err\n y\nelse\n z\nfinally\n z\nend"
# do-end
@test format_string("open() do\na$(d)end") == "open() do\n return a\nend"
@test format_string("open() do\na$(d)end") == "open() do\n a\nend"
@test format_string("open() do\nend") == "open() do\nend"
@test_broken format_string("open() do;a$(d)end") == "open() do\n a\nend"
@test_broken format_string("open() do ;a$(d)end") == "open() do\n a\nend"
@test format_string("open() do io$(d)a end") == "open() do io\n return a\nend"
@test format_string("open() do io$(d)a end") == "open() do io\n a\nend"
# let-end
@test format_string("let a = 1\nx$(d)end") == "let a = 1\n x\nend"
@test format_string("let\nx$(d)end") == "let\n x\nend"
Expand Down Expand Up @@ -1216,7 +1216,7 @@ end
"begin", "quote", "for i in I", "let", "let x = 1", "while cond",
"if cond", "macro f()", "function f()", "f() do", "f() do x",
)
rx = prefix in ("function f()", "macro f()", "f() do", "f() do x") ? " return x\n" : ""
rx = prefix in ("function f()", "macro f()") ? " return x\n" : ""
@test format_string("$(prefix)\n$(body)$(rx)\nend") == "$prefix\n$(bodyfmt)$(rx)\nend"
end
@test format_string(
Expand Down Expand Up @@ -1255,7 +1255,7 @@ end
end

@testset "explicit return" begin
for f in ("function f()", "function ()", "f() do", "macro m()")
for f in ("function f()", "function ()", "macro m()")
# Simple cases just prepend `return`
for r in (
"x", "*", "x, y", "(x, y)", "f()", "[1, 2]", "Int[1, 2]", "[1 2]", "Int[1 2]",
Expand All @@ -1265,7 +1265,7 @@ end
"a.b", "a.b.c", "x -> x^2", "[x for x in X]", "Int[x for x in X]",
"A{T} where {T}", "(@m a, b)", "A{T}",
"r\"foo\"", "r\"foo\"m", "`foo`", "```foo```", "r`foo`",
"f() do\n return x\n end", "f() do x\n return x\n end",
"f() do\n x\n end", "f() do x\n x\n end",
"function f()\n return x\n end",
"function ()\n return x\n end",
"quote\n x\n end", "begin\n x\n end",
Expand Down

0 comments on commit 65f4cc3

Please sign in to comment.