From d90813827108460c53ceb3d6deee707e16ee3296 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Mon, 13 Nov 2023 11:56:56 +0100 Subject: [PATCH] match EE updates (which are not yet released so CI will fail) --- src/analysis/Errors.jl | 2 +- src/analysis/ExpressionExplorer.jl | 43 +++++++++++++++++++++++++++--- src/analysis/Topology.jl | 2 +- src/analysis/TopologyUpdate.jl | 2 +- src/evaluation/MacroAnalysis.jl | 2 +- src/evaluation/Run.jl | 3 ++- src/evaluation/RunBonds.jl | 2 +- src/evaluation/WorkspaceManager.jl | 4 +-- src/runner/PlutoRunner.jl | 2 +- test/MoreAnalysis.jl | 40 +++++++++++++++++++++++++++ 10 files changed, 90 insertions(+), 12 deletions(-) diff --git a/src/analysis/Errors.jl b/src/analysis/Errors.jl index eb63f550f0..d849160f8b 100644 --- a/src/analysis/Errors.jl +++ b/src/analysis/Errors.jl @@ -1,5 +1,5 @@ import Base: showerror -import .ExpressionExplorer: FunctionName, join_funcname_parts +import .ExpressionExplorer: FunctionName abstract type ReactivityError <: Exception end diff --git a/src/analysis/ExpressionExplorer.jl b/src/analysis/ExpressionExplorer.jl index ae4f10b5aa..6c37dd9b3f 100644 --- a/src/analysis/ExpressionExplorer.jl +++ b/src/analysis/ExpressionExplorer.jl @@ -37,7 +37,7 @@ function ExpressionExplorer.explore_macrocall!(ex::Expr, scopestate::ScopeState{ end # Some macros can be expanded on the server process - if ExpressionExplorer.join_funcname_parts(macro_name) ∈ can_macroexpand + if macro_name.joined ∈ can_macroexpand new_ex = maybe_macroexpand_pluto(ex) union!(symstate, ExpressionExplorer.explore!(new_ex, scopestate)) end @@ -78,9 +78,8 @@ If the macro is **known to Pluto**, expand or 'mock expand' it, if not, return t function maybe_macroexpand_pluto(ex::Expr; recursive::Bool=false, expand_bind::Bool=true) result::Expr = if ex.head === :macrocall funcname = ExpressionExplorer.split_funcname(ex.args[1]) - funcname_joined = ExpressionExplorer.join_funcname_parts(funcname) - if funcname_joined ∈ (expand_bind ? can_macroexpand : can_macroexpand_no_bind) + if funcname.joined ∈ (expand_bind ? can_macroexpand : can_macroexpand_no_bind) macroexpand(PlutoRunner, ex; recursive=false)::Expr else ex @@ -133,4 +132,42 @@ function transform_dot_notation(ex::Expr) end + +############### + + +""" +```julia +can_be_function_wrapped(ex)::Bool +``` + +Is this code simple enough that we can wrap it inside a function, and run the function in global scope instead of running the code directly? Look for `Pluto.PlutoRunner.Computer` to learn more. +""" +function can_be_function_wrapped(x::Expr) + if x.head === :global || # better safe than sorry + x.head === :using || + x.head === :import || + x.head === :export || + x.head === :public || # Julia 1.11 + x.head === :module || + x.head === :incomplete || + # Only bail on named functions, but anonymous functions (args[1].head == :tuple) are fine. + # TODO Named functions INSIDE other functions should be fine too + (x.head === :function && !Meta.isexpr(x.args[1], :tuple)) || + x.head === :macro || + # Cells containing macrocalls will actually be function wrapped using the expanded version of the expression + # See https://github.com/fonsp/Pluto.jl/pull/1597 + x.head === :macrocall || + x.head === :struct || + x.head === :abstract || + (x.head === :(=) && ExpressionExplorer.is_function_assignment(x)) || # f(x) = ... + (x.head === :call && (x.args[1] === :eval || x.args[1] === :include)) + false + else + all(can_be_function_wrapped, x.args) + end +end + +can_be_function_wrapped(x::Any) = true + end diff --git a/src/analysis/Topology.jl b/src/analysis/Topology.jl index d08ee7d5c0..6a4ab6ade0 100644 --- a/src/analysis/Topology.jl +++ b/src/analysis/Topology.jl @@ -15,7 +15,7 @@ ExprAnalysisCache(notebook, cell::Cell) = let code=cell.code, parsedcode=parsedcode, module_usings_imports=ExpressionExplorer.compute_usings_imports(parsedcode), - function_wrapped=ExpressionExplorer.can_be_function_wrapped(parsedcode), + function_wrapped=ExpressionExplorerExtras.can_be_function_wrapped(parsedcode), ) end diff --git a/src/analysis/TopologyUpdate.jl b/src/analysis/TopologyUpdate.jl index 98fa42403b..19e77dc0c1 100644 --- a/src/analysis/TopologyUpdate.jl +++ b/src/analysis/TopologyUpdate.jl @@ -1,6 +1,6 @@ import .ExpressionExplorer import .ExpressionExplorerExtras -import .ExpressionExplorer: join_funcname_parts, SymbolsState, FunctionNameSignaturePair +import .ExpressionExplorer: SymbolsState, FunctionNameSignaturePair "Return a copy of `old_topology`, but with recomputed results from `cells` taken into account." function updated_topology(old_topology::NotebookTopology, notebook::Notebook, cells) diff --git a/src/evaluation/MacroAnalysis.jl b/src/evaluation/MacroAnalysis.jl index a3ebb36409..ab4e799b52 100644 --- a/src/evaluation/MacroAnalysis.jl +++ b/src/evaluation/MacroAnalysis.jl @@ -113,7 +113,7 @@ function resolve_topology( if result isa Success (expr, computer_id) = result.result expanded_node = ExpressionExplorer.compute_reactive_node(expr; configuration=ExpressionExplorerExtras.PlutoConfiguration()) - function_wrapped = ExpressionExplorer.can_be_function_wrapped(expr) + function_wrapped = ExpressionExplorerExtras.can_be_function_wrapped(expr) Success((expanded_node, function_wrapped, computer_id)) else result diff --git a/src/evaluation/Run.jl b/src/evaluation/Run.jl index e74f0d8c4d..071a414d10 100644 --- a/src/evaluation/Run.jl +++ b/src/evaluation/Run.jl @@ -164,7 +164,8 @@ function run_reactive_core!( )...) if will_run_code(notebook) - deletion_hook((session, notebook), old_workspace_name, nothing, to_delete_vars, to_delete_funcs, to_reimport, cells_to_macro_invalidate; to_run) # `deletion_hook` defaults to `WorkspaceManager.move_vars` + to_delete_funcs_simple = Set{Tuple{Vararg{Symbol}}}((id, name.parts) for (id,name) in to_delete_funcs) + deletion_hook((session, notebook), old_workspace_name, nothing, to_delete_vars, to_delete_funcs_simple, to_reimport, cells_to_macro_invalidate; to_run) # `deletion_hook` defaults to `WorkspaceManager.move_vars` end foreach(v -> delete!(notebook.bonds, v), to_delete_vars) diff --git a/src/evaluation/RunBonds.jl b/src/evaluation/RunBonds.jl index 291b6eef85..3371f938ee 100644 --- a/src/evaluation/RunBonds.jl +++ b/src/evaluation/RunBonds.jl @@ -41,7 +41,7 @@ function set_bond_values_reactive(; bond_value_pairs = zip(syms_to_set, new_values) syms_to_set_set = Set{Symbol}(syms_to_set) - function custom_deletion_hook((session, notebook)::Tuple{ServerSession,Notebook}, old_workspace_name, new_workspace_name, to_delete_vars::Set{Symbol}, methods_to_delete::Set{Tuple{UUID,FunctionName}}, to_reimport::Set{Expr}, invalidated_cell_uuids::Set{UUID}; to_run::AbstractVector{Cell}) + function custom_deletion_hook((session, notebook)::Tuple{ServerSession,Notebook}, old_workspace_name, new_workspace_name, to_delete_vars::Set{Symbol}, methods_to_delete, to_reimport, invalidated_cell_uuids; to_run) to_delete_vars = union(to_delete_vars, syms_to_set_set) # also delete the bound symbols WorkspaceManager.move_vars( (session, notebook), diff --git a/src/evaluation/WorkspaceManager.jl b/src/evaluation/WorkspaceManager.jl index 12fbee2dd9..1fa1cf89e3 100644 --- a/src/evaluation/WorkspaceManager.jl +++ b/src/evaluation/WorkspaceManager.jl @@ -551,7 +551,7 @@ function move_vars( old_workspace_name::Symbol, new_workspace_name::Union{Nothing,Symbol}, to_delete::Set{Symbol}, - methods_to_delete::Set{Tuple{UUID,FunctionName}}, + methods_to_delete::Set{Tuple{UUID,Vararg{Symbol}}}, module_imports_to_move::Set{Expr}, invalidated_cell_uuids::Set{UUID}, keep_registered::Set{Symbol}=Set{Symbol}(); @@ -574,7 +574,7 @@ function move_vars( end) end -function move_vars(session_notebook::Union{SN,Workspace}, to_delete::Set{Symbol}, methods_to_delete::Set{Tuple{UUID,FunctionName}}, module_imports_to_move::Set{Expr}, invalidated_cell_uuids::Set{UUID}; kwargs...) +function move_vars(session_notebook::Union{SN,Workspace}, to_delete::Set{Symbol}, methods_to_delete::Set{Tuple{UUID,Vararg{Symbol}}}, module_imports_to_move::Set{Expr}, invalidated_cell_uuids::Set{UUID}; kwargs...) move_vars(session_notebook, bump_workspace_module(session_notebook)..., to_delete, methods_to_delete, module_imports_to_move, invalidated_cell_uuids; kwargs...) end diff --git a/src/runner/PlutoRunner.jl b/src/runner/PlutoRunner.jl index 28eb0decb1..2bcc9ecc78 100644 --- a/src/runner/PlutoRunner.jl +++ b/src/runner/PlutoRunner.jl @@ -688,7 +688,7 @@ function move_vars( old_workspace_name::Symbol, new_workspace_name::Symbol, vars_to_delete::Set{Symbol}, - methods_to_delete::Set{Tuple{UUID,Vector{Symbol}}}, + methods_to_delete::Set{Tuple{UUID,Tuple{Vararg{Symbol}}}}, module_imports_to_move::Set{Expr}, invalidated_cell_uuids::Set{UUID}, keep_registered::Set{Symbol}, diff --git a/test/MoreAnalysis.jl b/test/MoreAnalysis.jl index 76d0da4f2e..71646afb40 100644 --- a/test/MoreAnalysis.jl +++ b/test/MoreAnalysis.jl @@ -74,4 +74,44 @@ using Test @test transform(connections) == transform(wanted_connections) end + + + + @testset "can_be_function_wrapped" begin + + c = ExpressionExplorerExtras.can_be_function_wrapped + + + @test c(quote + a = b + C + if d + for i = 1:10 + while Y + end + end + end + end) + + + @test c(quote + map(1:10) do i + i + 1 + end + end) + + + @test !c(quote + function x(x) + X + end + end) + + @test !c(quote + if false + using Asdf + end + end) + + + end end