|
| 1 | +# All code is attached to its underlying database source |
| 2 | +struct SourceCode{Source} |
| 3 | + source::Source |
| 4 | + code::Expr |
| 5 | +end |
| 6 | + |
| 7 | +# Every time two `SourceCode` objects are combined, check to see whether they both come from the same source |
| 8 | +function pop_sources!(sources, something) |
| 9 | + something |
| 10 | +end |
| 11 | +function pop_sources!(sources, source_code::SourceCode) |
| 12 | + push!(sources, source_code.source) |
| 13 | + source_code.code |
| 14 | +end |
| 15 | + |
| 16 | +function combine_sources(a_function, source_codes...) |
| 17 | + sources = Set(Any[]) |
| 18 | + codes = partial_map(pop_sources!, sources, source_codes) |
| 19 | + if length(sources) != 1 |
| 20 | + error("Expected exactly one source; got ($(sources...))") |
| 21 | + else |
| 22 | + SourceCode(first(sources), Expr(:call, a_function, codes...)) |
| 23 | + end |
| 24 | +end |
| 25 | + |
| 26 | +# `@code_instead` hijacks call to create Julia expressions instead of evaluating functions |
| 27 | +function numbered_argument(number) |
| 28 | + Symbol(string("argument", number)) |
| 29 | +end |
| 30 | + |
| 31 | +function assert_type(argument, type) |
| 32 | + Expr(:(::), argument, type) |
| 33 | +end |
| 34 | + |
| 35 | +# Splat Varargs |
| 36 | +function maybe_splat(argument, a_type) |
| 37 | + if @capture a_type Vararg{AType_} |
| 38 | + Expr(:(...), argument) |
| 39 | + else |
| 40 | + argument |
| 41 | + end |
| 42 | +end |
| 43 | + |
| 44 | +function code_instead(location, a_function, types...) |
| 45 | + arguments = ntuple(numbered_argument, length(types)) |
| 46 | + Expr(:function, |
| 47 | + Expr(:call, a_function, map_unrolled(assert_type, arguments, types)...), |
| 48 | + Expr(:block, location, Expr(:call, |
| 49 | + combine_sources, |
| 50 | + a_function, |
| 51 | + map_unrolled(maybe_splat, arguments, types)... |
| 52 | + )) |
| 53 | + ) |
| 54 | +end |
| 55 | + |
| 56 | +macro code_instead(a_function, types...) |
| 57 | + code_instead(__source__, a_function, types...) |> esc |
| 58 | +end |
| 59 | + |
| 60 | +# Currently, query doesn't do anything |
| 61 | +function QueryOperators.query(source_code::SourceCode) |
| 62 | + source_code |
| 63 | +end |
| 64 | + |
| 65 | +@code_instead (==) SourceCode Any |
| 66 | +@code_instead (==) Any SourceCode |
| 67 | +@code_instead (==) SourceCode SourceCode |
| 68 | + |
| 69 | +@code_instead (!=) SourceCode Any |
| 70 | +@code_instead (!=) Any SourceCode |
| 71 | +@code_instead (!=) SourceCode SourceCode |
| 72 | + |
| 73 | +@code_instead (!) SourceCode |
| 74 | + |
| 75 | +@code_instead (&) SourceCode Any |
| 76 | +@code_instead (&) Any SourceCode |
| 77 | +@code_instead (&) SourceCode SourceCode |
| 78 | + |
| 79 | +@code_instead (|) SourceCode Any |
| 80 | +@code_instead (|) Any SourceCode |
| 81 | +@code_instead (|) SourceCode SourceCode |
| 82 | + |
| 83 | +@code_instead coalesce SourceCode Vararg{Any} |
| 84 | + |
| 85 | +@code_instead QueryOperators.drop SourceCode Integer |
| 86 | + |
| 87 | +@code_instead QueryOperators.filter SourceCode Any Expr |
| 88 | + |
| 89 | +@code_instead QueryOperators.groupby SourceCode Any Expr Any Expr |
| 90 | + |
| 91 | +@code_instead if_else SourceCode Any Any |
| 92 | +@code_instead if_else Any SourceCode Any |
| 93 | +@code_instead if_else Any Any SourceCode |
| 94 | +@code_instead if_else Any SourceCode SourceCode |
| 95 | +@code_instead if_else SourceCode Any SourceCode |
| 96 | +@code_instead if_else SourceCode SourceCode Any |
| 97 | +@code_instead if_else SourceCode SourceCode SourceCode |
| 98 | + |
| 99 | +@code_instead in SourceCode Any |
| 100 | +@code_instead in Any SourceCode |
| 101 | +@code_instead in SourceCode SourceCode |
| 102 | + |
| 103 | +@code_instead isequal SourceCode Any |
| 104 | +@code_instead isequal Any SourceCode |
| 105 | +@code_instead isequal SourceCode SourceCode |
| 106 | + |
| 107 | +@code_instead isless SourceCode Any |
| 108 | +@code_instead isless Any SourceCode |
| 109 | +@code_instead isless SourceCode SourceCode |
| 110 | + |
| 111 | +@code_instead ismissing SourceCode |
| 112 | + |
| 113 | +@code_instead QueryOperators.join SourceCode SourceCode Any Expr Any Expr Any Expr |
| 114 | + |
| 115 | +@code_instead length SourceCode |
| 116 | + |
| 117 | +@code_instead QueryOperators.map SourceCode Any Expr |
| 118 | + |
| 119 | +@code_instead occursin AbstractString SourceCode |
| 120 | +@code_instead occursin Regex SourceCode |
| 121 | + |
| 122 | +@code_instead QueryOperators.orderby SourceCode Any Expr |
| 123 | + |
| 124 | +@code_instead QueryOperators.orderby_descending SourceCode Any Expr |
| 125 | + |
| 126 | +@code_instead secondary SourceCode |
| 127 | + |
| 128 | +@code_instead startswith SourceCode Any |
| 129 | +@code_instead startswith Any SourceCode |
| 130 | +@code_instead startswith SourceCode SourceCode |
| 131 | + |
| 132 | +@code_instead QueryOperators.take SourceCode Any |
| 133 | + |
| 134 | +@code_instead QueryOperators.thenby SourceCode Any Expr |
| 135 | + |
| 136 | +@code_instead QueryOperators.thenby_descending SourceCode Any Expr |
| 137 | + |
| 138 | +@code_instead QueryOperators.unique SourceCode Any Expr |
0 commit comments