Skip to content

Commit

Permalink
Added @SoftScope macro for ease of use (#1)
Browse files Browse the repository at this point in the history
* Added @SoftScope macro for ease of use

* Fix macro escaping

* Added tests and macro for v0.6

* need test with a variable not already defined
  • Loading branch information
dawbarton authored and stevengj committed Sep 3, 2018
1 parent 30e1176 commit da50d45
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 6 deletions.
18 changes: 15 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ However, for *interactive* use, especially for new users, the necessity of the `

## Usage

The `SoftGlobalScope` module exports two functions `softscope` and `softscope_include_string`:
The `SoftGlobalScope` module exports two functions `softscope` and `softscope_include_string`, and a macro `@softscope`:

You can transform the expression using `softscope(module, expression)` to automatically insert the necessary `global` keyword. For example, assuming that the module `Main` has a global variable `s` (as above), you can do:
```jl
Expand All @@ -77,8 +77,20 @@ julia> softscope(Main, :(for i = 1:10
global s += i
end)
```
You can then execute the statement with `eval`. Alternatively, you can execute an entire sequence of statements
using "soft" global scoping rules via `softscope_include_string(module, string, filename="string")`:
You can then execute the statement with `eval`. Alternatively, you can decorate the expression with the `@softscope` macro:
```jl
julia> s = 0;

julia> @softscope for i = 1:10
s += i
end

julia> s
55
```
This macro should only be used in the global scope (e.g., via the REPL); using this macro within a function is likely to lead to unintended consequences.

You can execute an entire sequence of statements using "soft" global scoping rules via `softscope_include_string(module, string, filename="string")`:
```jl
julia> softscope_include_string(Main, """
s = 0
Expand Down
48 changes: 45 additions & 3 deletions src/SoftGlobalScope.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,23 @@ julia> softscope(Main, :(for i = 1:10
global s += i
end)
```
You can then execute the statement with `eval`. Alternatively, you can execute an entire sequence of statements
using "soft" global scoping rules via `softscope_include_string`:
You can then execute the statement with `eval`. Alternatively, you can decorate
the expression with the `@softscope` macro:
```jl
julia> s = 0;
julia> @softscope for i = 1:10
s += i
end
julia> s
55
```
This macro should only be used in the global scope (e.g., via the REPL); using
this macro within a function is likely to lead to unintended consequences.
You can execute an entire sequence of statements using "soft" global scoping
rules via `softscope_include_string`:
```jl
julia> softscope_include_string(Main, \"\"\"
s = 0
Expand All @@ -44,7 +59,7 @@ On Julia 0.6, `softscope` is the identity and `softscope_include_string` is equi
`include_string`, since the `global` keyword is not needed there.
"""
module SoftGlobalScope
export softscope, softscope_include_string
export softscope, softscope_include_string, @softscope

if VERSION < v"0.7.0-DEV.2308" # before julia#19324 we don't need to change the ast
softscope(m::Module, ast) = ast
Expand Down Expand Up @@ -170,6 +185,33 @@ scoping rules for the global variables defined in `m`, returning the new express
"""
softscope

if VERSION < v"0.7.0-DEV.481" # the version that __module__ was introduced
macro softscope(ast)
esc(softscope(current_module(), ast))
end
else
macro softscope(ast)
esc(softscope(__module__, ast))
end
end

"""
@softscope(expr)
Apply "soft" scoping rules to the argument of the macro. For example
```jl
julia> s = 0;
julia> @softscope for i = 1:10
s += i
end
julia> s
55
```
"""
:(@softscope)

"""
softscope_include_string(m::Module, code::AbstractString, filename::AbstractString="string")
Expand Down
6 changes: 6 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,9 @@ end
@test e == LoadError("bar", 3, ErrorException("syntax: \"++\" is not a unary operator"))
end
end

@testset "softscope_macro" begin
Core.eval(TestMod, :(global a = 0 ; using SoftGlobalScope))
@test Core.eval(TestMod, :(@softscope (for i=1:10; a += 1; end; a))) == 10
@test Core.eval(TestMod, :(@softscope (amacro=0; for i=1:10; amacro += i; end; amacro))) == 55
end

0 comments on commit da50d45

Please sign in to comment.