using CUDA
using .ExpressionProcessing
using .Transpiler

expressions = Vector{Expr}(undef, 3)
variables = Matrix{Float32}(undef, 5, 4)
parameters = Vector{Vector{Float32}}(undef, 3)

expressions[1] = :(1 + 3 * 5 / 7 - sqrt(log(4)))
expressions[2] = :(5 + x1 + 1 * x2 + p1 + p2 + x1^x3)
expressions[3] = :(log(x1) / x2 * sqrt(p1) + x3^x4 - exp(x5))

variables[1,1] = 2.0
variables[2,1] = 3.0
variables[3,1] = 0.0
variables[4,1] = 1.0
variables[5,1] = 0.0

variables[1,2] = 2.0
variables[2,2] = 5.0
variables[3,2] = 3.0
variables[4,2] = 0.0 
variables[5,2] = 0.0

variables[1,3] = 6.0
variables[2,3] = 2.0
variables[3,3] = 2.0
variables[4,3] = 4.0
variables[5,3] = 2.0

variables[1,4] = 1.0
variables[2,4] = 2.0
variables[3,4] = 3.0
variables[4,4] = 4.0
variables[5,4] = 5.0

parameters[1] = Vector{Float32}(undef, 0)
parameters[2] = Vector{Float32}(undef, 2)
parameters[3] = Vector{Float32}(undef, 1)
parameters[2][1] = 5.0
parameters[2][2] = 0.0
parameters[3][1] = 16.0

@testset "Test transpiler evaluation" begin
	results = Transpiler.evaluate(expressions, variables, parameters)

	# dump(expressions[3]; maxdepth=10)
	# Expr 1:
	@test isapprox(results[1,1], 1.96545)
	@test isapprox(results[2,1], 1.96545)
	@test isapprox(results[3,1], 1.96545)
	@test isapprox(results[4,1], 1.96545)
	#Expr 2:
	@test isapprox(results[1,2], 16.0)
	@test isapprox(results[2,2], 25.0)
	@test isapprox(results[3,2], 54.0)
	@test isapprox(results[4,2], 14.0)

	#Expr3:
	@test isapprox(results[1,3],  -0.07580)
	@test isapprox(results[2,3],   0.55452)
	@test isapprox(results[3,3],  12.19446)
	@test isapprox(results[4,3], -67.41316)
end

# TODO: test performance of transpiler PTX generation when doing "return String(take!(buffer))" vs "return take!(buffer)"