Skip to content

Commit

Permalink
Fix JuliaData#328 parsing bug try 2 (JuliaData#346)
Browse files Browse the repository at this point in the history
* simpler diff

* hygiene

* better fix

* update versions
  • Loading branch information
pdeffebach committed Feb 6, 2023
1 parent 18e847a commit dc2d1c9
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 13 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ jobs:
fail-fast: false
matrix:
version:
- '1.0'
- '1.5'
- '1.6'
- '1.8'
- 'nightly'
os:
- ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Chain = "0.5"
DataFrames = "1"
MacroTools = "0.5"
Reexport = "0.2, 1"
julia = "1"
julia = "1.6"
OrderedCollections = "1"

[extras]
Expand Down
29 changes: 19 additions & 10 deletions src/parsing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -91,26 +91,40 @@ function is_nested_fun_recursive(x::Expr, nested_once)
return false
end
end

fix_simple_dot(x) = x
function fix_simple_dot(x::Symbol)
if startswith(string(x), '.')
f_sym_without_dot = Symbol(chop(string(x), head = 1, tail = 0))
return Expr(:., f_sym_without_dot)
else
return x
end
end

make_composed(x) = x
function make_composed(x::Expr)
funs = Any[]
x_orig = x
nested_once = false
while true
fun = fix_simple_dot(x.args[1])
if is_nested_fun(x)
push!(funs, x.args[1])
push!(funs, fun)
x = x.args[2]
nested_once = true
elseif is_simple_non_broadcast_call(x) && nested_once
push!(funs, x.args[1])
push!(funs, fun)
# ∘(f, g, h)(:x, :y, :z)
return Expr(:call, Expr(:call, , funs...), x.args[2:end]...)
x = Expr(:call, Expr(:call, , funs...), x.args[2:end]...)
return x
else
throw(ArgumentError("Not eligible for function composition"))
end
end
end


is_simple_non_broadcast_call(x) = false
function is_simple_non_broadcast_call(expr::Expr)
expr.head == :call &&
Expand Down Expand Up @@ -248,17 +262,12 @@ function get_source_fun(function_expr; exprflags = deepcopy(DEFAULT_FLAGS))
fun_t = function_expr.args[1]

# .+ to +
if startswith(string(fun_t), '.')
f_sym_without_dot = Symbol(chop(string(fun_t), head = 1, tail = 0))
fun = :(DataFrames.ByRow($f_sym_without_dot))
else
fun = fun_t
end
fun = fix_simple_dot(fun_t)
elseif is_simple_broadcast_call(function_expr)
# extract source symbols from quotenodes
source = args_to_selectors(function_expr.args[2].args)
fun_t = function_expr.args[1]
fun = :(DataFrames.ByRow($fun_t))
fun = Expr(:., fun_t)
elseif is_nested_fun_recursive(function_expr, false)
composed_expr = make_composed(function_expr)
# Repeat clean up from simple non-broadcast above
Expand Down
49 changes: 49 additions & 0 deletions test/parsing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,53 @@ end
@test n === nothing
end

@testset "broadcasted binary operators" begin
df = DataFrame(x = [1, 2], y = [3, 4])

df2 = @select df :z = first(:x .+ :y)
@test df2 == DataFrame(z = [4, 4])

df2 = @by df :x :y = first(:y .* :y)

@test df2 == DataFrame(x = [1, 2], y = [9, 16])

df2 = @select df :y = first(last(:y))

@test df2 == DataFrame(y = [4, 4])

df2 = @select df :z = .+(:x)

@test df2 == DataFrame(z = [1, 2])

df2 = @select df :z = .+(first(:x))

@test df2 == DataFrame(z = [1, 1])

df2 = @select df :z = first(.*(:x))

@test df2 == DataFrame(z = 1)

df2 = @select df :z = .+(.*(:x))

@test df2 == DataFrame(z = 1)

df2 = @select df :z = .+(.*(:x, :y))

@test df2 == DataFrame(z = 2)

@test df2 == DataFrame(y = 2)

df = DataFrame(
x = [1, 1, 2, 2, 3, 3],
y = [true, false, true, false, true, false],
z = [true, true, true, false, false, false])

df2 = @by(df,
:x,
:a = maximum(:y .* :z))

@test df2 == DataFrame(x = [1, 2, 3], a = [true, true, false])

end

end # module

0 comments on commit dc2d1c9

Please sign in to comment.