Skip to content
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

Added @softscope macro for ease of use #1

Merged
merged 6 commits into from
Sep 3, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
23 changes: 22 additions & 1 deletion src/SoftGlobalScope.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ julia> softscope_include_string(Main, \"\"\"
(This function works like `include_string`, returning the value of the last evaluated expression.)
"""
module SoftGlobalScope
export softscope, softscope_include_string
export softscope, softscope_include_string, @softscope

using Base.Meta: isexpr

Expand Down Expand Up @@ -68,6 +68,8 @@ function _softscope(ex::Expr, globals, insertglobal::Bool=false)
_softscope(ex.args[2], letglobals, true))
elseif isexpr(ex, :block) || isexpr(ex, :if)
return Expr(ex.head, _softscope.(ex.args, Ref(globals), insertglobal)...)
elseif isexpr(ex, :escape)
return Expr(ex.head, _softscope(ex.args[1], globals, true))
elseif insertglobal && ex.head in assignments && ex.args[1] in globals
return Expr(:global, Expr(ex.head, ex.args[1], _softscope(ex.args[2], globals, insertglobal)))
else
Expand All @@ -84,6 +86,25 @@ scoping rules for the global variables defined in `m`, returning the new express
"""
softscope(m::Module, ast) = _softscope(ast, Set(names(m, all=true)))

"""
@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
```
"""
macro softscope(ast)
softscope(__module__, esc(ast))
end

"""
softscope_include_string(m::Module, code::AbstractString, filename::AbstractString="string")

Expand Down