Skip to content

Commit 8465c3f

Browse files
Dale-Blackclaude
andcommitted
Package registry in compile_invoke, Type constructors, getproperty handling
- compile_invoke: check lookup_package_compilation(meth.module, meth.name) before fallback — enables registered functions in optimized IR :invoke path - compile_invoke: trace receiver SSA back to defining getfield statement to resolve correct captured_vars value for callable_overrides (fixes multiple same-type signal getters/setters in same closure) - compile_call: match Type constructors (isa Type) in package registry, not just Functions — enables PlotlyBase.Plot() struct constructor compilation - compile_call: suppress Base.getproperty(Module, :name) in unoptimized IR — allows PlotlyBase.scatter etc. to work via module field access - packages_plotly.jl: register Plot (capital P) alongside plot/plotly Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e8ea29c commit 8465c3f

2 files changed

Lines changed: 69 additions & 3 deletions

File tree

src/compiler/codegen.jl

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -822,8 +822,8 @@ function compile_call(ctx::JSCompilationContext, expr::Expr)
822822
return ""
823823
end
824824

825-
# Check package registry for positional calls
826-
if resolved_fn isa Function
825+
# Check package registry for positional calls (functions AND type constructors)
826+
if resolved_fn isa Function || resolved_fn isa Type
827827
fn_mod = parentmodule(resolved_fn)
828828
fn_sym = nameof(resolved_fn)
829829
compiler_fn = lookup_package_compilation(fn_mod, fn_sym)
@@ -832,6 +832,26 @@ function compile_call(ctx::JSCompilationContext, expr::Expr)
832832
end
833833
end
834834

835+
# Module field access: Base.getproperty(SomeModule, :name) → resolve to function
836+
# In unoptimized IR, `PlotlyBase.scatter(...)` becomes getproperty(PlotlyBase, :scatter)
837+
# followed by a call. Suppress the getproperty — the call will be matched by package registry.
838+
if resolved_fn === Base.getproperty && length(args) >= 3
839+
mod_arg = args[2]
840+
field_arg = args[3]
841+
mod_val = nothing
842+
if mod_arg isa GlobalRef
843+
mod_val = try getfield(mod_arg.mod, mod_arg.name) catch; nothing end
844+
elseif mod_arg isa Core.SSAValue
845+
mod_type = try ctx.code_info.ssavaluetypes[mod_arg.id] catch; nothing end
846+
if mod_type isa Core.Const
847+
mod_val = mod_type.val
848+
end
849+
end
850+
if mod_val isa Module
851+
return ""
852+
end
853+
end
854+
835855
# Array literal: [1.0, 2.0, 3.0] → Base.vect(1.0, 2.0, 3.0) → [1.0, 2.0, 3.0]
836856
if resolved_fn === Base.vect
837857
return "[$(join(call_args, ", "))]"
@@ -1090,6 +1110,21 @@ function compile_call(ctx::JSCompilationContext, expr::Expr)
10901110
return compile_string_concat(ctx, args[2:end])
10911111
end
10921112

1113+
# Base.getproperty(Module, :name) → suppress (module field access in unoptimized IR)
1114+
if bname === :getproperty && callee.mod === Base && length(args) >= 3
1115+
mod_arg = args[2]
1116+
mod_val = nothing
1117+
if mod_arg isa GlobalRef
1118+
mod_val = try getfield(mod_arg.mod, mod_arg.name) catch; nothing end
1119+
elseif mod_arg isa Core.SSAValue
1120+
mod_type = try ctx.code_info.ssavaluetypes[mod_arg.id] catch; nothing end
1121+
if mod_type isa Core.Const; mod_val = mod_type.val; end
1122+
end
1123+
if mod_val isa Module
1124+
return ""
1125+
end
1126+
end
1127+
10931128
# Base.vect — array literal [1, 2, 3]
10941129
if bname === :vect && callee.mod === Base
10951130
call_args_v = [compile_value(ctx, a) for a in args[2:end]]
@@ -1381,6 +1416,26 @@ function compile_invoke(ctx::JSCompilationContext, expr::Expr)
13811416
if receiver_type isa DataType && haskey(ctx.callable_overrides, receiver_type)
13821417
override_fn = ctx.callable_overrides[receiver_type]
13831418
receiver_js = compile_value(ctx, expr.args[2])
1419+
1420+
# Trace receiver SSA back to defining getfield to resolve correct
1421+
# captured_vars value (handles multiple same-type signal getters/setters)
1422+
if !isempty(ctx.captured_vars) && expr.args[2] isa Core.SSAValue
1423+
recv_ssa_id = expr.args[2].id
1424+
if recv_ssa_id >= 1 && recv_ssa_id <= length(ctx.code_info.code)
1425+
recv_stmt = ctx.code_info.code[recv_ssa_id]
1426+
if recv_stmt isa Expr && recv_stmt.head == :call && length(recv_stmt.args) >= 3
1427+
recv_target = recv_stmt.args[2]
1428+
recv_field = recv_stmt.args[3]
1429+
field_name = recv_field isa QuoteNode ? recv_field.value : recv_field
1430+
is_closure = (recv_target isa Core.Argument && recv_target.n == 1) ||
1431+
(recv_target isa Core.SlotNumber && recv_target.id == 1)
1432+
if is_closure && field_name isa Symbol && haskey(ctx.captured_vars, field_name)
1433+
receiver_js = ctx.captured_vars[field_name]
1434+
end
1435+
end
1436+
end
1437+
end
1438+
13841439
return override_fn(receiver_js, call_args)
13851440
end
13861441
end
@@ -1632,6 +1687,14 @@ function compile_invoke(ctx::JSCompilationContext, expr::Expr)
16321687
return call_args[2]
16331688
end
16341689

1690+
# Check package compilation registry (for registered functions like sort_for, plotly, etc.)
1691+
fn_mod = meth.module
1692+
fn_name_sym = meth.name
1693+
pkg_compiler = lookup_package_compilation(fn_mod, fn_name_sym)
1694+
if pkg_compiler !== nothing
1695+
return pkg_compiler(ctx, Dict{Symbol,String}(), call_args)
1696+
end
1697+
16351698
return "$(func_name)($(join(call_args, ", ")))"
16361699
end
16371700

src/compiler/packages_plotly.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,10 @@ function register_plotly_compilations!(mod::Module)
8585
register_package_compilation!(_plotly_layout_compiler, mod, :Layout)
8686
end
8787

88-
# Plot
88+
# Plot / plot / plotly
89+
if isdefined(mod, :Plot)
90+
register_package_compilation!(_plotly_plot_compiler, mod, :Plot)
91+
end
8992
if isdefined(mod, :plot)
9093
register_package_compilation!(_plotly_plot_compiler, mod, :plot)
9194
end

0 commit comments

Comments
 (0)