diff --git a/src/ast.c b/src/ast.c index 4799810c41550..0956723653b1c 100644 --- a/src/ast.c +++ b/src/ast.c @@ -191,11 +191,29 @@ value_t fl_invoke_julia_macro(fl_context_t *fl_ctx, value_t *args, uint32_t narg return scmresult; } +// Check whether v is a scalar for purposes of inlining fused-broadcast +// arguments when lowering; should agree with broadcast.jl on what is a +// scalar. When in doubt, return false, since this is only an optimization. +// (TODO: update after #16966 is resolved.) +int fl_julia_scalar(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) +{ + argcount(fl_ctx, "julia-scalar?", nargs, 1); + if (fl_isnumber(fl_ctx, args[0])) + return fl_ctx->T; + else if (iscvalue(args[0]) && fl_ctx->jl_sym == cv_type((cvalue_t*)ptr(args[0]))) { + jl_value_t *v = *(jl_value_t**)cptr(args[0]); + if (jl_subtype(v,(jl_value_t*)jl_number_type,1)) + return fl_ctx->T; + } + return fl_ctx->F; +} + static const builtinspec_t julia_flisp_ast_ext[] = { { "defined-julia-global", fl_defined_julia_global }, { "invoke-julia-macro", fl_invoke_julia_macro }, { "current-julia-module", fl_current_julia_module }, { "current-julia-module-counter", fl_current_module_counter }, + { "julia-scalar?", fl_julia_scalar }, { NULL, NULL } }; diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 0d14e75fd6327..1ed42e952c75a 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1679,7 +1679,7 @@ new-fargs new-args (cons (cons (cadr farg) (cadr varfarg)) renames) varfarg vararg) (error "multiple splatted args cannot be fused into a single broadcast")))) - ((number? arg) ; inline numeric literals + ((julia-scalar? arg) ; inline numeric literals etc. (cf (cdr old-fargs) (cdr old-args) new-fargs new-args (cons (cons farg arg) renames) diff --git a/test/broadcast.jl b/test/broadcast.jl index dfbbeed1c8950..ec4d4ebf111ef 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -289,6 +289,13 @@ let identity = error, x = [1,2,3] @test x == [1,1,1] end +# make sure scalars are inlined, which causes f.(x,scalar) to lower to a "thunk" +import Base.Meta: isexpr +@test isexpr(expand(:(f.(x,y))), :call) +@test isexpr(expand(:(f.(x,1))), :thunk) +@test isexpr(expand(:(f.(x,1.0))), :thunk) +@test isexpr(expand(:(f.(x,$π))), :thunk) + # PR 16988 @test Base.promote_op(+, Bool) === Int @test isa(broadcast(+, [true]), Array{Int,1})