@@ -5,6 +5,8 @@ using InteractiveUtils
55# Builtins not present in 1.10 (the lowest supported version)
66const RECENTLY_ADDED = Core. Builtin[
77 Core. current_scope,
8+ isdefinedglobal,
9+ Core. memorynew,
810 Core. memoryref_isassigned,
911 Core. memoryrefget,
1012 Core. memoryrefmodify!,
@@ -20,12 +22,38 @@ const RECENTLY_ADDED = Core.Builtin[
2022 setfieldonce!,
2123 setglobalonce!,
2224 swapglobal!,
25+ Core. _defaultctors,
26+ Core. _import,
27+ Core. _using,
28+ # Recently became builtins
29+ Base. invokelatest,
30+ Base. invoke_in_world,
2331]
2432# Builtins present from 1.10, not builtins (potentially still normal functions) anymore
2533const RECENTLY_REMOVED = GlobalRef .(Ref (Core), [
26- :arrayref , :arrayset , :arrayset , :const_arrayref , :memoryref , :set_binding_type!
34+ :arrayref , :arrayset , :arrayset , :const_arrayref , :memoryref , :set_binding_type! ,
35+ :_apply_pure , :_call_in_world , :_call_latest ,
2736])
2837const kwinvoke = Core. kwfunc (Core. invoke)
38+ const REQUIRES_WORLD = Core. Builtin[
39+ setglobal!,
40+ Core. get_binding_type,
41+ swapglobal!,
42+ modifyglobal!,
43+ replaceglobal!,
44+ setglobalonce!,
45+ ]
46+ const CALL_LATEST = """ args = getargs(interp, args, frame)
47+ if !expand
48+ return Some{Any}(Core._call_latest(args...))
49+ end
50+ new_expr = Expr(:call, args[1])
51+ popfirst!(args)
52+ for x in args
53+ push!(new_expr.args, QuoteNode(x))
54+ end
55+ return maybe_recurse_expanded_builtin(interp, frame, new_expr)
56+ """
2957
3058function scopedname (f)
3159 io = IOBuffer ()
@@ -35,7 +63,7 @@ function scopedname(f)
3563 tn = typeof (f). name
3664 Base. isexported (tn. module, Symbol (fstr)) && return fstr
3765 fsym = Symbol (fstr)
38- isdefined (tn. module, fsym) && return string (tn. module) * ' .' * fstr
66+ isdefinedglobal (tn. module, fsym) && return string (tn. module) * ' .' * fstr
3967 return " Base." * fstr
4068end
4169
@@ -49,13 +77,13 @@ function nargs(f, table, id)
4977 end
5078 # Specialize ~arrayref and arrayset~ memoryrefnew for small numbers of arguments
5179 # TODO : how about other memory intrinsics?
52- if (@static isdefined (Core, :memoryrefnew ) ? f == Core. memoryrefnew : f == Core. memoryref)
80+ if (@static isdefinedglobal (Core, :memoryrefnew ) ? f == Core. memoryrefnew : f == Core. memoryref)
5381 maxarg = 5
5482 end
5583 return minarg, maxarg
5684end
5785
58- function generate_fcall_nargs (fname, minarg, maxarg)
86+ function generate_fcall_nargs (fname, minarg, maxarg; requires_world :: Bool = false )
5987 # Generate a separate call for each number of arguments
6088 maxarg < typemax (Int) || error (" call this only for constrained number of arguments" )
6189 annotation = fname == " fieldtype" ? " ::Type" : " "
@@ -64,31 +92,41 @@ function generate_fcall_nargs(fname, minarg, maxarg)
6492 wrapper *= " $nargs \n "
6593 argcall = " "
6694 for i = 1 : nargs
67- argcall *= " @ lookup(frame, args[$(i+ 1 ) ])"
95+ argcall *= " lookup(interp, frame, args[$(i+ 1 ) ])"
6896 if i < nargs
6997 argcall *= " , "
7098 end
7199 end
72- wrapper *= " return Some{Any}($fname ($argcall )$annotation )"
100+ wrapper *= requires_world ? " return Some{Any}(Base.invoke_in_world(frame.world, $fname , $argcall )$annotation )" :
101+ " return Some{Any}($fname ($argcall )$annotation )"
73102 if nargs < maxarg
74103 wrapper *= " \n elseif nargs == "
75104 end
76105 end
77106 wrapper *= " \n else"
78- wrapper *= " \n return Some{Any}($fname (getargs(args, frame)...)$annotation )" # to throw the correct error
107+ # To throw the correct error
108+ if requires_world
109+ wrapper *= " \n return Some{Any}(Base.invoke_in_world(frame.world, $fname , getargs(interp, args, frame)...)$annotation )"
110+ else
111+ wrapper *= " \n return Some{Any}($fname (getargs(interp, args, frame)...)$annotation )"
112+ end
79113 wrapper *= " \n end"
80114 return wrapper
81115end
82116
83117function generate_fcall (f, table, id)
84118 minarg, maxarg = nargs (f, table, id)
85119 fname = scopedname (f)
120+ requires_world = f ∈ REQUIRES_WORLD
86121 if maxarg < typemax (Int)
87- return generate_fcall_nargs (fname, minarg, maxarg)
122+ return generate_fcall_nargs (fname, minarg, maxarg; requires_world )
88123 end
89124 # A built-in with arbitrary or unknown number of arguments.
90125 # This will (unfortunately) use dynamic dispatch.
91- return " return Some{Any}($fname (getargs(args, frame)...))"
126+ if requires_world
127+ return " return Some{Any}(Base.invoke_in_world(frame.world, $fname , getargs(interp, args, frame)...))"
128+ end
129+ return " return Some{Any}($fname (getargs(interp, args, frame)...))"
92130end
93131
94132# `io` is for the generated source file
@@ -104,42 +142,42 @@ function generate_builtins(io::IO)
104142"""
105143# This file is generated by `generate_builtins.jl`. Do not edit by hand.
106144
107- function getargs(args, frame)
145+ function getargs(interp::Interpreter, args::Vector{Any} , frame::Frame )
108146 nargs = length(args)-1 # skip f
109147 callargs = resize!(frame.framedata.callargs, nargs)
110148 for i = 1:nargs
111- callargs[i] = @ lookup(frame, args[i+1])
149+ callargs[i] = lookup(interp, frame, args[i+1])
112150 end
113151 return callargs
114152end
115153
116154const kwinvoke = Core.kwfunc(Core.invoke)
117155
118- function maybe_recurse_expanded_builtin(frame, new_expr)
156+ function maybe_recurse_expanded_builtin(interp::Interpreter, frame::Frame , new_expr::Expr )
119157 f = new_expr.args[1]
120158 if isa(f, Core.Builtin) || isa(f, Core.IntrinsicFunction)
121- return maybe_evaluate_builtin(frame, new_expr, true)
159+ return maybe_evaluate_builtin(interp, frame, new_expr, true)
122160 else
123161 return new_expr
124162 end
125163end
126164
127165\"\"\"
128- ret = maybe_evaluate_builtin(frame, call_expr, expand::Bool)
166+ ret = maybe_evaluate_builtin(interp::Interpreter, frame::Frame , call_expr::Expr , expand::Bool)
129167
130168If `call_expr` is to a builtin function, evaluate it, returning the result inside a `Some` wrapper.
131169Otherwise, return `call_expr`.
132170
133171If `expand` is true, `Core._apply_iterate` calls will be resolved as a call to the applied function.
134172\"\"\"
135- function maybe_evaluate_builtin(frame, call_expr, expand::Bool)
173+ function maybe_evaluate_builtin(interp::Interpreter, frame::Frame , call_expr::Expr , expand::Bool)
136174 args = call_expr.args
137175 nargs = length(args) - 1
138176 fex = args[1]
139177 if isa(fex, QuoteNode)
140178 f = fex.value
141179 else
142- f = @ lookup(frame, fex)
180+ f = lookup(interp, frame, fex)
143181 end
144182
145183 if f isa Core.OpaqueClosure
@@ -172,15 +210,15 @@ function maybe_evaluate_builtin(frame, call_expr, expand::Bool)
172210 print (io,
173211"""
174212 $head f === tuple
175- return Some{Any}(ntupleany(i->@ lookup(frame, args[i+1]), length(args)-1))
213+ return Some{Any}(ntupleany(i::Int-> lookup(interp, frame, args[i+1]), length(args)-1))
176214""" )
177215 continue
178216 elseif f === Core. _apply_iterate
179217 # Resolve varargs calls
180218 print (io,
181219"""
182220 $head f === Core._apply_iterate
183- argswrapped = getargs(args, frame)
221+ argswrapped = getargs(interp, args, frame)
184222 if !expand
185223 return Some{Any}(Core._apply_iterate(argswrapped...))
186224 end
@@ -193,7 +231,7 @@ function maybe_evaluate_builtin(frame, call_expr, expand::Bool)
193231 for x in argsflat
194232 push!(new_expr.args, QuoteNode(x))
195233 end
196- return maybe_recurse_expanded_builtin(frame, new_expr)
234+ return maybe_recurse_expanded_builtin(interp, frame, new_expr)
197235""" )
198236 continue
199237 elseif f === Core. invoke
@@ -202,42 +240,26 @@ function maybe_evaluate_builtin(frame, call_expr, expand::Bool)
202240"""
203241 $head f === $fstr
204242 if !expand
205- argswrapped = getargs(args, frame)
243+ argswrapped = getargs(interp, args, frame)
206244 return Some{Any}($fstr (argswrapped...))
207245 end
208246 # This uses the original arguments to avoid looking them up twice
209247 # See #442
210248 return Expr(:call, invoke, args[2:end]...)
211- """ )
212- continue
213- elseif f === Core. _call_latest
214- print (io,
215- """
216- elseif f === Core._call_latest
217- args = getargs(args, frame)
218- if !expand
219- return Some{Any}(Core._call_latest(args...))
220- end
221- new_expr = Expr(:call, args[1])
222- popfirst!(args)
223- for x in args
224- push!(new_expr.args, QuoteNode(x))
225- end
226- return maybe_recurse_expanded_builtin(frame, new_expr)
227249""" )
228250 continue
229251 elseif f === Core. current_scope
230252 print (io,
231253"""
232- elseif @static isdefined (Core, :current_scope) && f === Core.current_scope
254+ elseif @static isdefinedglobal (Core, :current_scope) && f === Core.current_scope
233255 if nargs == 0
234256 currscope = Core.current_scope()
235257 for scope in frame.framedata.current_scopes
236258 currscope = Scope(currscope, scope.values...)
237259 end
238260 return Some{Any}(currscope)
239261 else
240- return Some{Any}(Core.current_scope(getargs(args, frame)...))
262+ return Some{Any}(Core.current_scope(getargs(interp, args, frame)...))
241263 end
242264""" )
243265 continue
@@ -246,9 +268,12 @@ function maybe_evaluate_builtin(frame, call_expr, expand::Bool)
246268 id = findfirst (isequal (f), Core. Compiler. T_FFUNC_KEY)
247269 fcall = generate_fcall (f, Core. Compiler. T_FFUNC_VAL, id)
248270 if f in RECENTLY_ADDED
271+ if f === Core. invokelatest
272+ fcall = replace (CALL_LATEST, " _call_latest" => " invokelatest" )
273+ end
249274 print (io,
250275"""
251- $head @static isdefined ($(ft. name. module) , $(repr (nameof (f))) ) && f === $fname
276+ $head @static isdefinedglobal ($(ft. name. module) , $(repr (nameof (f))) ) && f === $fname
252277 $fcall
253278""" )
254279 else
@@ -270,13 +295,13 @@ function maybe_evaluate_builtin(frame, call_expr, expand::Bool)
270295 if nargs == 1
271296 call_expr = copy(call_expr)
272297 args2 = args[2]
273- call_expr.args[2] = isa(args2, QuoteNode) ? args2 : @ lookup(frame, args2)
298+ call_expr.args[2] = isa(args2, QuoteNode) ? args2 : lookup(interp, frame, args2)
274299 return Some{Any}(Core.eval(moduleof(frame), call_expr))
275300 elseif nargs == 2
276301 call_expr = copy(call_expr)
277302 args2 = args[2]
278- call_expr.args[2] = isa(args2, QuoteNode) ? args2 : @ lookup(frame, args2)
279- call_expr.args[3] = @ lookup(frame, args[3])
303+ call_expr.args[2] = isa(args2, QuoteNode) ? args2 : lookup(interp, frame, args2)
304+ call_expr.args[3] = lookup(interp, frame, args[3])
280305 return Some{Any}(Core.eval(moduleof(frame), call_expr))
281306 end
282307""" )
@@ -292,13 +317,18 @@ function maybe_evaluate_builtin(frame, call_expr, expand::Bool)
292317 elseif name === :set_binding_type!
293318 minarg = 2
294319 maxarg = 3
320+ elseif name in (:_apply_pure , :_call_in_world , :_call_latest )
321+ minarg = 0
322+ maxarg = typemax (Int)
295323 end
296324 _scopedname = " $mod .$name "
297- fcall = generate_fcall_nargs (_scopedname, minarg, maxarg)
325+ fcall = name === :_call_latest ? CALL_LATEST :
326+ maxarg < typemax (Int) ? generate_fcall_nargs (_scopedname, minarg, maxarg) :
327+ " return Some{Any}($_scopedname (getargs(interp, args, frame)...))"
298328 rname = repr (name)
299329 print (io,
300330"""
301- elseif @static (isdefined ($mod , $rname ) && $_scopedname isa Core.Builtin) && f === $_scopedname
331+ elseif @static (isdefinedglobal ($mod , $rname ) && $_scopedname isa Core.Builtin) && f === $_scopedname
302332 $fcall
303333""" )
304334 end
@@ -307,7 +337,7 @@ function maybe_evaluate_builtin(frame, call_expr, expand::Bool)
307337 minmin, maxmax = typemax (Int), 0
308338 for fsym in names (Core. Intrinsics)
309339 fsym === :Intrinsics && continue
310- isdefined (Base, fsym) || continue
340+ isdefinedglobal (Base, fsym) || continue
311341 f = getfield (Base, fsym)
312342 id = reinterpret (Int32, f) + 1
313343 minarg, maxarg = nargs (f, Core. Compiler. T_IFUNC, id)
@@ -333,7 +363,7 @@ function maybe_evaluate_builtin(frame, call_expr, expand::Bool)
333363 print (io,
334364"""
335365 if isa(f, Core.IntrinsicFunction)
336- cargs = getargs(args, frame)
366+ cargs = getargs(interp, args, frame)
337367 if f === Core.Intrinsics.have_fma && length(cargs) == 1
338368 cargs1 = cargs[1]
339369 if cargs1 == Float64
@@ -364,7 +394,7 @@ function maybe_evaluate_builtin(frame, call_expr, expand::Bool)
364394"""
365395 end
366396 if isa(f, typeof(kwinvoke))
367- return Some{Any}(kwinvoke(getargs(args, frame)...))
397+ return Some{Any}(kwinvoke(getargs(interp, args, frame)...))
368398 end
369399 return call_expr
370400end
0 commit comments