{"action":"created","issue":{"url":"https://api.github.com/repos/davidagold/StructuredQueries.jl/issues/25","repository_url":"https://api.github.com/repos/davidagold/StructuredQueries.jl","labels_url":"https://api.github.com/repos/davidagold/StructuredQueries.jl/issues/25/labels{/name}","comments_url":"https://api.github.com/repos/davidagold/StructuredQueries.jl/issues/25/comments","events_url":"https://api.github.com/repos/davidagold/StructuredQueries.jl/issues/25/events","html_url":"https://github.com/davidagold/StructuredQueries.jl/pull/25","id":181057317,"number":25,"title":"WIP: Include higher-order lifting","user":{"login":"davidagold","id":11862683,"avatar_url":"https://avatars.githubusercontent.com/u/11862683?v=3","gravatar_id":"","url":"https://api.github.com/users/davidagold","html_url":"https://github.com/davidagold","followers_url":"https://api.github.com/users/davidagold/followers","following_url":"https://api.github.com/users/davidagold/following{/other_user}","gists_url":"https://api.github.com/users/davidagold/gists{/gist_id}","starred_url":"https://api.github.com/users/davidagold/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/davidagold/subscriptions","organizations_url":"https://api.github.com/users/davidagold/orgs","repos_url":"https://api.github.com/users/davidagold/repos","events_url":"https://api.github.com/users/davidagold/events{/privacy}","received_events_url":"https://api.github.com/users/davidagold/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2016-10-05T03:31:39Z","updated_at":"2016-10-06T15:58:55Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/davidagold/StructuredQueries.jl/pulls/25","html_url":"https://github.com/davidagold/StructuredQueries.jl/pull/25","diff_url":"https://github.com/davidagold/StructuredQueries.jl/pull/25.diff","patch_url":"https://github.com/davidagold/StructuredQueries.jl/pull/25.patch"},"body":"I'm leaving this as WIP until I coordinate it across AbstractTables as well. This implements the higher-order lifting strategy described in https://github.com/davidagold/AbstractTables.jl/issues/2. The only noticeable user-facing change is that `|` and `&` now exhibit three-valued logic semantics, so long as they are visible to the querying macro:\r\n\r\n```julia\r\njulia> using TablesDemo\r\n\r\njulia> tbl = TablesDemo.Table(\r\n           A = NullableArray{Bool}(3),\r\n           B = NullableArray([true, true, true])\r\n       )\r\n\r\nTablesDemo.Table\r\n│ Row │ A     │ B    │\r\n├─────┼───────┼──────┤\r\n│ 1   │ #NULL │ true │\r\n│ 2   │ #NULL │ true │\r\n│ 3   │ #NULL │ true │\r\n\r\n\r\njulia> @collect filter(tbl, A | B)\r\nTablesDemo.Table\r\n│ Row │ A     │ B    │\r\n├─────┼───────┼──────┤\r\n│ 1   │ #NULL │ true │\r\n│ 2   │ #NULL │ true │\r\n│ 3   │ #NULL │ true │\r\n```\r\n\r\ncc @johnmyleswhite "},"comment":{"url":"https://api.github.com/repos/davidagold/StructuredQueries.jl/issues/comments/252007335","html_url":"https://github.com/davidagold/StructuredQueries.jl/pull/25#issuecomment-252007335","issue_url":"https://api.github.com/repos/davidagold/StructuredQueries.jl/issues/25","id":252007335,"user":{"login":"davidagold","id":11862683,"avatar_url":"https://avatars.githubusercontent.com/u/11862683?v=3","gravatar_id":"","url":"https://api.github.com/users/davidagold","html_url":"https://github.com/davidagold","followers_url":"https://api.github.com/users/davidagold/followers","following_url":"https://api.github.com/users/davidagold/following{/other_user}","gists_url":"https://api.github.com/users/davidagold/gists{/gist_id}","starred_url":"https://api.github.com/users/davidagold/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/davidagold/subscriptions","organizations_url":"https://api.github.com/users/davidagold/orgs","repos_url":"https://api.github.com/users/davidagold/repos","events_url":"https://api.github.com/users/davidagold/events{/privacy}","received_events_url":"https://api.github.com/users/davidagold/received_events","type":"User","site_admin":false},"created_at":"2016-10-06T15:58:55Z","updated_at":"2016-10-06T15:58:55Z","body":"@nalimilan That's a good idea re: `null_safe_op`. So, we'd have something like the following? It looks like the value of `null_safe_op` for a particular combination of `f` and `x` gets inlined during lowering and then the branch gets taken care of by llvm (maybe?)...\r\n```julia\r\njulia> function lift(f, x)\r\n           if Base.null_safe_op(f, eltype(x))\r\n               return Nullable(f(unsafe_get(x)), x.hasvalue)\r\n           else\r\n               U = Core.Inference.return_type(f, Tuple{eltype(typeof(x))})\r\n               if isnull(x)\r\n                   return Nullable{U}()\r\n               else\r\n                   return Nullable(f(unsafe_get(x)))\r\n               end\r\n           end\r\n       end\r\nlift (generic function with 1 method)\r\n\r\njulia> f(x::Int) = x\r\nf (generic function with 1 method)\r\n\r\njulia> Base.null_safe_op(::typeof(f), ::Type{Int}) = true\r\n\r\njulia> x = Nullable(1)\r\nNullable{Int64}(1)\r\n\r\njulia> @code_warntype lift(f, x)\r\nVariables:\r\n  #self#::#lift\r\n  f::#f\r\n  x::Nullable{Int64}\r\n  U::Type{Int64}\r\n\r\nBody:\r\n  begin \r\n      NewvarNode(:(U::Type{Int64}))\r\n      unless $(QuoteNode(true)) goto 5 # line 3:\r\n      return $(Expr(:new, Nullable{Int64}, :((Core.getfield)(x,:hasvalue)::Bool), :((Core.getfield)(x,:value)::Int64)))\r\n      5:  # line 5:\r\n      U::Type{Int64} = $(QuoteNode(Int64)) # line 6:\r\n      unless (Base.box)(Base.Bool,(Base.not_int)((Core.getfield)(x::Nullable{Int64},:hasvalue)::Bool)) goto 12 # line 7:\r\n      return $(Expr(:new, Nullable{Int64}, false))\r\n      12:  # line 9:\r\n      return $(Expr(:new, Nullable{Int64}, true, :((Core.getfield)(x,:value)::Int64)))\r\n  end::Nullable{Int64}\r\n\r\njulia> @code_llvm lift(f, x)\r\n\r\ndefine void @julia_lift_63473(%Nullable.4* noalias sret, %Nullable.4*) #0 {\r\ntop:\r\n  %.sroa.2 = alloca [7 x i8], align 1\r\n  %2 = getelementptr inbounds %Nullable.4, %Nullable.4* %1, i64 0, i32 0\r\n  %3 = load i8, i8* %2, align 1\r\n  %4 = and i8 %3, 1\r\n  %5 = getelementptr inbounds %Nullable.4, %Nullable.4* %1, i64 0, i32 1\r\n  %6 = load i64, i64* %5, align 1\r\n  %7 = getelementptr inbounds %Nullable.4, %Nullable.4* %0, i64 0, i32 0\r\n  store i8 %4, i8* %7, align 8\r\n  %8 = getelementptr inbounds i8, i8* %7, i64 1\r\n  %9 = getelementptr inbounds [7 x i8], [7 x i8]* %.sroa.2, i64 0, i64 0\r\n  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %8, i8* %9, i64 7, i32 1, i1 false)\r\n  %10 = getelementptr inbounds %Nullable.4, %Nullable.4* %0, i64 0, i32 1\r\n  store i64 %6, i64* %10, align 8\r\n  ret void\r\n}\r\n```\r\n\r\nYou probably already knew that, but I'd never looked at how the `null_safe_op` business lowers. That's pretty cool."}}
{"actor":{"display_login":"davidagold"}}