File: eval.jq

package info (click to toggle)
fq 0.9.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 106,624 kB
  • sloc: xml: 2,835; makefile: 250; sh: 241; exp: 57; ansic: 21
file content (109 lines) | stat: -rw-r--r-- 3,054 bytes parent folder | download
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
include "internal";
include "query";


def _eval_error($what; $error):
  error(
    { what: $what
    , error: $error
    , column: 0
    , line: 1
    , filename: ""
    }
  );

def _eval_error_function_not_defined($name; $args):
  _eval_error(
    "compile";
    "function not defined: \($name)/\($args | length)"
  );

# if catch_query . -> try (.) catch .catch_query
# if input_query . -> .input_query | .
# if ... | <.slurp.> -> .slurp({slurp: "<slurp>", slurp_args: [arg query ast], orig: orig query ast, rewrite: rewritten query})
# else if .output_query -> . | .output_query
#
# ex ... | slurp -> <slurp>({...})
# ex no slurp: . -> try (.input_query | . | .output_query) catch .catch_query
def _eval_query_rewrite($opts):
  _query_fromtostring(
    ( . as $orig_query
    | _query_pipe_last as $last
    | ( $last
      | if _query_is_func then [_query_func_name, _query_func_args]
        else ["", []]
        end
      ) as [$last_func_name, $last_func_args]
    | $opts.slurps[$last_func_name] as $slurp
    | if $slurp then
        _query_transform_pipe_last(_query_ident)
      end
    | if $opts.catch_query then
        # _query_query to get correct precedence and a valid query
        # try (1+1) catch vs try 1 + 1 catch
        _query_try(. | _query_query; $opts.catch_query)
      end
    | if $opts.input_query then
        _query_pipe($opts.input_query; .)
      end
    | if $slurp then
        _query_func(
          $slurp;
          [ # pass original, rewritten and args queries as query ast trees
            ( { slurp: _query_string($last_func_name)
              , slurp_args:
                  ( $last_func_args
                  | if . then
                      ( map(_query_toquery)
                      | _query_commas
                      | _query_array
                      )
                    else (null | _query_array)
                    end
                  )
              , orig: ($orig_query | _query_toquery)
              , rewrite: _query_toquery
              }
            | _query_object
            )
          ]
        )
      elif $opts.output_query then
        _query_pipe(.; $opts.output_query)
      end
    )
  );

# TODO: better way? what about nested eval errors?
def _eval_is_compile_error:
  _is_object and .error != null and .what != null;
def _eval_compile_error_tostring:
  [ (.filename // "expr")
  , if .line != 1 or .column != 0 then "\(.line):\(.column)"
    else empty
    end
  , " \(.error)"
  ] | join(":");

def eval($expr; $opts; on_error; on_compile_error):
  ( . as $c
  | ($opts.filename // "expr") as $filename
  | try
      _eval(
        $expr | _eval_query_rewrite($opts);
        {filename: $filename}
      )
    catch
      if _eval_is_compile_error then
        # rewrite parse error will not have filename
        ( .filename = $filename
        | {error: ., input: $c}
        | on_compile_error
        )
      else
        ( {error: ., input: $c}
        | on_error
        )
      end
  );
def eval($expr): eval($expr; {}; .error | error; .error | error);