Skip to content

Commit bf0874f

Browse files
committed
Improved @api
1 parent 37ffe9d commit bf0874f

File tree

3 files changed

+77
-36
lines changed

3 files changed

+77
-36
lines changed
File renamed without changes.

src/ModuleInterfaceTools.jl

Lines changed: 76 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ const debug = Ref(false)
1515
const V6_COMPAT = VERSION < v"0.7.0-DEV"
1616
const BIG_ENDIAN = (ENDIAN_BOM == 0x01020304)
1717

18+
@static if !V6_COMPAT
19+
using Pkg
20+
export Pkg
21+
end
22+
1823
Base.parse(::Type{Expr}, args...; kwargs...) =
1924
Meta.parse(args...; kwargs...)
2025

@@ -70,29 +75,39 @@ end
7075
"""Get current module"""
7176
cur_mod() = ccall(:jl_get_current_module, Ref{Module}, ())
7277

73-
m_eval(mod, expr) = Core.eval(mod, expr)
78+
function m_eval(mod, expr)
79+
try
80+
Core.eval(mod, expr)
81+
catch ex
82+
println("m_eval($mod, $expr)");
83+
rethrow(ex)
84+
end
85+
end
7486
m_eval(expr) = m_eval(cur_mod(), expr)
7587

7688
"""
7789
@api <cmd> [<symbols>...]
7890
79-
* @api freeze # use at end of module, to "freeze" API
91+
* freeze # use at end of module to freeze API
8092
81-
* @api list <modules>... # list API(s) of given modules (or current if none given)
93+
* list <modules>... # list API(s) of given modules (or current if none given)
8294
83-
* @api use <modules>... # use, without importing (i.e. can't extend)
84-
* @api test <modules>... # using public and develop APIs, for testing purposes
85-
* @api extend <modules>... # for development, imports api & dev, use api & dev definitions
86-
* @api export <modules>... # export public definitions
95+
* use <modules>... # use, without importing (i.e. can't extend)
96+
* use! <modules>... # use, without importing (i.e. can't extend), "export"
97+
* test <modules>... # using public and develop APIs, for testing purposes
98+
* extend <modules>... # for development, imports api & dev, use api & dev definitions
99+
* extend! <modules>... # for development, imports api & dev, use api & dev definitions, "export"
100+
* export <modules>... # export public definitions
87101
88-
* @api base <names...> # Add functions from Base that are part of the API
89-
* @api public! <names...> # Add other symbols that are part of the public API (structs, consts)
90-
* @api develop! <names...> # Add other symbols that are part of the development API
91-
* @api public <names...> # Add functions that are part of the public API
92-
* @api develop <names...> # Add functions that are part of the development API
93-
* @api modules <names...> # Add submodule names that are part of the API
102+
* base <names...> # Add functions from Base that are part of the API (extendible)
103+
* base! <names...> # Add functions from Base or define them if not in Base
104+
* public <names...> # Add other symbols that are part of the public API (structs, consts)
105+
* public! <names...> # Add functions that are part of the public API (extendible)
106+
* develop <names...> # Add other symbols that are part of the development API
107+
* develop! <names...> # Add functions that are part of the development API (extendible)
108+
* modules <names...> # Add submodule names that are part of the API
94109
95-
* @api def <name> <expr> # Same as the @def macro, creates a macro with the given name
110+
* def <name> <expr> # Same as the @def macro, creates a macro with the given name
96111
97112
"""
98113
macro api(cmd::Symbol)
@@ -113,7 +128,7 @@ function _api_freeze(mod::Module)
113128
nothing
114129
end
115130

116-
const _cmduse = (:use, :test, :extend, :export, :list)
131+
const _cmduse = (:use, :use!, :test, :extend, :extend!, :export, :list)
117132
const _cmdadd =
118133
(:modules, :public, :develop, :public!, :develop!, :base, :base!)
119134

@@ -138,6 +153,20 @@ function _add_def!(curmod, grp, exp)
138153
end
139154
end
140155

156+
function push_args!(symbols, lst, grp)
157+
for ex in lst
158+
if isa(ex, Expr) && ex.head == :tuple
159+
push_args!(symbols, ex.args)
160+
elseif isa(ex, Symbol)
161+
push!(symbols, ex)
162+
elseif isa(ex, AbstractString)
163+
push!(symbols, Symbol(ex))
164+
else
165+
error("@api $grp: syntax error $ex")
166+
end
167+
end
168+
end
169+
141170
"""Add symbols"""
142171
function _add_symbols(curmod, grp, exprs)
143172
if debug[]
@@ -161,7 +190,7 @@ function _add_symbols(curmod, grp, exprs)
161190
symbols = SymSet()
162191
for ex in exprs
163192
if isa(ex, Expr) && ex.head == :tuple
164-
push!(symbols, ex.args...)
193+
push_args!(symbols, ex.args, grp)
165194
elseif isa(ex, Symbol)
166195
push!(symbols, ex)
167196
elseif isa(ex, AbstractString)
@@ -183,34 +212,32 @@ function _add_symbols(curmod, grp, exprs)
183212
nothing
184213
end
185214

