@@ -11,8 +11,12 @@ Licensed under MIT License, see LICENSE.md
1111module APITools
1212
1313const V6_COMPAT = VERSION < v" 0.7.0-DEV"
14+ const BIG_ENDIAN = (ENDIAN_BOM == 0x01020304 )
1415
15- export @api, @def
16+ Base. parse(:: Type{Expr} , args... ; kwargs... ) =
17+ Meta. parse(args... ; kwargs... )
18+
19+ export @api, @def, V6_COMPAT, BIG_ENDIAN
1620
1721macro def(name, definition)
1822 quote
@@ -75,29 +79,41 @@ const _cur_mod = V6_COMPAT ? :( current_module() ) : :( @__MODULE__ )
7579 * @api define_module <names...> # Add submodule names that are part of the API
7680"""
7781macro api(cmd:: Symbol )
78- if cmd == :init
79- quote
80- export @api, APITools
81- global __tmp_api__ = APITools. TMP_API()
82- global __tmp_chain__ = Vector{APITools. API}[]
83- end
84- elseif cmd == :freeze
85- esc(quote
86- const __api__ = APITools. API($ _cur_mod, __tmp_api__)
87- push!(__tmp_chain__, __api__)
88- const __chain__ = APITools. APIList(__tmp_chain__)
89- __tmp_chain__ = _tmp_api__ = nothing
90- end )
91- elseif cmd == :list
92- quote
93- show(__api__)
94- show(__tmp_chain__)
95- end
96- else
97- error(" @api unrecognized command: $cmd " )
82+ cmd == :init && return _api_init()
83+ cmd == :freeze && return _api_freeze()
84+ cmd == :list && return _api_list()
85+ error(" @api unrecognized command: $cmd " )
86+ end
87+
88+ function _api_display(mod)
89+ if isdefined(mod, :__api__)
90+ show(eval(mod, :__api__))
91+ show(eval(mod, :__chain__))
92+ end
93+ if isdefined(mod, :__tmp_api__)
94+ show(eval(mod, :__tmp_api__))
95+ show(eval(mod, :__tmp_chain__))
9896 end
97+ nothing
9998end
10099
100+ _api_init() =
101+ quote
102+ export @api, APITools
103+ global __tmp_api__ = APITools. TMP_API()
104+ global __tmp_chain__ = APITools. API[]
105+ end
106+
107+ _api_freeze() =
108+ esc(quote
109+ const __api__ = APITools. API($ _cur_mod, __tmp_api__)
110+ push!(__tmp_chain__, __api__)
111+ const __chain__ = APITools. APIList(__tmp_chain__)
112+ __tmp_chain__ = _tmp_api__ = nothing
113+ end )
114+
115+ _api_list(mod = _cur_mod) = :( _api_display($ mod) )
116+
101117const _cmduse = (:use, :test, :extend, :export)
102118const _cmdadd =
103119 (:define_module, :define_public, :define_develop, :public, :develop, :base, :maybe_public)
@@ -111,7 +127,7 @@ _add_def!(deflst, explst, sym) = (push!(deflst, sym); push!(explst, esc(:(functi
111127function _maybe_public(exprs)
112128 implst = Symbol[]
113129 deflst = Symbol[]
114- explst = Expr[]
130+ explst = isdefined(eval(_cur_mod), :__tmp_api__) ? Expr[] : Expr[_api_init() ]
115131 for ex in exprs
116132 if isa(ex, Expr) && ex. head == :tuple
117133 for sym in ex. args
@@ -124,13 +140,11 @@ function _maybe_public(exprs)
124140 error(" @api $grp : syntax error $ex " )
125141 end
126142 end
127- lst = _add_symbols(:base, implst)
128- isempty(deflst) && return lst
129- Expr(:toplevel, lst, explst... , esc(:( append!(__tmp_api__. public, $ deflst))))
143+ isempty(deflst) || push!(explst, esc(:( append!(__tmp_api__. public, $ deflst))))
144+ Expr(:toplevel, _add_symbols(:base, implst). .. , explst... )
130145end
131146
132147function _add_symbols(grp, exprs)
133- grp == :maybe_public && return _maybe_public(exprs)
134148 symbols = Symbol[]
135149 for ex in exprs
136150 if isa(ex, Expr) && ex. head == :tuple
@@ -141,16 +155,13 @@ function _add_symbols(grp, exprs)
141155 error(" @api $grp : syntax error $ex " )
142156 end
143157 end
158+ lst = isdefined(eval(_cur_mod), :__tmp_api__) ? Expr[] : Expr[_api_init()]
144159 if grp == :base
145160 syms = SymList(symbols)
146161 expr = " APITools._make_list($(QuoteNode(:import)) , $(QuoteNode(:Base)) , $syms )"
147- parsed = Meta. parse(expr)
148- Expr(:toplevel,
149- V6_COMPAT ? :(eval(current_module(), $ parsed)) : :(eval(@__MODULE__, $ parsed)),
150- esc(:( append!(__tmp_api__. base, $ symbols))))
151- else
152- esc(:( append!(__tmp_api__.$ grp, $ symbols) ))
162+ push!(lst, :(eval($ _cur_mod, $ (Meta. parse(expr)))))
153163 end
164+ Expr(:toplevel, lst... , esc(:( append!(__tmp_api__.$ grp, $ symbols) )))
154165end
155166
156167function _make_modules(exprs)
172183
173184macro api(cmd:: Symbol , exprs... )
174185 ind = _ff(_cmdadd, cmd)
175- ind == 0 || return _add_symbols(cmd, exprs)
186+ ind == 0 || return cmd == :maybe_public ? _maybe_public(exprs) : _add_symbols(cmd, exprs)
176187
177188 ind = _ff(_cmduse, cmd)
178189
@@ -182,6 +193,8 @@ macro api(cmd::Symbol, exprs...)
182193 return esc(Expr(:toplevel, lst... ,
183194 [:(eval(Expr( :export, $ mod. __api__.$ grp... )))
184195 for mod in modules, grp in (:define_module, :define_public, :public)]. .. ))
196+ cmd == :list &&
197+ return Expr(:toplevel, [:(eval(Expr(:call, :_api_display, $ mod))) for mod in modules]. .. )
185198
186199 for mod in modules
187200 push!(lst, _make_module_exprs(mod))
@@ -194,6 +207,10 @@ macro api(cmd::Symbol, exprs...)
194207 push!(lst, V6_COMPAT ? :(using Base. Test) : :(using Test))
195208 elseif cmd == :extend
196209 grplst = (:define_public, :define_develop)
210+ # should add unique modules to __tmp_chain__
211+ for mod in modules
212+ push!(lst, :(in($ mod. __api__, __tmp_chain__) || push!(__tmp_chain__, $ mod. __api__)))
213+ end
197214 for mod in modules, grp in (:base, :public, :develop)
198215 push!(lst, _make_exprs(:import, mod, grp))
199216 end
0 commit comments