-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6f7801a
commit 0661d0a
Showing
5 changed files
with
169 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Manifest.toml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Public.jl | ||
|
||
## Example usage | ||
|
||
```julia | ||
module HelloWorld | ||
|
||
using Public: @public | ||
|
||
@public f | ||
|
||
function f() | ||
return "hello" | ||
end | ||
|
||
function g() | ||
return "world" | ||
end | ||
|
||
end # module | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
module Public | ||
|
||
# Based on Compat.jl | ||
# License: MIT | ||
# https://github.com/JuliaLang/Compat.jl | ||
# https://github.com/JuliaLang/Compat.jl/blob/master/src/compatmacro.jl | ||
# https://github.com/JuliaLang/Compat.jl/blob/a62d95906f3c16c9fa0fe8369a6613dcfd2a4659/src/compatmacro.jl | ||
|
||
# https://github.com/JuliaLang/julia/pull/50105 | ||
@static if Base.VERSION >= v"1.11.0-DEV.469" | ||
macro public(symbols_expr::Union{Symbol, Expr}) | ||
symbols = _get_symbols(symbols_expr) | ||
return esc(Expr(:public, symbols...)) | ||
end | ||
else | ||
macro public(symbols_expr::Union{Symbol, Expr}) | ||
return nothing | ||
end | ||
end | ||
|
||
_get_symbols(sym::Symbol) = [sym] | ||
|
||
function _get_symbols(expr::Expr) | ||
# `expr` must either be a "valid macro expression" or a tuple expression. | ||
|
||
# If `expr` is a "valid macro expression", then we simply return it: | ||
if _is_valid_macro_expr(expr::Expr) | ||
return [expr.args[1]] | ||
end | ||
|
||
# If `expr` is not a "valid macro expression", then we check to make sure | ||
# that it is a tuple expression: | ||
if expr.head != :tuple | ||
msg = """ | ||
Invalid expression head `$(expr.head)` in expression `$(expr)`. | ||
Try `@public foo, bar, @hello, @world` | ||
""" | ||
throw(ArgumentError(msg)) | ||
end | ||
|
||
# Now that we know that `expr` is a tuple expression, we iterate over | ||
# each element of the tuple | ||
num_symbols = length(expr.args) | ||
symbols = Vector{Symbol}(undef, num_symbols) | ||
for (i, arg) in enumerate(expr.args) | ||
end | ||
return symbols | ||
end | ||
|
||
# Return true if and only if `expr` is a valid macro call with no arguments. | ||
# | ||
# Example of "good" input: `@foo` | ||
function _is_valid_macro_expr(expr::Expr) | ||
# `expr` must be a `:macrocall` expression: | ||
Meta.isexpr(expr, :macrocall) || return false | ||
|
||
# `expr` must have exactly two arguments: | ||
(length(expr.args) == 2) || return false | ||
|
||
# The first argument must be a Symbol: | ||
(expr.args[1] isa Symbol) || return false | ||
|
||
# The first argument must begin with `@` | ||
arg1_str = string(expr.args[1]) | ||
(arg1_str[1] == '@') || return false | ||
|
||
# The first argument must have length >= 2 | ||
# (because otherwise the first argument would just be `@`, which doesn't | ||
# make sense) | ||
(length(arg1_str) >= 2) || return false | ||
|
||
# The second argument must be a `LineNumberNode` | ||
(expr.args[2] isa LineNumberNode) || return false | ||
|
||
return true | ||
end | ||
|
||
# TODO: figure out if we actually want to `export`, | ||
# or if we just want to mark as public. | ||
export @public | ||
|
||
end # module Public |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import Public | ||
import Test | ||
|
||
using Test: @testset | ||
using Test: @test | ||
|
||
@testset "Public.jl package" begin | ||
@testset "_is_valid_macro_expr" begin | ||
good_exprs = [ | ||
:(@hello), | ||
Meta.parse("@hello"), | ||
] | ||
bad_exprs = [ | ||
Meta.parse("@foo bar"), | ||
Meta.parse("@foo(bar)"), | ||
] | ||
for expr in good_exprs | ||
@testset let context = (; expr) | ||
@test Public._is_valid_macro_expr(expr) | ||
end | ||
|
||
end | ||
for expr in bad_exprs | ||
@testset let context = (; expr) | ||
@test !Public._is_valid_macro_expr(expr) | ||
end | ||
end | ||
end | ||
end | ||
|
||
module TestModule1 | ||
|
||
using Public: @public | ||
|
||
export f | ||
@public g | ||
|
||
function f end | ||
function g end | ||
function h end | ||
|
||
end # module TestModule1 | ||
|
||
@test Base.isexported(TestModule1, :f) | ||
@test !Base.isexported(TestModule1, :g) | ||
@test !Base.isexported(TestModule1, :h) | ||
|
||
# @test Base.ispublic(TestModule1, :f) | ||
# @test !Base.ispublic(TestModule1, :h) | ||
|
||
@static if Base.VERSION >= v"1.11.0-DEV.469" | ||
# @test Base.ispublic(TestModule1, :g) | ||
else | ||
# @test !Base.ispublic(TestModule1, :g) | ||
end |