File tree Expand file tree Collapse file tree 4 files changed +93
-0
lines changed Expand file tree Collapse file tree 4 files changed +93
-0
lines changed Original file line number Diff line number Diff line change @@ -5,6 +5,8 @@ New language features
5
5
---------------------
6
6
7
7
* An * exception stack* is maintained on each task to make exception handling more robust and enable root cause analysis using ` catch_stack ` ([ #28878 ] ).
8
+ * The experimental macro ` Base.@locals ` returns a dictionary of current local variable names
9
+ and values ([ #29733 ] ).
8
10
9
11
Language changes
10
12
----------------
Original file line number Diff line number Diff line change @@ -250,6 +250,42 @@ macro isdefined(s::Symbol)
250
250
return Expr (:isdefined , esc (s))
251
251
end
252
252
253
+ """
254
+ @locals()
255
+
256
+ Construct a dictionary of the names (as symbols) and values of all local
257
+ variables defined as of the call site.
258
+
259
+ # Examples
260
+ ```jldoctest
261
+ julia> let x = 1, y = 2
262
+ Base.@locals
263
+ end
264
+ Dict{Symbol,Any} with 2 entries:
265
+ :y => 2
266
+ :x => 1
267
+
268
+ julia> function f(x)
269
+ local y
270
+ show(Base.@locals); println()
271
+ for i = 1:1
272
+ show(Base.@locals); println()
273
+ end
274
+ y = 2
275
+ show(Base.@locals); println()
276
+ nothing
277
+ end;
278
+
279
+ julia> f(42)
280
+ Dict{Symbol,Any}(:x=>42)
281
+ Dict{Symbol,Any}(:i=>1,:x=>42)
282
+ Dict{Symbol,Any}(:y=>2,:x=>42)
283
+ ```
284
+ """
285
+ macro locals ()
286
+ return Expr (:locals )
287
+ end
288
+
253
289
"""
254
290
objectid(x)
255
291
Original file line number Diff line number Diff line change 2442
2442
(if (not (memq (cadr e) env))
2443
2443
(error "no outer local variable declaration exists for \"for outer\""))
2444
2444
'(null))
2445
+ ((eq? (car e) 'locals)
2446
+ (let* ((names (filter (lambda (v)
2447
+ (and (not (gensym? v))
2448
+ (not (length= (string-split (string v) "#") 2))
2449
+ (let ((r (assq v renames)))
2450
+ (or (atom? r)
2451
+ (let ((mapping (cdr r)))
2452
+ (not (and (pair? mapping)
2453
+ (eq? (car mapping) 'outerref))))))))
2454
+ env))
2455
+ (names (delete-duplicates
2456
+ (filter (lambda (v) (not (eq? v '||)))
2457
+ (map unmangled-name names))))
2458
+ (d (make-ssavalue)))
2459
+ `(block (= ,d (call (call (core apply_type) (top Dict) (core Symbol) (core Any))))
2460
+ ,@(map (lambda (v)
2461
+ (let ((var (resolve-scopes- v env implicitglobals lam renames newlam sp)))
2462
+ `(if (isdefined ,var)
2463
+ (call (top setindex!) ,d ,var (quote ,v)))))
2464
+ names)
2465
+ ,d)))
2445
2466
((eq? (car e) 'lambda)
2446
2467
(let* ((lv (lam: vars e))
2447
2468
(env (append lv env))
2494
2515
(new-renames (append (map cons need-rename renamed) ;; map from definition name -> gensym name
2495
2516
(map cons need-rename-def renamed-def)
2496
2517
(map (lambda (g) (cons g `(outerref ,g))) new-iglo)
2518
+ (map (lambda (g) (cons g `(outerref ,g))) glob)
2497
2519
(filter (lambda (ren) ;; old renames list, with anything in vars removed
2498
2520
(let ((var (car ren)))
2499
2521
(not (or (memq var all-vars) ;; remove anything new
Original file line number Diff line number Diff line change @@ -813,3 +813,36 @@ f20872(::Val, ::Val) = false
813
813
module M29962 end
814
814
# make sure checking if a binding is deprecated does not resolve it
815
815
@test ! Base. isdeprecated (M29962, :sin ) && ! Base. isbindingresolved (M29962, :sin )
816
+
817
+ # @locals
818
+ using Base: @locals
819
+ let
820
+ local x, y
821
+ global z
822
+ @test isempty (keys (@locals ))
823
+ x = 1
824
+ @test @locals () == Dict {Symbol,Any} (:x => 1 )
825
+ y = " "
826
+ @test @locals () == Dict {Symbol,Any} (:x => 1 ,:y => " " )
827
+ for i = 8 : 8
828
+ @test @locals () == Dict {Symbol,Any} (:x => 1 ,:y => " " ,:i => 8 )
829
+ end
830
+ for i = 42 : 42
831
+ local x
832
+ @test @locals () == Dict {Symbol,Any} (:y => " " ,:i => 42 )
833
+ end
834
+ @test @locals () == Dict {Symbol,Any} (:x => 1 ,:y => " " )
835
+ x = (y,)
836
+ @test @locals () == Dict {Symbol,Any} (:x => (" " ,),:y => " " )
837
+ end
838
+
839
+ function _test_at_locals1 (:: Any , :: Any )
840
+ x = 1
841
+ @test @locals () == Dict {Symbol,Any} (:x => 1 )
842
+ end
843
+ _test_at_locals1 (1 ,1 )
844
+ function _test_at_locals2 (a:: Any , :: Any )
845
+ x = 2
846
+ @test @locals () == Dict {Symbol,Any} (:x => 2 ,:a => a)
847
+ end
848
+ _test_at_locals2 (1 ,1 )
You can’t perform that action at this time.
0 commit comments