1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
|
# This file is a part of Julia. License is MIT: https://julialang.org/license
using Base.Printf: @sprintf
using Random
@generated function staged_t1(a,b)
if a == Int
return :(a+b)
else
return :(a*b)
end
end
@test staged_t1(1,2) == 3
@test staged_t1(1.0,0.5) == 0.5
@test staged_t1(1,0.5) == 1.5
tinline(a,b) = staged_t1(a,b)
@test !isa(tinline(1,2),Expr)
@test tinline(1,0.5) == 1.5
@generated function splat(a,b...)
:( ($a,$b,a,b) )
end
@test splat(1,2,3) == (Int,(Int,Int),1,(2,3))
stagediobuf = IOBuffer()
@generated function splat2(a...)
print(stagediobuf, a)
:(nothing)
end
const intstr = @sprintf("%s", Int)
splat2(1)
@test String(take!(stagediobuf)) == "($intstr,)"
splat2(1, 3)
@test String(take!(stagediobuf)) == "($intstr, $intstr)"
splat2(5, 2)
@test String(take!(stagediobuf)) == ""
splat2(1:3, 5.2)
@test String(take!(stagediobuf)) == "(UnitRange{$intstr}, Float64)"
splat2(3, 5:2:7)
@test String(take!(stagediobuf)) == "($intstr, StepRange{$intstr,$intstr})"
splat2(1, 2, 3, 4)
@test String(take!(stagediobuf)) == "($intstr, $intstr, $intstr, $intstr)"
splat2(1, 2, 3)
@test String(take!(stagediobuf)) == "($intstr, $intstr, $intstr)"
splat2(1:5, 3, 3:3)
@test String(take!(stagediobuf)) == "(UnitRange{$intstr}, $intstr, UnitRange{$intstr})"
splat2(1:5, 3, 3:3)
@test String(take!(stagediobuf)) == ""
splat2(1:5, 3:3, 3)
@test String(take!(stagediobuf)) == "(UnitRange{$intstr}, UnitRange{$intstr}, $intstr)"
splat2(1:5, 3:3)
@test String(take!(stagediobuf)) == "(UnitRange{$intstr}, UnitRange{$intstr})"
splat2(3, 3:5)
@test String(take!(stagediobuf)) == "($intstr, UnitRange{$intstr})"
# varargs specialization with parametric @generated functions (issue #8944)
@generated function splat3(A::AbstractArray{T,N}, indx::Base.RangeIndex...) where {T,N}
print(stagediobuf, indx)
:(nothing)
end
A = rand(5,5,3)
splat3(A, 1:2, 1:2, 1)
@test String(take!(stagediobuf)) == "(UnitRange{$intstr}, UnitRange{$intstr}, $intstr)"
splat3(A, 1:2, 1, 1:2)
@test String(take!(stagediobuf)) == "(UnitRange{$intstr}, $intstr, UnitRange{$intstr})"
B = view(A, 1:3, 2, 1:3)
@generated function mygetindex(S::SubArray, indices::Real...)
T, N, A, I = S.parameters
if N != length(indices)
error("Wrong number of indices supplied")
end
Ip = I.parameters
NP = length(Ip)
indexexprs = Vector{Expr}(undef, NP)
j = 1
for i = 1:NP
if Ip[i] == Int
indexexprs[i] = :(S.indices[$i])
else
indexexprs[i] = :(S.indices[$i][indices[$j]])
j += 1
end
end
ex = :(S.parent[$(indexexprs...)])
ex
end
@test mygetindex(B,2,2) == A[2,2,2]
# issue #8497
module MyTest8497
internalfunction(x) = x+1
@generated function h(x)
quote
internalfunction(x)
end
end
end
@test MyTest8497.h(3) == 4
# static parameters (issue #8505)
@generated function foo1(a::Array{T,N}) where {N,T}
"N = $N, T = $T"
end
@generated function foo2(a::Array{T,N}) where {T,N}
"N = $N, T = $T"
end
@test foo1(randn(3,3)) == "N = 2, T = Float64"
@test foo2(randn(3,3)) == "N = 2, T = Float64"
# issue #9088
@generated function f9088(x, a=5)
:(x+a)
end
@test f9088(7) == 12
# issue #10502
@generated function f10502(x...)
:($x)
end
f10502() = ()
@test f10502(1) == (Int,)
@test f10502(1,2) == (Int,Int)
@test f10502(1,2,3) == (Int,Int,Int)
# One-line @generated functions
@generated oneliner(x,y) = :($x, x, $y, y)
@test oneliner(1, 2.) == (Int, 1, Float64, 2.)
# issue #11982
@generated function f11982(T)
string(T.parameters[1])
end
@test f11982(Float32) == "Float32"
@test f11982(Int32) == "Int32"
# @generated functions that throw (shouldn't segfault or throw)
module TestGeneratedThrow
using Test, Random
@generated function bar(x)
error("I'm not happy with type $x")
end
foo() = (bar(rand() > 0.5 ? 1 : 1.0); error("foo"))
inited = false
function __init__()
code_typed(foo, (); optimize = false)
@cfunction(foo, Cvoid, ())
global inited = true
end
end
@test TestGeneratedThrow.inited
# @generated functions including inner functions
@generated function _g_f_with_inner(x)
return :(y -> y)
end
@test_throws ErrorException _g_f_with_inner(1)
@generated function _g_f_with_inner2(x)
return y -> y
end
@test _g_f_with_inner2(1)(2) == 2
# @generated functions errors
global gf_err_ref = Ref{Int}()
gf_err_ref[] = 0
let gf_err, tsk = @async nothing # create a Task for yield to try to run
@generated function gf_err()
gf_err_ref[] += 1
yield()
gf_err_ref[] += 1000
end
@test_throws ErrorException gf_err()
@test_throws ErrorException gf_err()
@test gf_err_ref[] == 4
end
gf_err_ref[] = 0
let gf_err2
@generated function gf_err2(::f) where {f}
gf_err_ref[] += 1
reflect = f.instance
gf_err_ref[] += 1
reflect(+, (Int,Int))
gf_err_ref[] += 1000
return nothing
end
@test_throws ErrorException gf_err2(code_typed)
@test gf_err_ref[] == 4
@test gf_err2(code_lowered) === nothing
end
# issue #15043
decorated = Set{DataType}()
let
@generated function decorate(t)
push!(decorated, t)
end
foo() = return nothing
decorate(foo)
@test in(typeof(foo), decorated)
bar() = return 1
decorate(bar)
@test in(typeof(bar), decorated)
end
# issue #19897
@test code_lowered(staged_t1, (Int,Int)) isa Array # check no error thrown
# issue #10178
@generated function f10178(x::X) where X
:(x)
end
g10178(x) = f10178(x)
@test g10178(5) == 5
@generated function f10178(x::X) where X
:(2x)
end
g10178(x) = f10178(x)
@test g10178(5) == 10
# issue #22135
@generated f22135(x::T) where T = x
@test f22135(1) === Int
# PR #22440
f22440kernel(x...) = x[1] + x[1]
f22440kernel(x::AbstractFloat) = x * x
f22440kernel(::Type{T}) where {T} = one(T)
f22440kernel(::Type{T}) where {T<:AbstractFloat} = zero(T)
@generated function f22440(y)
sig, spvals, method = Base._methods_by_ftype(Tuple{typeof(f22440kernel),y}, -1, typemax(UInt))[1]
code_info = Base.uncompressed_ast(method)
Meta.partially_inline!(code_info.code, Any[], sig, Any[spvals...], 0, 0, :propagate)
return code_info
end
@test f22440(Int) === f22440kernel(Int)
@test f22440(Float64) === f22440kernel(Float64)
@test f22440(Float32) === f22440kernel(Float32)
@test f22440(0.0) === f22440kernel(0.0)
@test f22440(0.0f0) === f22440kernel(0.0f0)
@test f22440(0) === f22440kernel(0)
# PR #23168
function f23168(a, x)
push!(a, 1)
if @generated
:(y = x + x)
else
y = 2x
end
push!(a, y)
if @generated
:(y = (y, $x))
else
y = (y, typeof(x))
end
push!(a, 3)
return y
end
let a = Any[]
@test f23168(a, 3) == (6, Int)
@test a == [1, 6, 3]
@test occursin(" + ", string(code_lowered(f23168, (Vector{Any},Int))))
@test occursin("2 * ", string(Base.uncompressed_ast(first(methods(f23168)))))
@test occursin("2 * ", string(code_lowered(f23168, (Vector{Any},Int), generated=false)))
@test occursin("Base.add_int", string(code_typed(f23168, (Vector{Any},Int))))
end
# issue #18747
@test_throws ErrorException eval(:(f(x) = @generated g() = x))
|