186-
function _api_extend(curmod, modules)
187-
imp = :import
188-
use = :using
189-
215+
function _api_extend(curmod, modules, cpy::Bool)
190216
for nam in modules
191217
mod = m_eval(curmod, nam)
192218
if isdefined(mod, :__api__)
193219
api = m_eval(mod, :__api__)
194-
_do_list(curmod, imp, api, :Base, :base)
195-
_do_list(curmod, imp, api, nam, :public!)
196-
_do_list(curmod, imp, api, nam, :develop!)
197-
_do_list(curmod, use, api, nam, :public)
198-
_do_list(curmod, use, api, nam, :develop)
220+
_do_list(curmod, cpy, :import, :Base, :base, api)
221+
_do_list(curmod, cpy, :import, nam, :public!, api)
222+
_do_list(curmod, cpy, :import, nam, :develop!, api)
223+
_do_list(curmod, cpy, :using, nam, :public, api)
224+
_do_list(curmod, cpy, :using, nam, :develop, api)
199225
else
200-
println("API not found for module: $mod")
226+
_do_list(curmod, cpy, :import, nam, :public!, names(mod))
201227
end
202228
end
203-
204229
nothing
205230
end
206231

207-
function _api_use(curmod, modules)
232+
function _api_use(curmod, modules, cpy::Bool)
208233
for nam in modules
209234
mod = m_eval(curmod, nam)
210235
if isdefined(mod, :__api__)
211236
api = m_eval(mod, :__api__)
212-
_do_list(curmod, :using, api, nam, :public)
213-
_do_list(curmod, :using, api, nam, :public!)
237+
_do_list(curmod, cpy, :using, nam, :public, api)
238+
_do_list(curmod, cpy, :using, nam, :public!, api)
239+
else
240+
_do_list(curmod, cpy, :using, nam, :public!, names(mod))
214241
end
215242
end
216243
nothing
@@ -248,8 +275,17 @@ function _api(curmod::Module, cmd::Symbol, exprs)
248275
modules = SymSet()
249276
for ex in exprs
250277
if isa(ex, Expr) && ex.head == :tuple
251-
push!(modules, ex.args...)
252-
for sym in ex.args ; m_eval(curmod, :(import $sym)) ; end
278+
# Some of these might not just be modules
279+
# might have module(symbols, !syms, sym => other), need to add support for that
280+
for sym in ex.args
281+
if isa(sym, Symbol)
282+
push!(modules, sym)
283+
m_eval(curmod, :(import $sym))
284+
else
285+
println("Not a symbol: $sym");
286+
dump(sym);
287+
end
288+
end
253289
elseif isa(ex, Symbol)
254290
push!(modules, ex)
255291
m_eval(curmod, :(import $ex))
@@ -272,13 +308,17 @@ function _api(curmod::Module, cmd::Symbol, exprs)
272308
# Be nice and set up standard Test
273309
cmd == :test && m_eval(curmod, V6_COMPAT ? :(using Base.Test) : :(using Test))
274310

275-
cmd == :use ? _api_use(curmod, modules) : _api_extend(curmod, modules)
311+
((cmd == :use || cmd == :use!)
312+
? _api_use(curmod, modules, cmd == :use!)
313+
: _api_extend(curmod, modules, cmd == :extend!))
276314
end
277315

278316
@static V6_COMPAT || (_dot_name(nam) = Expr(:., nam))
279317

280-
function _do_list(curmod, cmd, api, mod, grp)
281-
lst = getfield(api, grp)
318+
_do_list(curmod, cpy, cmd, mod, grp, api::API) =
319+
_do_list(curmod, cpy, cmd, mod, grp, getfield(api, grp))
320+
321+
function _do_list(curmod, cpy, cmd, mod, grp, lst)
282322
isempty(lst) && return
283323
@static if V6_COMPAT
284324
for nam in lst
@@ -297,6 +337,7 @@ function _do_list(curmod, cmd, api, mod, grp)
297337
println(sprint(showerror, ex, catch_backtrace()))
298338
end
299339
end
340+
cpy && for sym in lst; m_eval(curmod, :( push!(__tmp_api__.$grp, $(QuoteNode(sym)) ))); end
300341
end
301342

302343
macro api(cmd::Symbol, exprs...)

test/runtests.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
using ModuleInterfaceTools
55

6-
@static V6_COMPAT ? (using Base.Test) : (using Pkg, Test)
6+
@static V6_COMPAT ? (using Base.Test) : (using Test)
77

88
# Pick up APITest from the test directory
99
push!(LOAD_PATH, @__DIR__)

0 commit comments

Comments
 (0)