|
1 | 1 | using LoweredCodeUtils
|
2 | 2 | using LoweredCodeUtils.JuliaInterpreter
|
3 |
| -using LoweredCodeUtils: callee_matches |
| 3 | +using LoweredCodeUtils: callee_matches, istypedef |
4 | 4 | using JuliaInterpreter: is_global_ref, is_quotenode
|
5 | 5 | using Test
|
6 | 6 |
|
|
352 | 352 | end
|
353 | 353 | end
|
354 | 354 | end
|
| 355 | + |
| 356 | +@testset "selective interpretation of toplevel definitions" begin |
| 357 | + gen_mock_module() = Core.eval(@__MODULE__, :(module $(gensym(:LoweredCodeUtilsTestMock)) end)) |
| 358 | + function check_toplevel_definition_interprete(ex, defs, undefs) |
| 359 | + m = gen_mock_module() |
| 360 | + lwr = Meta.lower(m, ex) |
| 361 | + src = first(lwr.args) |
| 362 | + stmts = src.code |
| 363 | + edges = CodeEdges(src) |
| 364 | + |
| 365 | + isrq = lines_required!(istypedef.(stmts), src, edges) |
| 366 | + frame = Frame(m, src) |
| 367 | + selective_eval_fromstart!(frame, isrq, #= toplevel =# true) |
| 368 | + |
| 369 | + for def in defs; @test isdefined(m, def); end |
| 370 | + for undef in undefs; @test !isdefined(m, undef); end |
| 371 | + end |
| 372 | + |
| 373 | + @testset "case: $(i), interpret: $(defs), ignore $(undefs)" for (i, ex, defs, undefs) in ( |
| 374 | + (1, :(abstract type Foo end), (:Foo,), ()), |
| 375 | + |
| 376 | + (2, :(struct Foo end), (:Foo,), ()), |
| 377 | + |
| 378 | + (3, quote |
| 379 | + struct Foo |
| 380 | + val |
| 381 | + end |
| 382 | + end, (:Foo,), ()), |
| 383 | + |
| 384 | + (4, quote |
| 385 | + struct Foo{T} |
| 386 | + val::T |
| 387 | + Foo(v::T) where {T} = new{T}(v) |
| 388 | + end |
| 389 | + end, (:Foo,), ()), |
| 390 | + |
| 391 | + (5, :(primitive type Foo 32 end), (:Foo,), ()), |
| 392 | + |
| 393 | + (6, quote |
| 394 | + abstract type Foo end |
| 395 | + struct Foo1 <: Foo end |
| 396 | + struct Foo2 <: Foo end |
| 397 | + end, (:Foo, :Foo1, :Foo2), ()), |
| 398 | + |
| 399 | + (7, quote |
| 400 | + struct Foo |
| 401 | + v |
| 402 | + Foo(f) = new(f()) |
| 403 | + end |
| 404 | + |
| 405 | + foo = Foo(()->throw("don't interpret me")) |
| 406 | + end, (:Foo,), (:foo,)), |
| 407 | + |
| 408 | + # https://github.com/JuliaDebug/LoweredCodeUtils.jl/issues/47 |
| 409 | + (8, quote |
| 410 | + struct Foo |
| 411 | + b::Bool |
| 412 | + Foo(b) = new(b) |
| 413 | + end |
| 414 | + |
| 415 | + foo = Foo(false) |
| 416 | + end, (:Foo,), (:foo,)), |
| 417 | + |
| 418 | + # https://github.com/JuliaDebug/LoweredCodeUtils.jl/pull/48 |
| 419 | + # we shouldn't make `add_links!` recur into `QuoteNode`, otherwise the variable |
| 420 | + # `bar` will be selected as a requirement for `Bar1` (, which has "bar" field) |
| 421 | + (9, quote |
| 422 | + abstract type Bar end |
| 423 | + struct Bar1 <: Bar |
| 424 | + bar |
| 425 | + end |
| 426 | + |
| 427 | + r = (throw("don't interpret me"); rand(10000000000000000)) |
| 428 | + bar = Bar1(r) |
| 429 | + show(bar) |
| 430 | + end, (:Bar, :Bar1), (:r, :bar)) |
| 431 | + ) |
| 432 | + |
| 433 | + check_toplevel_definition_interprete(ex, defs, undefs) |
| 434 | + end |
| 435 | +end |
0 commit comments