New Upstream Release - gojq

Ready changes

Summary

Merged new upstream version: 0.12.13 (was: 0.12.11).

Diff

diff --git a/.dockerignore b/.dockerignore
index c8e02dc..ac00163 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -6,4 +6,12 @@
 *.exe
 *.test
 *.out
-/.github/
+*.md
+*.y
+**/*.jq
+**/*.json
+**/*.yaml
+**/*_test.go
+.github
+_gojq
+_tools
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index edbfe86..8ed1668 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -6,6 +6,9 @@ on:
     - main
   pull_request:
 
+permissions:
+  contents: read
+
 jobs:
   test:
     name: Test
@@ -13,12 +16,12 @@ jobs:
     strategy:
       matrix:
         os: [ubuntu-latest, macos-latest, windows-latest]
-        go: [1.19.x, 1.18.x, 1.17.x]
+        go: [1.20.x, 1.19.x, 1.18.x]
     steps:
     - name: Checkout code
       uses: actions/checkout@v3
     - name: Setup Go
-      uses: actions/setup-go@v3
+      uses: actions/setup-go@v4
       with:
         go-version: ${{ matrix.go }}
     - name: Test
@@ -28,6 +31,7 @@ jobs:
       if: matrix.os != 'macos-latest'
     - name: Lint
       run: make lint
+      if: matrix.go >= '1.19.x'
     - name: Check tools
       run: make check-tools
     - name: Check go generate
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index f9e090b..19f75ad 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -5,38 +5,36 @@ on:
     tags:
     - 'v*'
 
-jobs:
+permissions:
+  contents: write
+  packages: write
 
+jobs:
   release:
     name: Release
     runs-on: ubuntu-latest
     steps:
-
     - name: Checkout code
       uses: actions/checkout@v3
-
     - name: Setup Go
-      uses: actions/setup-go@v3
+      uses: actions/setup-go@v4
       with:
         go-version: 1.x
-
     - name: Cross build
       run: make cross
-
     - name: Create Release
-      id: create_release
-      uses: actions/create-release@v1
-      env:
-        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      uses: ncipollo/release-action@v1
       with:
-        tag_name: ${{ github.ref }}
-        release_name: Release ${{ github.ref }}
-
-    - name: Upload
-      run: make upload
-      env:
-        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        name: Release ${{ github.ref_name }}
+        artifacts: 'goxz/*'
 
+  docker:
+    name: Docker
+    runs-on: ubuntu-latest
+    needs: release
+    steps:
+    - name: Checkout code
+      uses: actions/checkout@v3
     - name: Docker metadata
       uses: docker/metadata-action@v4
       id: metadata
@@ -48,28 +46,23 @@ jobs:
           type=semver,pattern={{version}}
           type=semver,pattern={{major}}.{{minor}}
           type=semver,pattern={{major}}
-
     - name: Set up QEMU
       uses: docker/setup-qemu-action@v2
-
     - name: Set up Docker Buildx
       uses: docker/setup-buildx-action@v2
-
     - name: Login to Docker Hub
       uses: docker/login-action@v2
       with:
         username: ${{ secrets.DOCKER_USERNAME }}
         password: ${{ secrets.DOCKER_PASSWORD }}
-
     - name: Login to GitHub Container Registry
       uses: docker/login-action@v2
       with:
         registry: ghcr.io
         username: ${{ github.repository_owner }}
         password: ${{ secrets.GITHUB_TOKEN }}
-
     - name: Build and release Docker image
-      uses: docker/build-push-action@v3
+      uses: docker/build-push-action@v4
       with:
         context: .
         push: true
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fa03401..8477cd3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,16 @@
 # Changelog
+## [v0.12.13](https://github.com/itchyny/gojq/compare/v0.12.12..v0.12.13) (2023-06-01)
+* implement `@urid` format string to decode URI values
+* fix functions returning arrays not to emit nil slices (`flatten`, `group_by`,
+  `unique`, `unique_by`, `nth`, `indices`, `path`, and `modulemeta.deps`)
+
+## [v0.12.12](https://github.com/itchyny/gojq/compare/v0.12.11..v0.12.12) (2023-03-01)
+* fix assignment operator (`=`) with overlapping paths and multiple values (`[[]] | .. = ..`)
+* fix crash on multiplying large numbers to an empty string (`9223372036854775807 * ""`)
+* improve zsh completion file
+
 ## [v0.12.11](https://github.com/itchyny/gojq/compare/v0.12.10..v0.12.11) (2022-12-24)
-* fix crash on assignment operators (`=`) with multiple values (`. = (0,0)`)
+* fix crash on assignment operator (`=`) with multiple values (`. = (0,0)`)
 * fix `isnormal` and `normals` functions against subnormal numbers
 
 ## [v0.12.10](https://github.com/itchyny/gojq/compare/v0.12.9..v0.12.10) (2022-12-01)
@@ -229,7 +239,7 @@
 ## [v0.7.0](https://github.com/itchyny/gojq/compare/v0.6.0..v0.7.0) (2019-12-22)
 * implement YAML input (`--yaml-input`) and output (`--yaml-output`)
 * fix pipe in object value
-* fix precedence of if, try, reduce and foreach expressions
+* fix precedence of `if`, `try`, `reduce` and `foreach` expressions
 * release from GitHub Actions
 
 ## [v0.6.0](https://github.com/itchyny/gojq/compare/v0.5.0..v0.6.0) (2019-08-26)
diff --git a/Dockerfile b/Dockerfile
index 284ece7..51f8632 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM golang:1.19 AS builder
+FROM golang:1.20 AS builder
 
 WORKDIR /app
 COPY . .
diff --git a/LICENSE b/LICENSE
index e3fc027..3f4fcb2 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
 The MIT License (MIT)
 
-Copyright (c) 2019-2022 itchyny
+Copyright (c) 2019-2023 itchyny
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/Makefile b/Makefile
index 983f994..b7cdb40 100644
--- a/Makefile
+++ b/Makefile
@@ -101,10 +101,3 @@ bump: $(GOBIN)/gobump
 	git commit -am "bump up version to $(VERSION)"
 	git tag "v$(VERSION)"
 	git push --atomic origin main tag "v$(VERSION)"
-
-.PHONY: upload
-upload: $(GOBIN)/ghr
-	ghr "v$(VERSION)" goxz
-
-$(GOBIN)/ghr:
-	go install github.com/tcnksm/ghr@latest
diff --git a/README.md b/README.md
index 29888a9..ca13b2f 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
 [![release](https://img.shields.io/github/release/itchyny/gojq/all.svg)](https://github.com/itchyny/gojq/releases)
 [![pkg.go.dev](https://pkg.go.dev/badge/github.com/itchyny/gojq)](https://pkg.go.dev/github.com/itchyny/gojq)
 
-### Pure Go implementation of [jq](https://github.com/stedolan/jq)
+### Pure Go implementation of [jq](https://github.com/jqlang/jq)
 This is an implementation of jq command written in Go language.
 You can also embed gojq as a library to your Go products.
 
@@ -77,10 +77,10 @@ docker run -i --rm ghcr.io/itchyny/gojq
 - gojq implements nice error messages for invalid query and JSON input. The error message of jq is sometimes difficult to tell where to fix the query.
 - gojq does not keep the order of object keys. I understand this might cause problems for some scripts but basically, we should not rely on the order of object keys. Due to this limitation, gojq does not have `keys_unsorted` function and `--sort-keys` (`-S`) option. I would implement when ordered map is implemented in the standard library of Go but I'm less motivated.
 - gojq supports arbitrary-precision integer calculation while jq does not; jq loses the precision of large integers when calculation is involved. Note that even with gojq, all mathematical functions, including `floor` and `round`, convert integers to floating-point numbers; only addition, subtraction, multiplication, modulo, and division operators (when divisible) keep the integer precision. To calculate floor division of integers without losing the precision, use `def idivide($n): (. - . % $n) / $n;`. To round down floating-point numbers to integers, use `def ifloor: floor | tostring | tonumber;`, but note that this function does not work with large floating-point numbers and also loses the precision of large integers.
-- gojq fixes various bugs of jq. gojq correctly deletes elements of arrays by `|= empty` ([jq#2051](https://github.com/stedolan/jq/issues/2051)). gojq fixes `try`/`catch` handling ([jq#1859](https://github.com/stedolan/jq/issues/1859), [jq#1885](https://github.com/stedolan/jq/issues/1885), [jq#2140](https://github.com/stedolan/jq/issues/2140)). gojq fixes `nth/2` to output nothing when the count is equal to or larger than the stream size ([jq#1867](https://github.com/stedolan/jq/issues/1867)). gojq consistently counts by characters (not by bytes) in `index`, `rindex`, and `indices` functions; `"12345" | .[index("3"):]` results in `"345"` ([jq#1430](https://github.com/stedolan/jq/issues/1430), [jq#1624](https://github.com/stedolan/jq/issues/1624)). gojq handles overlapping occurrence differently in `rindex` and `indices`; `"ababa" | [rindex("aba"), indices("aba")]` results in `[2,[0,2]]` ([jq#2433](https://github.com/stedolan/jq/issues/2433)). gojq supports string indexing; `"abcde"[2]` ([jq#1520](https://github.com/stedolan/jq/issues/1520)). gojq accepts indexing query `.e0` ([jq#1526](https://github.com/stedolan/jq/issues/1526), [jq#1651](https://github.com/stedolan/jq/issues/1651)), and allows `gsub` to handle patterns including `"^"` ([jq#2148](https://github.com/stedolan/jq/issues/2148)). gojq improves variable lexer to allow using keywords for variable names, especially in binding patterns, also disallows spaces after `$` ([jq#526](https://github.com/stedolan/jq/issues/526)). gojq fixes handling files with no newline characters at the end ([jq#2374](https://github.com/stedolan/jq/issues/2374)).
-- gojq truncates down floating-point numbers on indexing (`[0] | .[0.5]` results in `0` not `null`), and slicing (`[0,1,2] | .[0.5:1.5]` results in `[0]` not `[0,1]`). gojq parses unary operators with higher precedence than variable binding (`[-1 as $x | 1,$x]` results in `[1,-1]` not `[-1,-1]`). gojq implements `@uri` to escape all the reserved characters defined in RFC 3986, Sec. 2.2 ([jq#1506](https://github.com/stedolan/jq/issues/1506)), and fixes `@base64d` to allow binary string as the decoded string ([jq#1931](https://github.com/stedolan/jq/issues/1931)). gojq improves time formatting and parsing; deals with `%f` in `strftime` and `strptime` ([jq#1409](https://github.com/stedolan/jq/issues/1409)), parses timezone offsets with `fromdate` and `fromdateiso8601` ([jq#1053](https://github.com/stedolan/jq/issues/1053)), supports timezone name/offset with `%Z`/`%z` in `strptime` ([jq#929](https://github.com/stedolan/jq/issues/929), [jq#2195](https://github.com/stedolan/jq/issues/2195)), and looks up correct timezone during daylight saving time on formatting with `%Z` ([jq#1912](https://github.com/stedolan/jq/issues/1912)). gojq supports nanoseconds in date and time functions.
-- gojq does not support some functions intentionally; `get_jq_origin`, `get_prog_origin`, `get_search_list` (unstable, not listed in jq document), `input_line_number`, `$__loc__` (performance issue), `recurse_down` (deprecated in jq). gojq does not support some flags; `--ascii-output, -a` (performance issue), `--seq` (not used commonly), `--sort-keys, -S` (sorts by default because `map[string]interface{}` does not keep the order), `--unbuffered` (unbuffered by default). gojq does not parse JSON extensions supported by jq; `NaN`, `Infinity`, and `[000]`. gojq normalizes floating-point numbers to fit to double-precision floating-point numbers. gojq does not support some regular expression flags (regular expression engine differences). gojq does not support BOM (`encoding/json` does not support this). gojq disallows using keywords for function names (`def true: .; true` is a confusing query), and module name prefixes in function declarations (using module prefixes like `def m::f: .;` is undocumented).
-- gojq supports reading from YAML input (`--yaml-input`) while jq does not. gojq also supports YAML output (`--yaml-output`).
+- gojq fixes various bugs of jq. gojq correctly deletes elements of arrays by `|= empty` ([jq#2051](https://github.com/jqlang/jq/issues/2051)). gojq fixes `try`/`catch` handling ([jq#1859](https://github.com/jqlang/jq/issues/1859), [jq#1885](https://github.com/jqlang/jq/issues/1885), [jq#2140](https://github.com/jqlang/jq/issues/2140)). gojq fixes `nth/2` to output nothing when the count is equal to or larger than the stream size ([jq#1867](https://github.com/jqlang/jq/issues/1867)). gojq consistently counts by characters (not by bytes) in `index`, `rindex`, and `indices` functions; `"12345" | .[index("3"):]` results in `"345"` ([jq#1430](https://github.com/jqlang/jq/issues/1430), [jq#1624](https://github.com/jqlang/jq/issues/1624)). gojq handles overlapping occurrence differently in `rindex` and `indices`; `"ababa" | [rindex("aba"), indices("aba")]` results in `[2,[0,2]]` ([jq#2433](https://github.com/jqlang/jq/issues/2433)). gojq supports string indexing; `"abcde"[2]` ([jq#1520](https://github.com/jqlang/jq/issues/1520)). gojq accepts indexing query `.e0` ([jq#1526](https://github.com/jqlang/jq/issues/1526), [jq#1651](https://github.com/jqlang/jq/issues/1651)), and allows `gsub` to handle patterns including `"^"` ([jq#2148](https://github.com/jqlang/jq/issues/2148)). gojq improves variable lexer to allow using keywords for variable names, especially in binding patterns, also disallows spaces after `$` ([jq#526](https://github.com/jqlang/jq/issues/526)). gojq fixes handling files with no newline characters at the end ([jq#2374](https://github.com/jqlang/jq/issues/2374)).
+- gojq truncates down floating-point numbers on indexing (`[0] | .[0.5]` results in `0` not `null`), and slicing (`[0,1,2] | .[0.5:1.5]` results in `[0]` not `[0,1]`). gojq parses unary operators with higher precedence than variable binding (`[-1 as $x | 1,$x]` results in `[1,-1]` not `[-1,-1]`). gojq implements `@uri` to escape all the reserved characters defined in RFC 3986, Sec. 2.2 ([jq#1506](https://github.com/jqlang/jq/issues/1506)), and fixes `@base64d` to allow binary string as the decoded string ([jq#1931](https://github.com/jqlang/jq/issues/1931)). gojq improves time formatting and parsing; deals with `%f` in `strftime` and `strptime` ([jq#1409](https://github.com/jqlang/jq/issues/1409)), parses timezone offsets with `fromdate` and `fromdateiso8601` ([jq#1053](https://github.com/jqlang/jq/issues/1053)), supports timezone name/offset with `%Z`/`%z` in `strptime` ([jq#929](https://github.com/jqlang/jq/issues/929), [jq#2195](https://github.com/jqlang/jq/issues/2195)), and looks up correct timezone during daylight saving time on formatting with `%Z` ([jq#1912](https://github.com/jqlang/jq/issues/1912)). gojq supports nanoseconds in date and time functions.
+- gojq does not support some functions intentionally; `get_jq_origin`, `get_prog_origin`, `get_search_list` (unstable, not listed in jq document), `input_line_number`, `$__loc__` (performance issue), `recurse_down` (deprecated in jq). gojq does not support some flags; `--ascii-output, -a` (performance issue), `--seq` (not used commonly), `--sort-keys, -S` (sorts by default because `map[string]any` does not keep the order), `--unbuffered` (unbuffered by default). gojq does not parse JSON extensions supported by jq; `NaN`, `Infinity`, and `[000]`. gojq normalizes floating-point numbers to fit to double-precision floating-point numbers. gojq does not support or behaves differently with some regular expression metacharacters and flags (regular expression engine differences). gojq does not support BOM (`encoding/json` does not support this). gojq disallows using keywords for function names (`def true: .; true` is a confusing query), and module name prefixes in function declarations (using module prefixes like `def m::f: .;` is undocumented).
+- gojq supports reading from YAML input (`--yaml-input`) while jq does not. gojq also supports YAML output (`--yaml-output`). gojq supports a few filters missing in jq; `scan/2` ([jq#2207](https://github.com/jqlang/jq/pull/2207)), and `@urid` format string ([jq#2261](https://github.com/jqlang/jq/issues/2261)).
 
 ### Color configuration
 The gojq command automatically disables coloring output when the output is not a tty.
@@ -109,7 +109,7 @@ func main() {
 	if err != nil {
 		log.Fatalln(err)
 	}
-	input := map[string]interface{}{"foo": []interface{}{1, 2, 3}}
+	input := map[string]any{"foo": []any{1, 2, 3}}
 	iter := query.Run(input) // or query.RunWithContext
 	for {
 		v, ok := iter.Next()
@@ -128,9 +128,9 @@ func main() {
 - Secondly, get the result iterator
   - using [`query.Run`](https://pkg.go.dev/github.com/itchyny/gojq#Query.Run) or [`query.RunWithContext`](https://pkg.go.dev/github.com/itchyny/gojq#Query.RunWithContext)
   - or alternatively, compile the query using [`gojq.Compile`](https://pkg.go.dev/github.com/itchyny/gojq#Compile) and then [`code.Run`](https://pkg.go.dev/github.com/itchyny/gojq#Code.Run) or [`code.RunWithContext`](https://pkg.go.dev/github.com/itchyny/gojq#Code.RunWithContext). You can reuse the `*Code` against multiple inputs to avoid compilation of the same query. But for arguments of `code.Run`, do not give values sharing same data between multiple calls.
-  - In either case, you cannot use custom type values as the query input. The type should be `[]interface{}` for an array and `map[string]interface{}` for a map (just like decoded to an `interface{}` using the [encoding/json](https://golang.org/pkg/encoding/json/) package). You can't use `[]int` or `map[string]string`, for example. If you want to query your custom struct, marshal to JSON, unmarshal to `interface{}` and use it as the query input.
-- Thirdly, iterate through the results using [`iter.Next() (interface{}, bool)`](https://pkg.go.dev/github.com/itchyny/gojq#Iter). The iterator can emit an error so make sure to handle it. The method returns `true` with results, and `false` when the iterator terminates.
-  - The return type is not `(interface{}, error)` because iterators can emit multiple errors and you can continue after an error. It is difficult for the iterator to tell the termination in this situation.
+  - In either case, you cannot use custom type values as the query input. The type should be `[]any` for an array and `map[string]any` for a map (just like decoded to an `any` using the [encoding/json](https://golang.org/pkg/encoding/json/) package). You can't use `[]int` or `map[string]string`, for example. If you want to query your custom struct, marshal to JSON, unmarshal to `any` and use it as the query input.
+- Thirdly, iterate through the results using [`iter.Next() (any, bool)`](https://pkg.go.dev/github.com/itchyny/gojq#Iter). The iterator can emit an error so make sure to handle it. The method returns `true` with results, and `false` when the iterator terminates.
+  - The return type is not `(any, error)` because iterators can emit multiple errors and you can continue after an error. It is difficult for the iterator to tell the termination in this situation.
   - Note that the result iterator may emit infinite number of values; `repeat(0)` and `range(infinite)`. It may stuck with no output value; `def f: f; f`. Use `RunWithContext` when you want to limit the execution time.
 
 [`gojq.Compile`](https://pkg.go.dev/github.com/itchyny/gojq#Compile) allows to configure the following compiler options.
diff --git a/_gojq b/_gojq
index 4c94718..d403a31 100644
--- a/_gojq
+++ b/_gojq
@@ -2,31 +2,42 @@
 
 _gojq()
 {
-  _arguments -C \
-    '(-c --compact-output)'{-c,--compact-output}'[compact output]' \
-    '(-r --raw-output)'{-r,--raw-output}'[output raw strings]' \
-    '(-j --join-output)'{-j,--join-output}'[stop printing a newline after each output]' \
-    '(-0 --nul-output)'{-0,--nul-output}'[print NUL after each output]' \
-    '(-C --color-output)'{-C,--color-output}'[colorize output even if piped]' \
-    '(-M --monochrome-output)'{-M,--monochrome-output}'[stop colorizing output]' \
-    '(--yaml-output)'--yaml-output'[output by YAML]' \
-    '(--indent)'--indent'[number of spaces for indentation]:indentation count' \
-    '(--tab)'--tab'[use tabs for indentation]' \
+  _arguments -s -S \
+    '(-r --raw-output -j --join-output -0 --nul-output)'{-r,--raw-output}'[output raw strings]' \
+    '(-r --raw-output -j --join-output -0 --nul-output)'{-j,--join-output}'[output without newlines]' \
+    '(-r --raw-output -j --join-output -0 --nul-output)'{-0,--nul-output}'[output with NUL character]' \
+    '(-c --compact-output --indent --tab --yaml-output)'{-c,--compact-output}'[output without pretty-printing]' \
+    '(-c --compact-output          --tab --yaml-output)--indent=[number of spaces for indentation]:indentation count:(2 4 8)' \
+    '(-c --compact-output --indent       --yaml-output)--tab[use tabs for indentation]' \
+    '(-c --compact-output --indent --tab              )--yaml-output[output in YAML format]' \
+    '(-C --color-output -M --monochrome-output)'{-C,--color-output}'[output with colors even if piped]' \
+    '(-C --color-output -M --monochrome-output)'{-M,--monochrome-output}'[output without colors]' \
     '(-n --null-input)'{-n,--null-input}'[use null as input value]' \
-    '(-R --raw-input)'{-R,--raw-input}'[read input as raw strings]' \
+    '(-R --raw-input --stream --yaml-input)'{-R,--raw-input}'[read input as raw strings]' \
+    '(-R --raw-input          --yaml-input)--stream[parse input in stream fashion]' \
+    '(-R --raw-input --stream             )--yaml-input[read input as YAML format]' \
     '(-s --slurp)'{-s,--slurp}'[read all inputs into an array]' \
-    '(--stream)'--stream'[parse input in stream fashion]' \
-    '(--yaml-input)'--yaml-input'[read input as YAML]' \
-    '(-f --from-file)'{-f,--from-file}'[load query from file]:filename of jq query:_files' \
-    '(-L)'-L'[directory to search modules from]:module directory:_directories' \
-    '(--arg)'--arg'[set variable to string value]:variable name:' \
-    '(--argjson)'--argjson'[set variable to JSON value]:variable name:' \
-    '(--slurpfile)'--slurpfile'[set variable to the JSON contents of the file]:variable name:' \
-    '(--rawfile)'--rawfile'[set variable to the contents of the file]:variable name:' \
-    '(--args)'--args'[consume remaining arguments as positional string values]' \
-    '(--jsonargs)'--jsonargs'[consume remaining arguments as positional JSON values]' \
+    '(-f --from-file 1)'{-f,--from-file}='[load query from file]:filename of jq query:_files' \
+    '*-L=[directory to search modules from]:module directory:_directories' \
+    '*--arg[set a string value to a variable]:variable name: :string value' \
+    '*--argjson[set a JSON value to a variable]:variable name: :JSON value' \
+    '*--slurpfile[set the JSON contents of a file to a variable]:variable name: :JSON file:_files' \
+    '*--rawfile[set the contents of a file to a variable]:variable name: :file:_files' \
+    '*--args[consume remaining arguments as positional string values]' \
+    '*--jsonargs[consume remaining arguments as positional JSON values]' \
     '(-e --exit-status)'{-e,--exit-status}'[exit 1 when the last value is false or null]' \
-    '(-v --version)'{-v,--version}'[print version]' \
-    '(-h --help)'{-h,--help}'[print help]' \
-    && ret=0
+    '(- 1 *)'{-v,--version}'[display version information]' \
+    '(- 1 *)'{-h,--help}'[display help information]' \
+    '1: :_guard "^-([[:alpha:]0]#|-*)" "jq query"' \
+    '*: :_gojq_args'
+}
+
+_gojq_args() {
+  if (($words[(I)--args] > $words[(I)--jsonargs])); then
+    _message 'string value'
+  elif (($words[(I)--args] < $words[(I)--jsonargs])); then
+    _message 'JSON value'
+  else
+    _arguments '*:input file:_files'
+  fi
 }
diff --git a/cli/cli.go b/cli/cli.go
index cc06135..a10ead5 100644
--- a/cli/cli.go
+++ b/cli/cli.go
@@ -17,7 +17,7 @@ import (
 
 const name = "gojq"
 
-const version = "0.12.11"
+const version = "0.12.13"
 
 var revision = "HEAD"
 
@@ -35,51 +35,51 @@ type cli struct {
 	outStream io.Writer
 	errStream io.Writer
 
-	outputCompact bool
 	outputRaw     bool
 	outputJoin    bool
 	outputNul     bool
-	outputYAML    bool
+	outputCompact bool
 	outputIndent  *int
 	outputTab     bool
+	outputYAML    bool
 	inputRaw      bool
-	inputSlurp    bool
 	inputStream   bool
 	inputYAML     bool
+	inputSlurp    bool
 
 	argnames  []string
-	argvalues []interface{}
+	argvalues []any
 
 	outputYAMLSeparator bool
 	exitCodeError       error
 }
 
 type flagopts struct {
-	OutputCompact bool              `short:"c" long:"compact-output" description:"compact output"`
 	OutputRaw     bool              `short:"r" long:"raw-output" description:"output raw strings"`
-	OutputJoin    bool              `short:"j" long:"join-output" description:"stop printing a newline after each output"`
-	OutputNul     bool              `short:"0" long:"nul-output" description:"print NUL after each output"`
-	OutputColor   bool              `short:"C" long:"color-output" description:"colorize output even if piped"`
-	OutputMono    bool              `short:"M" long:"monochrome-output" description:"stop colorizing output"`
-	OutputYAML    bool              `long:"yaml-output" description:"output by YAML"`
+	OutputJoin    bool              `short:"j" long:"join-output" description:"output without newlines"`
+	OutputNul     bool              `short:"0" long:"nul-output" description:"output with NUL character"`
+	OutputCompact bool              `short:"c" long:"compact-output" description:"output without pretty-printing"`
 	OutputIndent  *int              `long:"indent" description:"number of spaces for indentation"`
 	OutputTab     bool              `long:"tab" description:"use tabs for indentation"`
+	OutputYAML    bool              `long:"yaml-output" description:"output in YAML format"`
+	OutputColor   bool              `short:"C" long:"color-output" description:"output with colors even if piped"`
+	OutputMono    bool              `short:"M" long:"monochrome-output" description:"output without colors"`
 	InputNull     bool              `short:"n" long:"null-input" description:"use null as input value"`
 	InputRaw      bool              `short:"R" long:"raw-input" description:"read input as raw strings"`
-	InputSlurp    bool              `short:"s" long:"slurp" description:"read all inputs into an array"`
 	InputStream   bool              `long:"stream" description:"parse input in stream fashion"`
-	InputYAML     bool              `long:"yaml-input" description:"read input as YAML"`
+	InputYAML     bool              `long:"yaml-input" description:"read input as YAML format"`
+	InputSlurp    bool              `short:"s" long:"slurp" description:"read all inputs into an array"`
 	FromFile      string            `short:"f" long:"from-file" description:"load query from file"`
 	ModulePaths   []string          `short:"L" description:"directory to search modules from"`
-	Arg           map[string]string `long:"arg" description:"set variable to string value"`
-	ArgJSON       map[string]string `long:"argjson" description:"set variable to JSON value"`
-	SlurpFile     map[string]string `long:"slurpfile" description:"set variable to the JSON contents of the file"`
-	RawFile       map[string]string `long:"rawfile" description:"set variable to the contents of the file"`
-	Args          []interface{}     `long:"args" positional:"" description:"consume remaining arguments as positional string values"`
-	JSONArgs      []interface{}     `long:"jsonargs" positional:"" description:"consume remaining arguments as positional JSON values"`
+	Arg           map[string]string `long:"arg" description:"set a string value to a variable"`
+	ArgJSON       map[string]string `long:"argjson" description:"set a JSON value to a variable"`
+	SlurpFile     map[string]string `long:"slurpfile" description:"set the JSON contents of a file to a variable"`
+	RawFile       map[string]string `long:"rawfile" description:"set the contents of a file to a variable"`
+	Args          []any             `long:"args" positional:"" description:"consume remaining arguments as positional string values"`
+	JSONArgs      []any             `long:"jsonargs" positional:"" description:"consume remaining arguments as positional JSON values"`
 	ExitStatus    bool              `short:"e" long:"exit-status" description:"exit 1 when the last value is false or null"`
-	Version       bool              `short:"v" long:"version" description:"print version"`
-	Help          bool              `short:"h" long:"help" description:"print this help"`
+	Version       bool              `short:"v" long:"version" description:"display version information"`
+	Help          bool              `short:"h" long:"help" description:"display this help information"`
 }
 
 var addDefaultModulePaths = true
@@ -121,10 +121,10 @@ Usage:
 		fmt.Fprintf(cli.outStream, "%s %s (rev: %s/%s)\n", name, version, revision, runtime.Version())
 		return nil
 	}
-	cli.outputCompact, cli.outputRaw, cli.outputJoin, cli.outputNul,
-		cli.outputYAML, cli.outputIndent, cli.outputTab =
-		opts.OutputCompact, opts.OutputRaw, opts.OutputJoin, opts.OutputNul,
-		opts.OutputYAML, opts.OutputIndent, opts.OutputTab
+	cli.outputRaw, cli.outputJoin, cli.outputNul,
+		cli.outputCompact, cli.outputIndent, cli.outputTab, cli.outputYAML =
+		opts.OutputRaw, opts.OutputJoin, opts.OutputNul,
+		opts.OutputCompact, opts.OutputIndent, opts.OutputTab, opts.OutputYAML
 	defer func(x bool) { noColor = x }(noColor)
 	if opts.OutputColor || opts.OutputMono {
 		noColor = opts.OutputMono
@@ -151,8 +151,8 @@ Usage:
 	if opts.OutputYAML && opts.OutputTab {
 		return errors.New("cannot use tabs for YAML output")
 	}
-	cli.inputRaw, cli.inputSlurp, cli.inputStream, cli.inputYAML =
-		opts.InputRaw, opts.InputSlurp, opts.InputStream, opts.InputYAML
+	cli.inputRaw, cli.inputStream, cli.inputYAML, cli.inputSlurp =
+		opts.InputRaw, opts.InputStream, opts.InputYAML, opts.InputSlurp
 	for k, v := range opts.Arg {
 		cli.argnames = append(cli.argnames, "$"+k)
 		cli.argvalues = append(cli.argvalues, v)
@@ -181,7 +181,7 @@ Usage:
 		cli.argnames = append(cli.argnames, "$"+k)
 		cli.argvalues = append(cli.argvalues, string(val))
 	}
-	named := make(map[string]interface{}, len(cli.argnames))
+	named := make(map[string]any, len(cli.argnames))
 	for i, name := range cli.argnames {
 		named[name[1:]] = cli.argvalues[i]
 	}
@@ -200,7 +200,7 @@ Usage:
 		}
 	}
 	cli.argnames = append(cli.argnames, "$ARGS")
-	cli.argvalues = append(cli.argvalues, map[string]interface{}{
+	cli.argvalues = append(cli.argvalues, map[string]any{
 		"named":      named,
 		"positional": positional,
 	})
@@ -242,8 +242,8 @@ Usage:
 		gojq.WithFunction("debug", 0, 0, cli.funcDebug),
 		gojq.WithFunction("stderr", 0, 0, cli.funcStderr),
 		gojq.WithFunction("input_filename", 0, 0,
-			func(iter inputIter) func(interface{}, []interface{}) interface{} {
-				return func(interface{}, []interface{}) interface{} {
+			func(iter inputIter) func(any, []any) any {
+				return func(any, []any) any {
 					if fname := iter.Name(); fname != "" && (len(args) > 0 || !opts.InputNull) {
 						return fname
 					}
@@ -291,7 +291,7 @@ func listDefaultModulePaths() []string {
 	return modulePaths
 }
 
-func slurpFile(name string) (interface{}, error) {
+func slurpFile(name string) (any, error) {
 	iter := newSlurpInputIter(
 		newFilesInputIter(newJSONInputIter, []string{name}, nil),
 	)
@@ -408,14 +408,20 @@ func (cli *cli) createMarshaler() marshaler {
 	return f
 }
 
-func (cli *cli) funcDebug(v interface{}, _ []interface{}) interface{} {
-	newEncoder(false, 0).marshal([]interface{}{"DEBUG:", v}, cli.errStream)
-	cli.errStream.Write([]byte{'\n'})
+func (cli *cli) funcDebug(v any, _ []any) any {
+	if err := newEncoder(false, 0).marshal([]any{"DEBUG:", v}, cli.errStream); err != nil {
+		return err
+	}
+	if _, err := cli.errStream.Write([]byte{'\n'}); err != nil {
+		return err
+	}
 	return v
 }
 
-func (cli *cli) funcStderr(v interface{}, _ []interface{}) interface{} {
-	newEncoder(false, 0).marshal(v, cli.errStream)
+func (cli *cli) funcStderr(v any, _ []any) any {
+	if err := newEncoder(false, 0).marshal(v, cli.errStream); err != nil {
+		return err
+	}
 	return v
 }
 
diff --git a/cli/encoder.go b/cli/encoder.go
index 2f6edee..8841baa 100644
--- a/cli/encoder.go
+++ b/cli/encoder.go
@@ -31,7 +31,7 @@ func (e *encoder) flush() error {
 	return err
 }
 
-func (e *encoder) marshal(v interface{}, w io.Writer) error {
+func (e *encoder) marshal(v any, w io.Writer) error {
 	e.out = w
 	err := e.encode(v)
 	if ferr := e.flush(); ferr != nil && err == nil {
@@ -40,7 +40,7 @@ func (e *encoder) marshal(v interface{}, w io.Writer) error {
 	return err
 }
 
-func (e *encoder) encode(v interface{}) error {
+func (e *encoder) encode(v any) error {
 	switch v := v.(type) {
 	case nil:
 		e.write([]byte("null"), nullColor)
@@ -58,12 +58,12 @@ func (e *encoder) encode(v interface{}) error {
 		e.write(v.Append(e.buf[:0], 10), numberColor)
 	case string:
 		e.encodeString(v, stringColor)
-	case []interface{}:
+	case []any:
 		if err := e.encodeArray(v); err != nil {
 			return err
 		}
-	case map[string]interface{}:
-		if err := e.encodeMap(v); err != nil {
+	case map[string]any:
+		if err := e.encodeObject(v); err != nil {
 			return err
 		}
 	default:
@@ -86,12 +86,12 @@ func (e *encoder) encodeFloat64(f float64) {
 	} else if f <= -math.MaxFloat64 {
 		f = -math.MaxFloat64
 	}
-	fmt := byte('f')
+	format := byte('f')
 	if x := math.Abs(f); x != 0 && x < 1e-6 || x >= 1e21 {
-		fmt = 'e'
+		format = 'e'
 	}
-	buf := strconv.AppendFloat(e.buf[:0], f, fmt, -1, 64)
-	if fmt == 'e' {
+	buf := strconv.AppendFloat(e.buf[:0], f, format, -1, 64)
+	if format == 'e' {
 		// clean up e-09 to e-9
 		if n := len(buf); n >= 4 && buf[n-4] == 'e' && buf[n-3] == '-' && buf[n-2] == '0' {
 			buf[n-2] = buf[n-1]
@@ -163,7 +163,7 @@ func (e *encoder) encodeString(s string, color []byte) {
 	}
 }
 
-func (e *encoder) encodeArray(vs []interface{}) error {
+func (e *encoder) encodeArray(vs []any) error {
 	e.writeByte('[', arrayColor)
 	e.depth += e.indent
 	for i, v := range vs {
@@ -185,12 +185,12 @@ func (e *encoder) encodeArray(vs []interface{}) error {
 	return nil
 }
 
-func (e *encoder) encodeMap(vs map[string]interface{}) error {
+func (e *encoder) encodeObject(vs map[string]any) error {
 	e.writeByte('{', objectColor)
 	e.depth += e.indent
 	type keyVal struct {
 		key string
-		val interface{}
+		val any
 	}
 	kvs := make([]keyVal, len(vs))
 	var i int
diff --git a/cli/flags.go b/cli/flags.go
index aab827b..fb3e34e 100644
--- a/cli/flags.go
+++ b/cli/flags.go
@@ -7,7 +7,7 @@ import (
 	"strings"
 )
 
-func parseFlags(args []string, opts interface{}) ([]string, error) {
+func parseFlags(args []string, opts any) ([]string, error) {
 	rest := make([]string, 0, len(args))
 	val := reflect.ValueOf(opts).Elem()
 	typ := val.Type()
@@ -158,7 +158,7 @@ func parseFlags(args []string, opts interface{}) ([]string, error) {
 	return rest, nil
 }
 
-func formatFlags(opts interface{}) string {
+func formatFlags(opts any) string {
 	val := reflect.ValueOf(opts).Elem()
 	typ := val.Type()
 	var sb strings.Builder
diff --git a/cli/inputs.go b/cli/inputs.go
index cf655af..1f91c48 100644
--- a/cli/inputs.go
+++ b/cli/inputs.go
@@ -83,11 +83,11 @@ func newJSONInputIter(r io.Reader, fname string) inputIter {
 	return &jsonInputIter{dec: dec, ir: ir, fname: fname}
 }
 
-func (i *jsonInputIter) Next() (interface{}, bool) {
+func (i *jsonInputIter) Next() (any, bool) {
 	if i.err != nil {
 		return nil, false
 	}
-	var v interface{}
+	var v any
 	if err := i.dec.Decode(&v); err != nil {
 		if err == io.EOF {
 			i.err = err
@@ -127,7 +127,7 @@ func newNullInputIter() inputIter {
 	return &nullInputIter{}
 }
 
-func (i *nullInputIter) Next() (interface{}, bool) {
+func (i *nullInputIter) Next() (any, bool) {
 	if i.err != nil {
 		return nil, false
 	}
@@ -159,7 +159,7 @@ func newFilesInputIter(
 	return &filesInputIter{newIter: newIter, fnames: fnames, stdin: stdin}
 }
 
-func (i *filesInputIter) Next() (interface{}, bool) {
+func (i *filesInputIter) Next() (any, bool) {
 	if i.err != nil {
 		return nil, false
 	}
@@ -227,7 +227,7 @@ func newRawInputIter(r io.Reader, fname string) inputIter {
 	return &rawInputIter{r: bufio.NewReader(r), fname: fname}
 }
 
-func (i *rawInputIter) Next() (interface{}, bool) {
+func (i *rawInputIter) Next() (any, bool) {
 	if i.err != nil {
 		return nil, false
 	}
@@ -269,7 +269,7 @@ func newStreamInputIter(r io.Reader, fname string) inputIter {
 	return &streamInputIter{stream: newJSONStream(dec), ir: ir, fname: fname}
 }
 
-func (i *streamInputIter) Next() (interface{}, bool) {
+func (i *streamInputIter) Next() (any, bool) {
 	if i.err != nil {
 		return nil, false
 	}
@@ -318,11 +318,11 @@ func newYAMLInputIter(r io.Reader, fname string) inputIter {
 	return &yamlInputIter{dec: dec, ir: ir, fname: fname}
 }
 
-func (i *yamlInputIter) Next() (interface{}, bool) {
+func (i *yamlInputIter) Next() (any, bool) {
 	if i.err != nil {
 		return nil, false
 	}
-	var v interface{}
+	var v any
 	if err := i.dec.Decode(&v); err != nil {
 		if err == io.EOF {
 			i.err = err
@@ -352,12 +352,12 @@ func newSlurpInputIter(iter inputIter) inputIter {
 	return &slurpInputIter{iter: iter}
 }
 
-func (i *slurpInputIter) Next() (interface{}, bool) {
+func (i *slurpInputIter) Next() (any, bool) {
 	if i.err != nil {
 		return nil, false
 	}
-	var vs []interface{}
-	var v interface{}
+	var vs []any
+	var v any
 	var ok bool
 	for {
 		v, ok = i.iter.Next()
@@ -395,7 +395,7 @@ func newReadAllIter(r io.Reader, fname string) inputIter {
 	return &readAllIter{r: r, fname: fname}
 }
 
-func (i *readAllIter) Next() (interface{}, bool) {
+func (i *readAllIter) Next() (any, bool) {
 	if i.err != nil {
 		return nil, false
 	}
@@ -425,12 +425,12 @@ func newSlurpRawInputIter(iter inputIter) inputIter {
 	return &slurpRawInputIter{iter: iter}
 }
 
-func (i *slurpRawInputIter) Next() (interface{}, bool) {
+func (i *slurpRawInputIter) Next() (any, bool) {
 	if i.err != nil {
 		return nil, false
 	}
 	var vs []string
-	var v interface{}
+	var v any
 	var ok bool
 	for {
 		v, ok = i.iter.Next()
diff --git a/cli/marshaler.go b/cli/marshaler.go
index 8b6ae9f..9c38e7a 100644
--- a/cli/marshaler.go
+++ b/cli/marshaler.go
@@ -7,14 +7,14 @@ import (
 )
 
 type marshaler interface {
-	marshal(interface{}, io.Writer) error
+	marshal(any, io.Writer) error
 }
 
 type rawMarshaler struct {
 	m marshaler
 }
 
-func (m *rawMarshaler) marshal(v interface{}, w io.Writer) error {
+func (m *rawMarshaler) marshal(v any, w io.Writer) error {
 	if s, ok := v.(string); ok {
 		_, err := w.Write([]byte(s))
 		return err
@@ -30,7 +30,7 @@ type yamlMarshaler struct {
 	indent *int
 }
 
-func (m *yamlMarshaler) marshal(v interface{}, w io.Writer) error {
+func (m *yamlMarshaler) marshal(v any, w io.Writer) error {
 	enc := yaml.NewEncoder(w)
 	if i := m.indent; i != nil {
 		enc.SetIndent(*i)
diff --git a/cli/stream.go b/cli/stream.go
index e647711..d9285cc 100644
--- a/cli/stream.go
+++ b/cli/stream.go
@@ -7,12 +7,12 @@ import (
 
 type jsonStream struct {
 	dec    *json.Decoder
-	path   []interface{}
+	path   []any
 	states []int
 }
 
 func newJSONStream(dec *json.Decoder) *jsonStream {
-	return &jsonStream{dec: dec, states: []int{jsonStateTopValue}, path: []interface{}{}}
+	return &jsonStream{dec: dec, states: []int{jsonStateTopValue}, path: []any{}}
 }
 
 const (
@@ -28,7 +28,7 @@ const (
 	jsonStateObjectEmptyEnd
 )
 
-func (s *jsonStream) next() (interface{}, error) {
+func (s *jsonStream) next() (any, error) {
 	switch s.states[len(s.states)-1] {
 	case jsonStateArrayEnd, jsonStateObjectEnd:
 		s.path = s.path[:len(s.path)-1]
@@ -71,17 +71,17 @@ func (s *jsonStream) next() (interface{}, error) {
 				if s.states[len(s.states)-1] == jsonStateArrayStart {
 					s.states[len(s.states)-1] = jsonStateArrayEmptyEnd
 					s.path = s.path[:len(s.path)-1]
-					return []interface{}{s.copyPath(), []interface{}{}}, nil
+					return []any{s.copyPath(), []any{}}, nil
 				}
 				s.states[len(s.states)-1] = jsonStateArrayEnd
-				return []interface{}{s.copyPath()}, nil
+				return []any{s.copyPath()}, nil
 			case '}':
 				if s.states[len(s.states)-1] == jsonStateObjectStart {
 					s.states[len(s.states)-1] = jsonStateObjectEmptyEnd
-					return []interface{}{s.copyPath(), map[string]interface{}{}}, nil
+					return []any{s.copyPath(), map[string]any{}}, nil
 				}
 				s.states[len(s.states)-1] = jsonStateObjectEnd
-				return []interface{}{s.copyPath()}, nil
+				return []any{s.copyPath()}, nil
 			default:
 				panic(d)
 			}
@@ -91,23 +91,23 @@ func (s *jsonStream) next() (interface{}, error) {
 				s.states[len(s.states)-1] = jsonStateArrayValue
 				fallthrough
 			case jsonStateArrayValue:
-				return []interface{}{s.copyPath(), token}, nil
+				return []any{s.copyPath(), token}, nil
 			case jsonStateObjectStart, jsonStateObjectValue:
 				s.states[len(s.states)-1] = jsonStateObjectKey
 				s.path = append(s.path, token)
 			case jsonStateObjectKey:
 				s.states[len(s.states)-1] = jsonStateObjectValue
-				return []interface{}{s.copyPath(), token}, nil
+				return []any{s.copyPath(), token}, nil
 			default:
 				s.states[len(s.states)-1] = jsonStateTopValue
-				return []interface{}{s.copyPath(), token}, nil
+				return []any{s.copyPath(), token}, nil
 			}
 		}
 	}
 }
 
-func (s *jsonStream) copyPath() []interface{} {
-	path := make([]interface{}, len(s.path))
+func (s *jsonStream) copyPath() []any {
+	path := make([]any, len(s.path))
 	copy(path, s.path)
 	return path
 }
diff --git a/cli/test.yaml b/cli/test.yaml
index 63fc028..4582944 100644
--- a/cli/test.yaml
+++ b/cli/test.yaml
@@ -1264,7 +1264,7 @@
     - 'has(0)'
   input: '{}'
   error: |
-    cannot check whether object ({}) has a key: number (0)
+    has(0) cannot be applied to: object ({})
 
 - name: in function for object
   args:
@@ -1296,7 +1296,7 @@
     - 'in([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])'
   input: '"x"'
   error: |
-    cannot check whether array ([0,0,0,0,0,0,0,0,0,0,0,0, ...]) has a key: string ("x")
+    has("x") cannot be applied to: array ([0,0,0,0,0,0,0,0,0,0,0,0, ...])
 
 - name: map function
   args:
@@ -1330,7 +1330,14 @@
     - 'from_entries'
   input: '[{"value":1}]'
   error: |
-    expected a string for object key but got: null
+    from_entries cannot be applied to [{"value":1}]: expected a string for object key but got: null
+
+- name: from_entries function key type error
+  args:
+    - 'from_entries'
+  input: '[{"key":{},"value":1}]'
+  error: |
+    from_entries cannot be applied to [{"key":{},"value":1}]: expected a string for object key but got: object ({})
 
 - name: with_entries function
   args:
@@ -1445,7 +1452,7 @@
     - 'flatten(-1)'
   input: '[]'
   error: |
-    flatten depth must not be negative: number (-1)
+    flatten depth should not be negative: -1
 
 - name: min, min_by, max, max_by functions
   args:
@@ -1709,12 +1716,12 @@
     ".e1"
     "-.e"
   expected: |
-    "invalid number: \"\""
-    "invalid number: \".\""
-    "invalid number: \" \""
-    "invalid number: \"1a\""
-    "invalid number: \".e1\""
-    "invalid number: \"-.e\""
+    "tonumber cannot be applied to \"\": invalid number"
+    "tonumber cannot be applied to \".\": invalid number"
+    "tonumber cannot be applied to \" \": invalid number"
+    "tonumber cannot be applied to \"1a\": invalid number"
+    "tonumber cannot be applied to \".e1\": invalid number"
+    "tonumber cannot be applied to \"-.e\": invalid number"
 
 - name: tostring function
   args:
@@ -1818,7 +1825,7 @@
     - 'nan | contains([nan])'
   input: '0'
   error: |
-    cannot check contains([null]): number (null)
+    contains([null]) cannot be applied to: number (null)
 
 - name: indices, index, rindex functions against null
   args:
@@ -1868,6 +1875,15 @@
     [0,1,3]
     [5,1,3]
 
+- name: indices, index, rindex functions type error
+  args:
+    - '(try indices([]) catch .), (try index([]) catch .), (try rindex([]) catch .)'
+  input: '{}'
+  expected: |
+    "indices([]) cannot be applied to: object ({})"
+    "index([]) cannot be applied to: object ({})"
+    "rindex([]) cannot be applied to: object ({})"
+
 - name: inside function
   args:
     - -c
@@ -1901,8 +1917,8 @@
     - '("x" | try startswith({}) catch .), (10 | try startswith("x") catch .)'
   input: '0'
   expected: |
-    "startswith cannot be applied to: object ({})"
-    "startswith cannot be applied to: number (10)"
+    "startswith({}) cannot be applied to: string (\"x\")"
+    "startswith(\"x\") cannot be applied to: number (10)"
 
 - name: endswith function
   args:
@@ -1925,8 +1941,8 @@
     - '("x" | try endswith({}) catch .), (10 | try endswith("x") catch .)'
   input: '0'
   expected: |
-    "endswith cannot be applied to: object ({})"
-    "endswith cannot be applied to: number (10)"
+    "endswith({}) cannot be applied to: string (\"x\")"
+    "endswith(\"x\") cannot be applied to: number (10)"
 
 - name: combinations/0 function
   args:
@@ -2084,18 +2100,18 @@
     - 'try join(",") catch .'
   input: '["1","2",[3,4,5]]'
   expected: |
-    "cannot join: array ([3,4,5])"
+    "join cannot be applied to an array including: array ([3,4,5])"
 
 - name: join function error input
   args:
     - '.[] | try join(",") catch .'
   input: '[null, false, true, 1, "a"]'
   expected: |
-    "join cannot be applied to: null"
-    "join cannot be applied to: boolean (false)"
-    "join cannot be applied to: boolean (true)"
-    "join cannot be applied to: number (1)"
-    "join cannot be applied to: string (\"a\")"
+    "join(\",\") cannot be applied to: null"
+    "join(\",\") cannot be applied to: boolean (false)"
+    "join(\",\") cannot be applied to: boolean (true)"
+    "join(\",\") cannot be applied to: number (1)"
+    "join(\",\") cannot be applied to: string (\"a\")"
 
 - name: join function non-string separator
   args:
@@ -2104,7 +2120,7 @@
   expected: |
     ""
     "1"
-    "join cannot be applied to: number (1)"
+    "join(1) cannot be applied to: array ([1,2])"
 
 - name: ascii_downcase function
   args:
@@ -2647,9 +2663,16 @@
 
 - name: multiply empty string
   args:
-    - '7 * ""'
+    - '(-9223372036854775808, -1, 0, 0.001, 0.999, 1, 7, 9223372036854775807) * ""'
   input: 'null'
   expected: |
+    null
+    null
+    null
+    ""
+    ""
+    ""
+    ""
     ""
 
 - name: multiply objects
@@ -3389,6 +3412,13 @@
     ["foo"]
     {"a":[1,2,3]}
 
+- name: fromjson function error
+  args:
+    - 'fromjson'
+  input: '"[0"'
+  error: |
+    fromjson cannot be applied to "[0": unexpected EOF
+
 - name: variable definition
   args:
     - -c
@@ -4200,49 +4230,49 @@
     - 'setpath([-1]; 10)'
   input: '[]'
   error: |
-    setpath cannot be applied to: number (-1)
+    setpath([-1]; 10) cannot be applied to []: array index should not be negative: -1
 
 - name: setpath function error
   args:
     - 'setpath(["a","b","c"]; 10)'
   input: '{"a":{"b":[]}}'
   error: |
-    expected an object but got: array ([])
+    setpath(["a","b","c"]; 10) cannot be applied to {"a":{"b":[]}}: expected an object but got: array ([])
 
 - name: setpath function error
   args:
     - 'setpath(["a",1]; 10)'
   input: '{"a":{"b":[]}}'
   error: |
-    expected an array but got: object ({"b":[]})
+    setpath(["a",1]; 10) cannot be applied to {"a":{"b":[]}}: expected an array but got: object ({"b":[]})
 
 - name: setpath function error
   args:
     - 'setpath([{}]; 10)'
   input: 'null'
   error: |
-    expected "start" and "end" for slicing but got: object ({})
+    setpath([{}]; 10) cannot be applied to null: expected "start" and "end" for slicing but got: object ({})
 
 - name: setpath function error
   args:
     - 'setpath([{start:0}]; 10)'
   input: 'null'
   error: |
-    expected "start" and "end" for slicing but got: object ({"start":0})
+    setpath([{"start":0}]; 10) cannot be applied to null: expected "start" and "end" for slicing but got: object ({"start":0})
 
 - name: setpath function error
   args:
     - 'setpath([[]]; 10)'
   input: '[]'
   error: |
-    expected a number for indexing an array but got: array ([])
+    setpath([[]]; 10) cannot be applied to []: expected a number for indexing an array but got: array ([])
 
 - name: setpath function error
   args:
     - 'setpath([{start:0,end:1}]; 10)'
   input: '[]'
   error: |
-    expected an array but got: number (10)
+    setpath([{"end":1,"start":0}]; 10) cannot be applied to []: expected an array but got: number (10)
 
 - name: delpaths function
   args:
@@ -4286,6 +4316,20 @@
     {"x":[]}
     {}
 
+- name: delpaths function error
+  args:
+    - 'delpaths([{}])'
+  input: '[]'
+  error: |
+    delpaths([{}]) cannot be applied to []: expected an array but got: object ({})
+
+- name: delpaths function error
+  args:
+    - 'delpaths([["x"]])'
+  input: '[]'
+  error: |
+    delpaths([["x"]]) cannot be applied to []: expected an object but got: array ([])
+
 - name: getpath function
   args:
     - -c
@@ -4307,7 +4351,7 @@
     - 'getpath(["a",1,"b","c"])'
   input: '{"a":[{},{"b":[1,2,3,4,5,6,7]}]}'
   error: |
-    cannot getpath with ["a",1,"b","c"] against: object ({"a":[{},{"b":[1,2,3,4,5, ...})
+    getpath(["a",1,"b","c"]) cannot be applied to {"a":[{},{"b":[1,2,3,4,5, ...}: expected an object but got: array ([1,2,3,4,5,6,7])
 
 - name: setpath, delpaths, getpath functions
   args:
@@ -4334,10 +4378,10 @@
   expected: |
     {"a":[{"b":5}]}
     {"a":[{"b":5}],"b":0}
-    "cannot getpath with [\"a\",0,\"b\"] against: object ({\"a\":0})"
+    "getpath([\"a\",0,\"b\"]) cannot be applied to: object ({\"a\":0})"
     {"a":[{"b":5}]}
-    "cannot getpath with [\"a\",0,\"b\"] against: object ({\"a\":[0,1]})"
-    "cannot getpath with [\"a\",0,\"b\"] against: object ({\"a\":{\"b\":1}})"
+    "getpath([\"a\",0,\"b\"]) cannot be applied to: object ({\"a\":[0,1]})"
+    "getpath([\"a\",0,\"b\"]) cannot be applied to {\"a\":{\"b\":1}}: expected an array but got: object ({\"b\":1})"
     {"a":[{"b":5}]}
     {"a":[{"b":5,"c":3}]}
 
@@ -4509,7 +4553,7 @@
   expected: |
     [{"x":{"y":{"z":{}}}},{"x":{}}]
 
-- name: assignment operator query
+- name: assignment operator with query value
   args:
     - -c
     - '.foo = .bar'
@@ -4517,7 +4561,7 @@
   expected: |
     {"bar":42,"foo":42}
 
-- name: assignment operator query with multiple paths and values
+- name: assignment operator with multiple paths and query values
   args:
     - -c
     - '(.foo,.bar,.baz) = .bar[]'
@@ -4527,12 +4571,35 @@
     {"bar":1,"baz":1,"foo":1}
     {"bar":2,"baz":2,"foo":2}
 
+- name: assignment operator with overlapping paths and multiple values
+  args:
+    - -c
+    - '.. = ..'
+  input: '{"x":{"y":{}}} [[[]]]'
+  expected: |
+    {"x":{"x":{"y":{}},"y":{"x":{"y":{}}}}}
+    {"x":{"y":{"y":{}}},"y":{}}
+    {"x":{"y":{}}}
+    [[[[[]]]]]
+    [[[[]]]]
+    [[[]]]
+
+- name: assignment operator with overlapping and slicing paths
+  args:
+    - -c
+    - '..[:0] = ..'
+  input: '[[[]]]'
+  expected: |
+    [[[[[]],[]],[]],[[]]]
+    [[[[]]],[[]]]
+    [[[]]]
+
 - name: assignment operator array index negative error
   args:
     - '.[-1,0] = 1'
   input: '[]'
   error: |
-    setpath cannot be applied to: number (-1)
+    setpath([-1]; 1) cannot be applied to []: array index should not be negative: -1
 
 - name: assignment operator array index limit error
   args:
@@ -5688,6 +5755,13 @@
     [{"captures":[{"length":1,"name":"foo","offset":2,"string":"c"},{"length":1,"name":null,"offset":3,"string":"d"}],"length":3,"offset":1,"string":"bcd"},{"captures":[{"length":1,"name":"foo","offset":9,"string":"c"},{"length":1,"name":null,"offset":10,"string":"d"}],"length":3,"offset":8,"string":"bcd"},{"captures":[{"length":1,"name":"foo","offset":16,"string":"C"},{"length":1,"name":null,"offset":17,"string":"D"}],"length":3,"offset":15,"string":"BCD"}]
     [{"captures":[{"length":0,"name":null,"offset":-1,"string":null},{"length":0,"name":null,"offset":-1,"string":null}],"length":3,"offset":1,"string":"bcd"}]
 
+- name: match function type error
+  args:
+    - 'match("x"; "g")'
+  input: '{}'
+  error: |
+    match("x"; "g") cannot be applied to: object ({})
+
 - name: match function flag error
   args:
     - 'match("x"; "a")'
@@ -5695,6 +5769,13 @@
   error: |
     unsupported regular expression flag: "a"
 
+- name: match function regular expression error
+  args:
+    - 'match("["; "g")'
+  input: '""'
+  error: |
+    invalid regular expression "[": error parsing regexp: missing closing ]: `[`
+
 - name: test function
   args:
     - -c
@@ -5876,6 +5957,22 @@
   expected: |
     "q=%5B%22%3C%3E%22%2C%22%7B%26%7D%22%5D&q=%5B%22%3C%3E%22%2C%22%7B%26%7D%22%2C%22%3C%3E%22%2C%22%7B%26%7D%22%5D"
 
+- name: format strings @urid
+  args:
+    - '@urid'
+  input: |
+    "%5B1%2C%7B%22foo%22%3A%22%3Cdiv%3E%26%27%5C%22%28%29%3C%2Fdiv%3E%22%7D%5D"
+  expected: |
+    "[1,{\"foo\":\"<div>&'\\\"()</div>\"}]"
+
+- name: format strings @urid error
+  args:
+    - '@urid'
+  input: |
+    "%5B1%2C%"
+  error: |
+    @urid cannot be applied to "%5B1%2C%": invalid URL escape "%"
+
 - name: format strings @csv
   args:
     - '@csv'
@@ -5996,6 +6093,14 @@
   expected: |
     "{\"foo\":\"bar\"}"
 
+- name: format strings @base64d error
+  args:
+    - '@base64d'
+  input: |
+    ":"
+  error: |
+    @base64d cannot be applied to ":": illegal base64 data at input byte 0
+
 - name: format strings not defined error
   args:
     - -n
diff --git a/cli/yaml.go b/cli/yaml.go
index f72f10d..652bdb2 100644
--- a/cli/yaml.go
+++ b/cli/yaml.go
@@ -6,23 +6,23 @@ import (
 )
 
 // Workaround for https://github.com/go-yaml/yaml/issues/139
-func normalizeYAML(v interface{}) interface{} {
+func normalizeYAML(v any) any {
 	switch v := v.(type) {
-	case map[interface{}]interface{}:
-		w := make(map[string]interface{}, len(v))
+	case map[any]any:
+		w := make(map[string]any, len(v))
 		for k, v := range v {
 			w[fmt.Sprint(k)] = normalizeYAML(v)
 		}
 		return w
 
-	case map[string]interface{}:
-		w := make(map[string]interface{}, len(v))
+	case map[string]any:
+		w := make(map[string]any, len(v))
 		for k, v := range v {
 			w[k] = normalizeYAML(v)
 		}
 		return w
 
-	case []interface{}:
+	case []any:
 		for i, w := range v {
 			v[i] = normalizeYAML(w)
 		}
diff --git a/code.go b/code.go
index efac134..33505bd 100644
--- a/code.go
+++ b/code.go
@@ -1,7 +1,7 @@
 package gojq
 
 type code struct {
-	v  interface{}
+	v  any
 	op opcode
 }
 
diff --git a/compare.go b/compare.go
index 89f0cdf..e70c1fb 100644
--- a/compare.go
+++ b/compare.go
@@ -8,14 +8,14 @@ import (
 // Compare l and r, and returns jq-flavored comparison value.
 // The result will be 0 if l == r, -1 if l < r, and +1 if l > r.
 // This comparison is used by built-in operators and functions.
-func Compare(l, r interface{}) int {
+func Compare(l, r any) int {
 	return compare(l, r)
 }
 
-func compare(l, r interface{}) int {
+func compare(l, r any) int {
 	return binopTypeSwitch(l, r,
 		compareInt,
-		func(l, r float64) interface{} {
+		func(l, r float64) any {
 			switch {
 			case l < r || math.IsNaN(l):
 				return -1
@@ -25,10 +25,10 @@ func compare(l, r interface{}) int {
 				return 1
 			}
 		},
-		func(l, r *big.Int) interface{} {
+		func(l, r *big.Int) any {
 			return l.Cmp(r)
 		},
-		func(l, r string) interface{} {
+		func(l, r string) any {
 			switch {
 			case l < r:
 				return -1
@@ -38,7 +38,7 @@ func compare(l, r interface{}) int {
 				return 1
 			}
 		},
-		func(l, r []interface{}) interface{} {
+		func(l, r []any) any {
 			n := len(l)
 			if len(r) < n {
 				n = len(r)
@@ -50,25 +50,25 @@ func compare(l, r interface{}) int {
 			}
 			return compareInt(len(l), len(r))
 		},
-		func(l, r map[string]interface{}) interface{} {
+		func(l, r map[string]any) any {
 			lk, rk := funcKeys(l), funcKeys(r)
 			if cmp := compare(lk, rk); cmp != 0 {
 				return cmp
 			}
-			for _, k := range lk.([]interface{}) {
+			for _, k := range lk.([]any) {
 				if cmp := compare(l[k.(string)], r[k.(string)]); cmp != 0 {
 					return cmp
 				}
 			}
 			return 0
 		},
-		func(l, r interface{}) interface{} {
+		func(l, r any) any {
 			return compareInt(typeIndex(l), typeIndex(r))
 		},
 	).(int)
 }
 
-func compareInt(l, r int) interface{} {
+func compareInt(l, r int) any {
 	switch {
 	case l < r:
 		return -1
@@ -79,7 +79,7 @@ func compareInt(l, r int) interface{} {
 	}
 }
 
-func typeIndex(v interface{}) int {
+func typeIndex(v any) int {
 	switch v := v.(type) {
 	default:
 		return 0
@@ -92,9 +92,9 @@ func typeIndex(v interface{}) int {
 		return 3
 	case string:
 		return 4
-	case []interface{}:
+	case []any:
 		return 5
-	case map[string]interface{}:
+	case map[string]any:
 		return 6
 	}
 }
diff --git a/compare_test.go b/compare_test.go
index e996037..f05e990 100644
--- a/compare_test.go
+++ b/compare_test.go
@@ -11,7 +11,7 @@ import (
 
 func TestCompare(t *testing.T) {
 	testCases := []struct {
-		l, r     interface{}
+		l, r     any
 		expected int
 	}{
 		{nil, nil, 0},
@@ -44,24 +44,24 @@ func TestCompare(t *testing.T) {
 		{"", "abc", -1},
 		{"abc", "", 1},
 		{"abc", "abc", 0},
-		{"", []interface{}{}, -1},
-		{[]interface{}{}, "", 1},
-		{[]interface{}{}, []interface{}{}, 0},
-		{[]interface{}{}, []interface{}{nil}, -1},
-		{[]interface{}{nil}, []interface{}{}, 1},
-		{[]interface{}{nil}, []interface{}{nil}, 0},
-		{[]interface{}{0, 1, 2}, []interface{}{0, 1, nil}, 1},
-		{[]interface{}{0, 1, 2}, []interface{}{0, 1, 2, nil}, -1},
-		{[]interface{}{0, 1, 2, false, nil}, []interface{}{0, 1, 2, nil, false}, 1},
-		{[]interface{}{}, map[string]interface{}{}, -1},
-		{map[string]interface{}{}, []interface{}{}, 1},
-		{map[string]interface{}{}, map[string]interface{}{}, 0},
-		{map[string]interface{}{"a": nil}, map[string]interface{}{"a": nil}, 0},
-		{map[string]interface{}{"a": nil}, map[string]interface{}{"a": nil, "b": nil}, -1},
-		{map[string]interface{}{"a": nil, "b": nil}, map[string]interface{}{"a": nil, "c": nil}, -1},
-		{map[string]interface{}{"a": 0, "b": 0, "c": 0}, map[string]interface{}{"a": 0, "b": 0, "c": 0}, 0},
-		{map[string]interface{}{"a": 0, "b": 0, "d": 0}, map[string]interface{}{"a": 0, "b": 1, "c": 0}, 1},
-		{map[string]interface{}{"a": 0, "b": 1, "c": 2}, map[string]interface{}{"a": 0, "b": 2, "c": 1}, -1},
+		{"", []any{}, -1},
+		{[]any{}, "", 1},
+		{[]any{}, []any{}, 0},
+		{[]any{}, []any{nil}, -1},
+		{[]any{nil}, []any{}, 1},
+		{[]any{nil}, []any{nil}, 0},
+		{[]any{0, 1, 2}, []any{0, 1, nil}, 1},
+		{[]any{0, 1, 2}, []any{0, 1, 2, nil}, -1},
+		{[]any{0, 1, 2, false, nil}, []any{0, 1, 2, nil, false}, 1},
+		{[]any{}, map[string]any{}, -1},
+		{map[string]any{}, []any{}, 1},
+		{map[string]any{}, map[string]any{}, 0},
+		{map[string]any{"a": nil}, map[string]any{"a": nil}, 0},
+		{map[string]any{"a": nil}, map[string]any{"a": nil, "b": nil}, -1},
+		{map[string]any{"a": nil, "b": nil}, map[string]any{"a": nil, "c": nil}, -1},
+		{map[string]any{"a": 0, "b": 0, "c": 0}, map[string]any{"a": 0, "b": 0, "c": 0}, 0},
+		{map[string]any{"a": 0, "b": 0, "d": 0}, map[string]any{"a": 0, "b": 1, "c": 0}, 1},
+		{map[string]any{"a": 0, "b": 1, "c": 2}, map[string]any{"a": 0, "b": 2, "c": 1}, -1},
 	}
 	for _, tc := range testCases {
 		t.Run(fmt.Sprintf("%v,%v", tc.l, tc.r), func(t *testing.T) {
diff --git a/compiler.go b/compiler.go
index c750c47..de5f9a1 100644
--- a/compiler.go
+++ b/compiler.go
@@ -35,12 +35,12 @@ type Code struct {
 //
 // It is safe to call this method in goroutines, to reuse a compiled [*Code].
 // But for arguments, do not give values sharing same data between goroutines.
-func (c *Code) Run(v interface{}, values ...interface{}) Iter {
+func (c *Code) Run(v any, values ...any) Iter {
 	return c.RunWithContext(context.Background(), v, values...)
 }
 
 // RunWithContext runs the code with context.
-func (c *Code) RunWithContext(ctx context.Context, v interface{}, values ...interface{}) Iter {
+func (c *Code) RunWithContext(ctx context.Context, v any, values ...any) Iter {
 	if len(values) > len(c.variables) {
 		return NewIter(&tooManyVariableValuesError{})
 	} else if len(values) < len(c.variables) {
@@ -144,15 +144,15 @@ func (c *compiler) compileImport(i *Import) error {
 		return fmt.Errorf("cannot load module: %q", path)
 	}
 	if strings.HasPrefix(alias, "$") {
-		var vals interface{}
+		var vals any
 		if moduleLoader, ok := c.moduleLoader.(interface {
-			LoadJSONWithMeta(string, map[string]interface{}) (interface{}, error)
+			LoadJSONWithMeta(string, map[string]any) (any, error)
 		}); ok {
 			if vals, err = moduleLoader.LoadJSONWithMeta(path, i.Meta.ToValue()); err != nil {
 				return err
 			}
 		} else if moduleLoader, ok := c.moduleLoader.(interface {
-			LoadJSON(string) (interface{}, error)
+			LoadJSON(string) (any, error)
 		}); ok {
 			if vals, err = moduleLoader.LoadJSON(path); err != nil {
 				return err
@@ -169,7 +169,7 @@ func (c *compiler) compileImport(i *Import) error {
 	}
 	var q *Query
 	if moduleLoader, ok := c.moduleLoader.(interface {
-		LoadModuleWithMeta(string, map[string]interface{}) (*Query, error)
+		LoadModuleWithMeta(string, map[string]any) (*Query, error)
 	}); ok {
 		if q, err = moduleLoader.LoadModuleWithMeta(path, i.Meta.ToValue()); err != nil {
 			return err
@@ -498,7 +498,7 @@ func (c *compiler) compileQueryUpdate(l, r *Query, op Operator) error {
 			}
 			c.append(&code{op: oppush, v: xs})
 			c.append(&code{op: opload, v: v})
-			c.append(&code{op: opcall, v: [3]interface{}{internalFuncs["setpath"].callback, 2, "setpath"}})
+			c.append(&code{op: opcall, v: [3]any{internalFuncs["setpath"].callback, 2, "setpath"}})
 			return nil
 		}
 		fallthrough
@@ -625,7 +625,7 @@ func (c *compiler) compilePattern(vs [][2]int, p *Pattern) ([][2]int, error) {
 				c.append(&code{op: opload, v: v})
 				c.append(&code{op: oppush, v: nil})
 				// ref: compileCall
-				c.append(&code{op: opcall, v: [3]interface{}{internalFuncs["_index"].callback, 2, "_index"}})
+				c.append(&code{op: opcall, v: [3]any{internalFuncs["_index"].callback, 2, "_index"}})
 			}
 			if name != "" {
 				if kv.Val != nil {
@@ -800,12 +800,12 @@ func (c *compiler) compileBreak(label string) error {
 	}
 	c.append(&code{op: oppop})
 	c.append(&code{op: opload, v: v})
-	c.append(&code{op: opcall, v: [3]interface{}{funcBreak(label), 0, "_break"}})
+	c.append(&code{op: opcall, v: [3]any{funcBreak(label), 0, "_break"}})
 	return nil
 }
 
-func funcBreak(label string) func(interface{}, []interface{}) interface{} {
-	return func(v interface{}, _ []interface{}) interface{} {
+func funcBreak(label string) func(any, []any) any {
+	return func(v any, _ []any) any {
 		return &breakError{label, v}
 	}
 }
@@ -907,7 +907,7 @@ func (c *compiler) compileFunc(e *Func) error {
 			}
 			return nil
 		} else if e.Name == "$ENV" || e.Name == "env" {
-			env := make(map[string]interface{})
+			env := make(map[string]any)
 			if c.environLoader != nil {
 				for _, kv := range c.environLoader() {
 					if i := strings.IndexByte(kv, '='); i > 0 {
@@ -968,7 +968,7 @@ func (c *compiler) compileFunc(e *Func) error {
 			return nil
 		case "builtins":
 			return c.compileCallInternal(
-				[3]interface{}{c.funcBuiltins, 0, e.Name},
+				[3]any{c.funcBuiltins, 0, e.Name},
 				e.Args,
 				true,
 				-1,
@@ -978,14 +978,14 @@ func (c *compiler) compileFunc(e *Func) error {
 				return &inputNotAllowedError{}
 			}
 			return c.compileCallInternal(
-				[3]interface{}{c.funcInput, 0, e.Name},
+				[3]any{c.funcInput, 0, e.Name},
 				e.Args,
 				true,
 				-1,
 			)
 		case "modulemeta":
 			return c.compileCallInternal(
-				[3]interface{}{c.funcModulemeta, 0, e.Name},
+				[3]any{c.funcModulemeta, 0, e.Name},
 				e.Args,
 				true,
 				-1,
@@ -996,7 +996,7 @@ func (c *compiler) compileFunc(e *Func) error {
 	}
 	if fn, ok := c.customFuncs[e.Name]; ok && fn.accept(len(e.Args)) {
 		if err := c.compileCallInternal(
-			[3]interface{}{fn.callback, len(e.Args), e.Name},
+			[3]any{fn.callback, len(e.Args), e.Name},
 			e.Args,
 			true,
 			-1,
@@ -1023,9 +1023,10 @@ func (c *compiler) compileAssign() {
 	scope := c.newScope()
 	v, p := [2]int{scope.id, 0}, [2]int{scope.id, 1}
 	x, a := [2]int{scope.id, 2}, [2]int{scope.id, 3}
-	q := [2]int{scope.id, 4} // Cannot reuse p due to backtracking in x.
+	// Cannot reuse v, p due to backtracking in x.
+	w, q := [2]int{scope.id, 4}, [2]int{scope.id, 5}
 	c.appends(
-		&code{op: opscope, v: [3]int{scope.id, 5, 2}},
+		&code{op: opscope, v: [3]int{scope.id, 6, 2}},
 		&code{op: opstore, v: v}, //                def _assign(p; $x):
 		&code{op: opstore, v: p},
 		&code{op: opstore, v: x},
@@ -1036,25 +1037,27 @@ func (c *compiler) compileAssign() {
 		&code{op: opstore, v: x},
 		&code{op: opexpend},
 		&code{op: oppush, v: nil},
-		&code{op: opcall, v: [3]interface{}{funcAllocator, 0, "_allocator"}},
+		&code{op: opcall, v: [3]any{funcAllocator, 0, "_allocator"}},
 		&code{op: opstore, v: a},
 		&code{op: opload, v: v},
-		&code{op: opfork, v: len(c.codes) + 28}, // reduce [L1]
-		&code{op: oppathbegin},                  // path(p)
+		&code{op: opfork, v: len(c.codes) + 30}, // reduce [L1]
+		&code{op: opdup},
+		&code{op: opstore, v: w},
+		&code{op: oppathbegin}, // path(p)
 		&code{op: opload, v: p},
 		&code{op: opcallpc},
-		&code{op: opload, v: v},
+		&code{op: opload, v: w},
 		&code{op: oppathend},
 		&code{op: opstore, v: q}, //                as $q (.;
 		&code{op: opload, v: a},  //                setpath($q; $x)
 		&code{op: opload, v: x},
 		&code{op: opload, v: q},
-		&code{op: opload, v: v},
-		&code{op: opcall, v: [3]interface{}{funcSetpathWithAllocator, 3, "_setpath"}},
-		&code{op: opstore, v: v},
+		&code{op: opload, v: w},
+		&code{op: opcall, v: [3]any{funcSetpathWithAllocator, 3, "_setpath"}},
+		&code{op: opstore, v: w},
 		&code{op: opbacktrack}, //                  );
 		&code{op: oppop},       //                  [L1]
-		&code{op: opload, v: v},
+		&code{op: opload, v: w},
 		&code{op: opret},
 	)
 }
@@ -1072,10 +1075,10 @@ func (c *compiler) compileModify() {
 		&code{op: opstore, v: v}, //                def _modify(p; f):
 		&code{op: opstore, v: p},
 		&code{op: opstore, v: f},
-		&code{op: oppush, v: []interface{}{}},
+		&code{op: oppush, v: []any{}},
 		&code{op: opstore, v: d},
 		&code{op: oppush, v: nil},
-		&code{op: opcall, v: [3]interface{}{funcAllocator, 0, "_allocator"}},
+		&code{op: opcall, v: [3]any{funcAllocator, 0, "_allocator"}},
 		&code{op: opstore, v: a},
 		&code{op: opload, v: v},
 		&code{op: opfork, v: len(c.codes) + 39}, // reduce [L1]
@@ -1092,18 +1095,18 @@ func (c *compiler) compileModify() {
 		&code{op: opload, v: a},
 		&code{op: opload, v: p},
 		&code{op: opload, v: v},
-		&code{op: opcall, v: [3]interface{}{internalFuncs["getpath"].callback, 1, "getpath"}},
+		&code{op: opcall, v: [3]any{internalFuncs["getpath"].callback, 1, "getpath"}},
 		&code{op: opload, v: f}, //                 f)
 		&code{op: opcallpc},
 		&code{op: opload, v: p}, //                 setpath($p; ...)
 		&code{op: opload, v: v},
-		&code{op: opcall, v: [3]interface{}{funcSetpathWithAllocator, 3, "_setpath"}},
+		&code{op: opcall, v: [3]any{funcSetpathWithAllocator, 3, "_setpath"}},
 		&code{op: opstore, v: v},
 		&code{op: opload, v: v},                 // ., break $l
 		&code{op: opfork, v: len(c.codes) + 34}, // [L4]
 		&code{op: opjump, v: len(c.codes) + 38}, // [L3]
 		&code{op: opload, v: l},                 // [L4]
-		&code{op: opcall, v: [3]interface{}{funcBreak(""), 0, "_break"}},
+		&code{op: opcall, v: [3]any{funcBreak(""), 0, "_break"}},
 		&code{op: opload, v: p},   //               append $p to $d [L2]
 		&code{op: opappend, v: d}, //
 		&code{op: opbacktrack},    //               ) |           [L3]
@@ -1111,12 +1114,12 @@ func (c *compiler) compileModify() {
 		&code{op: opload, v: a},
 		&code{op: opload, v: d},
 		&code{op: opload, v: v},
-		&code{op: opcall, v: [3]interface{}{funcDelpathsWithAllocator, 2, "_delpaths"}},
+		&code{op: opcall, v: [3]any{funcDelpathsWithAllocator, 2, "_delpaths"}},
 		&code{op: opret},
 	)
 }
 
-func (c *compiler) funcBuiltins(interface{}, []interface{}) interface{} {
+func (c *compiler) funcBuiltins(any, []any) any {
 	type funcNameArity struct {
 		name  string
 		arity int
@@ -1151,14 +1154,14 @@ func (c *compiler) funcBuiltins(interface{}, []interface{}) interface{} {
 		return xs[i].name < xs[j].name ||
 			xs[i].name == xs[j].name && xs[i].arity < xs[j].arity
 	})
-	ys := make([]interface{}, len(xs))
+	ys := make([]any, len(xs))
 	for i, x := range xs {
 		ys[i] = x.name + "/" + strconv.Itoa(x.arity)
 	}
 	return ys
 }
 
-func (c *compiler) funcInput(interface{}, []interface{}) interface{} {
+func (c *compiler) funcInput(any, []any) any {
 	v, ok := c.inputIter.Next()
 	if !ok {
 		return errors.New("break")
@@ -1166,10 +1169,10 @@ func (c *compiler) funcInput(interface{}, []interface{}) interface{} {
 	return normalizeNumbers(v)
 }
 
-func (c *compiler) funcModulemeta(v interface{}, _ []interface{}) interface{} {
+func (c *compiler) funcModulemeta(v any, _ []any) any {
 	s, ok := v.(string)
 	if !ok {
-		return &funcTypeError{"modulemeta", v}
+		return &func0TypeError{"modulemeta", v}
 	}
 	if c.moduleLoader == nil {
 		return fmt.Errorf("cannot load module: %q", s)
@@ -1177,7 +1180,7 @@ func (c *compiler) funcModulemeta(v interface{}, _ []interface{}) interface{} {
 	var q *Query
 	var err error
 	if moduleLoader, ok := c.moduleLoader.(interface {
-		LoadModuleWithMeta(string, map[string]interface{}) (*Query, error)
+		LoadModuleWithMeta(string, map[string]any) (*Query, error)
 	}); ok {
 		if q, err = moduleLoader.LoadModuleWithMeta(s, nil); err != nil {
 			return err
@@ -1191,13 +1194,13 @@ func (c *compiler) funcModulemeta(v interface{}, _ []interface{}) interface{} {
 	}
 	meta := q.Meta.ToValue()
 	if meta == nil {
-		meta = make(map[string]interface{})
+		meta = make(map[string]any)
 	}
-	var deps []interface{}
+	deps := []any{}
 	for _, i := range q.Imports {
 		v := i.Meta.ToValue()
 		if v == nil {
-			v = make(map[string]interface{})
+			v = make(map[string]any)
 		} else {
 			for k := range v {
 				// dirty hack to remove the internal fields
@@ -1227,7 +1230,7 @@ func (c *compiler) funcModulemeta(v interface{}, _ []interface{}) interface{} {
 func (c *compiler) compileObject(e *Object) error {
 	c.appendCodeInfo(e)
 	if len(e.KeyVals) == 0 {
-		c.append(&code{op: opconst, v: map[string]interface{}{}})
+		c.append(&code{op: opconst, v: map[string]any{}})
 		return nil
 	}
 	defer c.newScopeDepth()()
@@ -1252,7 +1255,7 @@ func (c *compiler) compileObject(e *Object) error {
 			return nil
 		}
 	}
-	w := make(map[string]interface{}, l)
+	w := make(map[string]any, l)
 	for i := 0; i < l; i++ {
 		w[c.codes[pc+i*3].v.(string)] = c.codes[pc+i*3+2].v
 	}
@@ -1295,7 +1298,7 @@ func (c *compiler) compileObjectKeyVal(v [2]int, kv *ObjectKeyVal) error {
 				c.append(&code{op: opload, v: v})
 				c.append(&code{op: oppush, v: nil})
 				// ref: compileCall
-				c.append(&code{op: opcall, v: [3]interface{}{internalFuncs["_index"].callback, 2, "_index"}})
+				c.append(&code{op: opcall, v: [3]any{internalFuncs["_index"].callback, 2, "_index"}})
 			}
 		}
 	} else if kv.KeyQuery != nil {
@@ -1320,10 +1323,10 @@ func (c *compiler) compileObjectKeyVal(v [2]int, kv *ObjectKeyVal) error {
 func (c *compiler) compileArray(e *Array) error {
 	c.appendCodeInfo(e)
 	if e.Query == nil {
-		c.append(&code{op: opconst, v: []interface{}{}})
+		c.append(&code{op: opconst, v: []any{}})
 		return nil
 	}
-	c.append(&code{op: oppush, v: []interface{}{}})
+	c.append(&code{op: oppush, v: []any{}})
 	arr := c.newVariable()
 	c.append(&code{op: opstore, v: arr})
 	pc := len(c.codes)
@@ -1354,7 +1357,7 @@ func (c *compiler) compileArray(e *Array) error {
 			return nil
 		}
 	}
-	v := make([]interface{}, l)
+	v := make([]any, l)
 	for i := 0; i < l; i++ {
 		v[i] = c.codes[pc+i*2+l].v
 	}
@@ -1382,12 +1385,12 @@ func (c *compiler) compileUnary(e *Unary) error {
 	}
 }
 
-func (c *compiler) compileFormat(fmt string, str *String) error {
-	f := formatToFunc(fmt)
+func (c *compiler) compileFormat(format string, str *String) error {
+	f := formatToFunc(format)
 	if f == nil {
 		f = &Func{
 			Name: "format",
-			Args: []*Query{{Term: &Term{Type: TermTypeString, Str: &String{Str: fmt[1:]}}}},
+			Args: []*Query{{Term: &Term{Type: TermTypeString, Str: &String{Str: format[1:]}}}},
 		}
 	}
 	if str == nil {
@@ -1396,8 +1399,8 @@ func (c *compiler) compileFormat(fmt string, str *String) error {
 	return c.compileString(str, f)
 }
 
-func formatToFunc(fmt string) *Func {
-	switch fmt {
+func formatToFunc(format string) *Func {
+	switch format {
 	case "@text":
 		return &Func{Name: "tostring"}
 	case "@json":
@@ -1406,6 +1409,8 @@ func formatToFunc(fmt string) *Func {
 		return &Func{Name: "_tohtml"}
 	case "@uri":
 		return &Func{Name: "_touri"}
+	case "@urid":
+		return &Func{Name: "_tourid"}
 	case "@csv":
 		return &Func{Name: "_tocsv"}
 	case "@tsv":
@@ -1483,7 +1488,7 @@ func (c *compiler) compileCall(name string, args []*Query) error {
 		indexing = -1
 	}
 	if err := c.compileCallInternal(
-		[3]interface{}{fn.callback, len(args), name},
+		[3]any{fn.callback, len(args), name},
 		args,
 		true,
 		indexing,
@@ -1501,7 +1506,7 @@ func (c *compiler) compileCallPc(fn *funcinfo, args []*Query) error {
 }
 
 func (c *compiler) compileCallInternal(
-	fn interface{}, args []*Query, internal bool, indexing int,
+	fn any, args []*Query, internal bool, indexing int,
 ) error {
 	if len(args) == 0 {
 		c.append(&code{op: opcall, v: fn})
diff --git a/compiler_test.go b/compiler_test.go
index d495c7d..d12240a 100644
--- a/compiler_test.go
+++ b/compiler_test.go
@@ -23,12 +23,12 @@ func ExampleCompile() {
 	if err != nil {
 		log.Fatalln(err)
 	}
-	iter := code.Run([]interface{}{
+	iter := code.Run([]any{
 		nil,
 		"string",
 		42,
-		[]interface{}{"foo"},
-		map[string]interface{}{"foo": 42},
+		[]any{"foo"},
+		map[string]any{"foo": 42},
 	})
 	for {
 		v, ok := iter.Next()
@@ -59,7 +59,7 @@ func ExampleCode_Run() {
 	if err != nil {
 		log.Fatalln(err)
 	}
-	input := map[string]interface{}{"foo": 42}
+	input := map[string]any{"foo": 42}
 	iter := code.Run(input)
 	for {
 		v, ok := iter.Next()
@@ -123,8 +123,8 @@ func TestCodeCompile_OptimizeConstants(t *testing.T) {
 		if !ok {
 			break
 		}
-		if expected := []interface{}{
-			1, map[string]interface{}{"foo": 2, "bar": 3}, []interface{}{-4},
+		if expected := []any{
+			1, map[string]any{"foo": 2, "bar": 3}, []any{-4},
 		}; !reflect.DeepEqual(got, expected) {
 			t.Errorf("expected: %v, got: %v", expected, got)
 		}
@@ -175,10 +175,10 @@ func TestCodeCompile_OptimizeIndexSliceAssign(t *testing.T) {
 		if !ok {
 			break
 		}
-		if expected := map[string]interface{}{
-			"foo": map[string]interface{}{
-				"bar": map[string]interface{}{
-					"baz": []interface{}{map[string]interface{}{"": []interface{}{0}}},
+		if expected := map[string]any{
+			"foo": map[string]any{
+				"bar": map[string]any{
+					"baz": []any{map[string]any{"": []any{0}}},
 				},
 			},
 		}; !reflect.DeepEqual(got, expected) {
@@ -260,7 +260,7 @@ func TestCodeCompile_OptimizeJumps(t *testing.T) {
 		t.Errorf("expected: %v, got: %v", expected, got)
 	}
 	v := codes.Index(1).Elem().FieldByName("v")
-	if got, expected := *(*interface{})(unsafe.Pointer(v.UnsafeAddr())), 13; expected != got {
+	if got, expected := *(*any)(unsafe.Pointer(v.UnsafeAddr())), 13; expected != got {
 		t.Errorf("expected: %v, got: %v", expected, got)
 	}
 	iter := code.Run(nil)
diff --git a/debian/changelog b/debian/changelog
index d0a036f..7c7c697 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+gojq (0.12.13-1) UNRELEASED; urgency=low
+
+  * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Thu, 01 Jun 2023 17:51:50 -0000
+
 gojq (0.12.11-1) unstable; urgency=medium
 
   * New upstream version 0.12.11
diff --git a/debug.go b/debug.go
index 2e63908..ad3d721 100644
--- a/debug.go
+++ b/debug.go
@@ -32,7 +32,7 @@ type codeinfo struct {
 	pc   int
 }
 
-func (c *compiler) appendCodeInfo(x interface{}) {
+func (c *compiler) appendCodeInfo(x any) {
 	if !debug {
 		return
 	}
@@ -182,7 +182,7 @@ func debugOperand(c *code) string {
 		switch v := c.v.(type) {
 		case int:
 			return strconv.Itoa(v)
-		case [3]interface{}:
+		case [3]any:
 			return fmt.Sprintf("%s/%d", v[2], v[1])
 		default:
 			panic(c)
@@ -192,7 +192,7 @@ func debugOperand(c *code) string {
 	}
 }
 
-func debugValue(v interface{}) string {
+func debugValue(v any) string {
 	switch v := v.(type) {
 	case Iter:
 		return fmt.Sprintf("gojq.Iter(%#v)", v)
@@ -202,7 +202,7 @@ func debugValue(v interface{}) string {
 		return fmt.Sprintf("[%d,%d]", v[0], v[1])
 	case [3]int:
 		return fmt.Sprintf("[%d,%d,%d]", v[0], v[1], v[2])
-	case [3]interface{}:
+	case [3]any:
 		return fmt.Sprintf("[%v,%v,%v]", v[0], v[1], v[2])
 	case allocator:
 		return fmt.Sprintf("%v", v)
diff --git a/encoder.go b/encoder.go
index d61456c..3233e8a 100644
--- a/encoder.go
+++ b/encoder.go
@@ -15,19 +15,19 @@ import (
 // Marshal returns the jq-flavored JSON encoding of v.
 //
 // This method accepts only limited types (nil, bool, int, float64, *big.Int,
-// string, []interface{}, and map[string]interface{}) because these are the
-// possible types a gojq iterator can emit. This method marshals NaN to null,
-// truncates infinities to (+|-) math.MaxFloat64, uses \b and \f in strings,
-// and does not escape '<', '>', '&', '\u2028', and '\u2029'. These behaviors
-// are based on the marshaler of jq command, and different from json.Marshal in
-// the Go standard library. Note that the result is not safe to embed in HTML.
-func Marshal(v interface{}) ([]byte, error) {
+// string, []any, and map[string]any) because these are the possible types a
+// gojq iterator can emit. This method marshals NaN to null, truncates
+// infinities to (+|-) math.MaxFloat64, uses \b and \f in strings, and does not
+// escape '<', '>', '&', '\u2028', and '\u2029'. These behaviors are based on
+// the marshaler of jq command, and different from json.Marshal in the Go
+// standard library. Note that the result is not safe to embed in HTML.
+func Marshal(v any) ([]byte, error) {
 	var b bytes.Buffer
 	(&encoder{w: &b}).encode(v)
 	return b.Bytes(), nil
 }
 
-func jsonMarshal(v interface{}) string {
+func jsonMarshal(v any) string {
 	var sb strings.Builder
 	(&encoder{w: &sb}).encode(v)
 	return sb.String()
@@ -46,7 +46,7 @@ type encoder struct {
 	buf [64]byte
 }
 
-func (e *encoder) encode(v interface{}) {
+func (e *encoder) encode(v any) {
 	switch v := v.(type) {
 	case nil:
 		e.w.WriteString("null")
@@ -64,10 +64,10 @@ func (e *encoder) encode(v interface{}) {
 		e.w.Write(v.Append(e.buf[:0], 10))
 	case string:
 		e.encodeString(v)
-	case []interface{}:
+	case []any:
 		e.encodeArray(v)
-	case map[string]interface{}:
-		e.encodeMap(v)
+	case map[string]any:
+		e.encodeObject(v)
 	default:
 		panic(fmt.Sprintf("invalid type: %[1]T (%[1]v)", v))
 	}
@@ -84,12 +84,12 @@ func (e *encoder) encodeFloat64(f float64) {
 	} else if f <= -math.MaxFloat64 {
 		f = -math.MaxFloat64
 	}
-	fmt := byte('f')
+	format := byte('f')
 	if x := math.Abs(f); x != 0 && x < 1e-6 || x >= 1e21 {
-		fmt = 'e'
+		format = 'e'
 	}
-	buf := strconv.AppendFloat(e.buf[:0], f, fmt, -1, 64)
-	if fmt == 'e' {
+	buf := strconv.AppendFloat(e.buf[:0], f, format, -1, 64)
+	if format == 'e' {
 		// clean up e-09 to e-9
 		if n := len(buf); n >= 4 && buf[n-4] == 'e' && buf[n-3] == '-' && buf[n-2] == '0' {
 			buf[n-2] = buf[n-1]
@@ -155,7 +155,7 @@ func (e *encoder) encodeString(s string) {
 	e.w.WriteByte('"')
 }
 
-func (e *encoder) encodeArray(vs []interface{}) {
+func (e *encoder) encodeArray(vs []any) {
 	e.w.WriteByte('[')
 	for i, v := range vs {
 		if i > 0 {
@@ -166,11 +166,11 @@ func (e *encoder) encodeArray(vs []interface{}) {
 	e.w.WriteByte(']')
 }
 
-func (e *encoder) encodeMap(vs map[string]interface{}) {
+func (e *encoder) encodeObject(vs map[string]any) {
 	e.w.WriteByte('{')
 	type keyVal struct {
 		key string
-		val interface{}
+		val any
 	}
 	kvs := make([]keyVal, len(vs))
 	var i int
diff --git a/encoder_test.go b/encoder_test.go
index 5d9d2b7..1d1247e 100644
--- a/encoder_test.go
+++ b/encoder_test.go
@@ -11,7 +11,7 @@ import (
 
 func TestMarshal(t *testing.T) {
 	testCases := []struct {
-		value    interface{}
+		value    any
 		expected string
 	}{
 		{
@@ -19,26 +19,26 @@ func TestMarshal(t *testing.T) {
 			expected: "null",
 		},
 		{
-			value:    []interface{}{false, true},
+			value:    []any{false, true},
 			expected: "[false,true]",
 		},
 		{
-			value: []interface{}{
+			value: []any{
 				42, 3.14, 1e-6, 1e-7, -1e-9, 1e-10, math.NaN(), math.Inf(1), math.Inf(-1),
 				new(big.Int).SetBytes([]byte("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff")),
 			},
 			expected: "[42,3.14,0.000001,1e-7,-1e-9,1e-10,null,1.7976931348623157e+308,-1.7976931348623157e+308,340282366920938463463374607431768211455]",
 		},
 		{
-			value:    []interface{}{"", "abcde", "foo\x00\x1f\r\n\t\f\b<=>!\"#$%'& \\\x7fbar"},
+			value:    []any{"", "abcde", "foo\x00\x1f\r\n\t\f\b<=>!\"#$%'& \\\x7fbar"},
 			expected: `["","abcde","foo\u0000\u001f\r\n\t\f\b<=>!\"#$%'& \\\u007fbar"]`,
 		},
 		{
-			value:    []interface{}{1, []interface{}{2, []interface{}{3, []interface{}{map[string]interface{}{}}}}},
+			value:    []any{1, []any{2, []any{3, []any{map[string]any{}}}}},
 			expected: `[1,[2,[3,[{}]]]]`,
 		},
 		{
-			value:    map[string]interface{}{"x": []interface{}{100}, "y": map[string]interface{}{"z": 42}},
+			value:    map[string]any{"x": []any{100}, "y": map[string]any{"z": 42}},
 			expected: `{"x":[100],"y":{"z":42}}`,
 		},
 	}
diff --git a/env.go b/env.go
index dd1859c..bf058ed 100644
--- a/env.go
+++ b/env.go
@@ -7,7 +7,7 @@ type env struct {
 	stack     *stack
 	paths     *stack
 	scopes    *scopeStack
-	values    []interface{}
+	values    []any
 	codes     []*code
 	codeinfos []codeinfo
 	forks     []fork
@@ -15,7 +15,7 @@ type env struct {
 	offset    int
 	expdepth  int
 	label     int
-	args      [32]interface{} // len(env.args) > maxarity
+	args      [32]any // len(env.args) > maxarity
 	ctx       context.Context
 }
 
diff --git a/error.go b/error.go
index e128b54..1686587 100644
--- a/error.go
+++ b/error.go
@@ -8,11 +8,11 @@ import "strconv"
 // Refer to [WithFunction] to add a custom internal function.
 type ValueError interface {
 	error
-	Value() interface{}
+	Value() any
 }
 
 type expectedObjectError struct {
-	v interface{}
+	v any
 }
 
 func (err *expectedObjectError) Error() string {
@@ -20,31 +20,31 @@ func (err *expectedObjectError) Error() string {
 }
 
 type expectedArrayError struct {
-	v interface{}
+	v any
 }
 
 func (err *expectedArrayError) Error() string {
 	return "expected an array but got: " + typeErrorPreview(err.v)
 }
 
-type expectedStringError struct {
-	v interface{}
+type iteratorError struct {
+	v any
 }
 
-func (err *expectedStringError) Error() string {
-	return "expected a string but got: " + typeErrorPreview(err.v)
+func (err *iteratorError) Error() string {
+	return "cannot iterate over: " + typeErrorPreview(err.v)
 }
 
-type iteratorError struct {
-	v interface{}
+type arrayIndexNegativeError struct {
+	v int
 }
 
-func (err *iteratorError) Error() string {
-	return "cannot iterate over: " + typeErrorPreview(err.v)
+func (err *arrayIndexNegativeError) Error() string {
+	return "array index should not be negative: " + Preview(err.v)
 }
 
 type arrayIndexTooLargeError struct {
-	v interface{}
+	v any
 }
 
 func (err *arrayIndexTooLargeError) Error() string {
@@ -52,7 +52,7 @@ func (err *arrayIndexTooLargeError) Error() string {
 }
 
 type objectKeyNotStringError struct {
-	v interface{}
+	v any
 }
 
 func (err *objectKeyNotStringError) Error() string {
@@ -60,7 +60,7 @@ func (err *objectKeyNotStringError) Error() string {
 }
 
 type arrayIndexNotNumberError struct {
-	v interface{}
+	v any
 }
 
 func (err *arrayIndexNotNumberError) Error() string {
@@ -68,7 +68,7 @@ func (err *arrayIndexNotNumberError) Error() string {
 }
 
 type stringIndexNotNumberError struct {
-	v interface{}
+	v any
 }
 
 func (err *stringIndexNotNumberError) Error() string {
@@ -76,20 +76,17 @@ func (err *stringIndexNotNumberError) Error() string {
 }
 
 type expectedStartEndError struct {
-	v interface{}
+	v any
 }
 
 func (err *expectedStartEndError) Error() string {
 	return `expected "start" and "end" for slicing but got: ` + typeErrorPreview(err.v)
 }
 
-type lengthMismatchError struct {
-	name string
-	v, x []interface{}
-}
+type lengthMismatchError struct{}
 
 func (err *lengthMismatchError) Error() string {
-	return "length mismatch in " + err.name + ": " + typeErrorPreview(err.v) + ", " + typeErrorPreview(err.x)
+	return "length mismatch"
 }
 
 type inputNotAllowedError struct{}
@@ -106,17 +103,65 @@ func (err *funcNotFoundError) Error() string {
 	return "function not defined: " + err.f.Name + "/" + strconv.Itoa(len(err.f.Args))
 }
 
-type funcTypeError struct {
+type func0TypeError struct {
 	name string
-	v    interface{}
+	v    any
 }
 
-func (err *funcTypeError) Error() string {
+func (err *func0TypeError) Error() string {
 	return err.name + " cannot be applied to: " + typeErrorPreview(err.v)
 }
 
+type func1TypeError struct {
+	name string
+	v, w any
+}
+
+func (err *func1TypeError) Error() string {
+	return err.name + "(" + Preview(err.w) + ") cannot be applied to: " + typeErrorPreview(err.v)
+}
+
+type func2TypeError struct {
+	name    string
+	v, w, x any
+}
+
+func (err *func2TypeError) Error() string {
+	return err.name + "(" + Preview(err.w) + "; " + Preview(err.x) + ") cannot be applied to: " + typeErrorPreview(err.v)
+}
+
+type func0WrapError struct {
+	name string
+	v    any
+	err  error
+}
+
+func (err *func0WrapError) Error() string {
+	return err.name + " cannot be applied to " + Preview(err.v) + ": " + err.err.Error()
+}
+
+type func1WrapError struct {
+	name string
+	v, w any
+	err  error
+}
+
+func (err *func1WrapError) Error() string {
+	return err.name + "(" + Preview(err.w) + ") cannot be applied to " + Preview(err.v) + ": " + err.err.Error()
+}
+
+type func2WrapError struct {
+	name    string
+	v, w, x any
+	err     error
+}
+
+func (err *func2WrapError) Error() string {
+	return err.name + "(" + Preview(err.w) + "; " + Preview(err.x) + ") cannot be applied to " + Preview(err.v) + ": " + err.err.Error()
+}
+
 type exitCodeError struct {
-	value interface{}
+	value any
 	code  int
 	halt  bool
 }
@@ -132,7 +177,7 @@ func (err *exitCodeError) IsEmptyError() bool {
 	return err.value == nil
 }
 
-func (err *exitCodeError) Value() interface{} {
+func (err *exitCodeError) Value() any {
 	return err.value
 }
 
@@ -144,41 +189,31 @@ func (err *exitCodeError) IsHaltError() bool {
 	return err.halt
 }
 
-type containsTypeError struct {
-	l, r interface{}
-}
-
-func (err *containsTypeError) Error() string {
-	return "cannot check contains(" + Preview(err.r) + "): " + typeErrorPreview(err.l)
-}
-
-type hasKeyTypeError struct {
-	l, r interface{}
-}
-
-func (err *hasKeyTypeError) Error() string {
-	return "cannot check whether " + typeErrorPreview(err.l) + " has a key: " + typeErrorPreview(err.r)
-}
-
 type flattenDepthError struct {
 	v float64
 }
 
 func (err *flattenDepthError) Error() string {
-	return "flatten depth must not be negative: " + typeErrorPreview(err.v)
+	return "flatten depth should not be negative: " + Preview(err.v)
 }
 
 type joinTypeError struct {
-	v interface{}
+	v any
 }
 
 func (err *joinTypeError) Error() string {
-	return "cannot join: " + typeErrorPreview(err.v)
+	return "join cannot be applied to an array including: " + typeErrorPreview(err.v)
+}
+
+type timeArrayError struct{}
+
+func (err *timeArrayError) Error() string {
+	return "expected an array of 8 numbers"
 }
 
 type unaryTypeError struct {
 	name string
-	v    interface{}
+	v    any
 }
 
 func (err *unaryTypeError) Error() string {
@@ -187,7 +222,7 @@ func (err *unaryTypeError) Error() string {
 
 type binopTypeError struct {
 	name string
-	l, r interface{}
+	l, r any
 }
 
 func (err *binopTypeError) Error() string {
@@ -195,7 +230,7 @@ func (err *binopTypeError) Error() string {
 }
 
 type zeroDivisionError struct {
-	l, r interface{}
+	l, r any
 }
 
 func (err *zeroDivisionError) Error() string {
@@ -203,7 +238,7 @@ func (err *zeroDivisionError) Error() string {
 }
 
 type zeroModuloError struct {
-	l, r interface{}
+	l, r any
 }
 
 func (err *zeroModuloError) Error() string {
@@ -220,7 +255,7 @@ func (err *formatNotFoundError) Error() string {
 
 type formatRowError struct {
 	typ string
-	v   interface{}
+	v   any
 }
 
 func (err *formatRowError) Error() string {
@@ -259,7 +294,7 @@ func (err *variableNameError) Error() string {
 
 type breakError struct {
 	n string
-	v interface{}
+	v any
 }
 
 func (err *breakError) Error() string {
@@ -279,7 +314,7 @@ func (err *tryEndError) Error() string {
 }
 
 type invalidPathError struct {
-	v interface{}
+	v any
 }
 
 func (err *invalidPathError) Error() string {
@@ -287,21 +322,13 @@ func (err *invalidPathError) Error() string {
 }
 
 type invalidPathIterError struct {
-	v interface{}
+	v any
 }
 
 func (err *invalidPathIterError) Error() string {
 	return "invalid path on iterating against: " + typeErrorPreview(err.v)
 }
 
-type getpathError struct {
-	v, path interface{}
-}
-
-func (err *getpathError) Error() string {
-	return "cannot getpath with " + Preview(err.path) + " against: " + typeErrorPreview(err.v)
-}
-
 type queryParseError struct {
 	fname, contents string
 	err             error
@@ -328,7 +355,7 @@ func (err *jsonParseError) Error() string {
 	return "invalid json: " + err.fname + ": " + err.err.Error()
 }
 
-func typeErrorPreview(v interface{}) string {
+func typeErrorPreview(v any) string {
 	switch v.(type) {
 	case nil:
 		return "null"
diff --git a/execute.go b/execute.go
index af00229..dcf9d98 100644
--- a/execute.go
+++ b/execute.go
@@ -7,7 +7,7 @@ import (
 	"sort"
 )
 
-func (env *env) execute(bc *Code, v interface{}, vars ...interface{}) Iter {
+func (env *env) execute(bc *Code, v any, vars ...any) Iter {
 	env.codes = bc.codes
 	env.codeinfos = bc.codeinfos
 	env.push(v)
@@ -18,7 +18,7 @@ func (env *env) execute(bc *Code, v interface{}, vars ...interface{}) Iter {
 	return env
 }
 
-func (env *env) Next() (interface{}, bool) {
+func (env *env) Next() (any, bool) {
 	var err error
 	pc, callpc, index := env.pc, len(env.codes)-1, -1
 	backtrack, hasCtx := env.backtrack, env.ctx != context.Background()
@@ -58,7 +58,7 @@ loop:
 				break loop
 			}
 			n := code.v.(int)
-			m := make(map[string]interface{}, n)
+			m := make(map[string]any, n)
 			for i := 0; i < n; i++ {
 				v, k := env.pop(), env.pop()
 				s, ok := k.(string)
@@ -71,7 +71,7 @@ loop:
 			env.push(m)
 		case opappend:
 			i := env.index(code.v.([2]int))
-			env.values[i] = append(env.values[i].([]interface{}), env.pop())
+			env.values[i] = append(env.values[i].([]any), env.pop())
 		case opfork:
 			if backtrack {
 				if err != nil {
@@ -157,7 +157,7 @@ loop:
 			}
 			p, v := code.v, env.pop()
 			if code.op == opindexarray && v != nil {
-				if _, ok := v.([]interface{}); !ok {
+				if _, ok := v.([]any); !ok {
 					err = &expectedArrayError{v}
 					break loop
 				}
@@ -183,13 +183,13 @@ loop:
 			case int:
 				pc, callpc, index = v, pc, env.scopes.index
 				goto loop
-			case [3]interface{}:
+			case [3]any:
 				argcnt := v[1].(int)
 				x, args := env.pop(), env.args[:argcnt]
 				for i := 0; i < argcnt; i++ {
 					args[i] = env.pop()
 				}
-				w := v[0].(func(interface{}, []interface{}) interface{})(x, args)
+				w := v[0].(func(any, []any) any)(x, args)
 				if e, ok := w.(error); ok {
 					if er, ok := e.(*exitCodeError); !ok || er.value != nil || er.halt {
 						err = e
@@ -211,7 +211,7 @@ loop:
 							break loop
 						}
 						env.paths.push(pathValue{
-							path:  map[string]interface{}{"start": args[2], "end": args[1]},
+							path:  map[string]any{"start": args[2], "end": args[1]},
 							value: w,
 						})
 					case "getpath":
@@ -219,7 +219,7 @@ loop:
 							err = &invalidPathError{x}
 							break loop
 						}
-						for _, p := range args[0].([]interface{}) {
+						for _, p := range args[0].([]any) {
 							env.paths.push(pathValue{path: p, value: w})
 						}
 					}
@@ -257,7 +257,7 @@ loop:
 			env.scopes.push(scope{xs[0], env.offset, callpc, saveindex, outerindex})
 			env.offset += xs[1]
 			if env.offset > len(env.values) {
-				vs := make([]interface{}, env.offset*2)
+				vs := make([]any, env.offset*2)
 				copy(vs, env.values)
 				env.values = vs
 			}
@@ -278,7 +278,7 @@ loop:
 			switch v := env.pop().(type) {
 			case []pathValue:
 				xs = v
-			case []interface{}:
+			case []any:
 				if !env.paths.empty() && env.expdepth == 0 && !env.pathIntact(v) {
 					err = &invalidPathIterError{v}
 					break loop
@@ -290,7 +290,7 @@ loop:
 				for i, v := range v {
 					xs[i] = pathValue{path: i, value: v}
 				}
-			case map[string]interface{}:
+			case map[string]any:
 				if !env.paths.empty() && env.expdepth == 0 && !env.pathIntact(v) {
 					err = &invalidPathIterError{v}
 					break loop
@@ -367,11 +367,11 @@ loop:
 	return nil, false
 }
 
-func (env *env) push(v interface{}) {
+func (env *env) push(v any) {
 	env.stack.push(v)
 }
 
-func (env *env) pop() interface{} {
+func (env *env) pop() any {
 	return env.stack.pop()
 }
 
@@ -415,15 +415,15 @@ func (env *env) index(v [2]int) int {
 }
 
 type pathValue struct {
-	path, value interface{}
+	path, value any
 }
 
-func (env *env) pathIntact(v interface{}) bool {
+func (env *env) pathIntact(v any) bool {
 	w := env.paths.top().(pathValue).value
 	switch v := v.(type) {
-	case []interface{}, map[string]interface{}:
+	case []any, map[string]any:
 		switch w.(type) {
-		case []interface{}, map[string]interface{}:
+		case []any, map[string]any:
 			v, w := reflect.ValueOf(v), reflect.ValueOf(w)
 			return v.Pointer() == w.Pointer() && v.Len() == w.Len()
 		}
@@ -435,8 +435,8 @@ func (env *env) pathIntact(v interface{}) bool {
 	return v == w
 }
 
-func (env *env) poppaths() []interface{} {
-	var xs []interface{}
+func (env *env) poppaths() []any {
+	xs := []any{}
 	for {
 		p := env.paths.pop().(pathValue)
 		if p.path == nil {
diff --git a/func.go b/func.go
index 2c2a28f..6e8d150 100644
--- a/func.go
+++ b/func.go
@@ -3,6 +3,7 @@ package gojq
 import (
 	"encoding/base64"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"io"
 	"math"
@@ -32,7 +33,7 @@ const (
 type function struct {
 	argcount int
 	iter     bool
-	callback func(interface{}, []interface{}) interface{}
+	callback func(any, []any) any
 }
 
 func (fn function) accept(cnt int) bool {
@@ -78,6 +79,7 @@ func init() {
 		"format":         argFunc1(funcFormat),
 		"_tohtml":        argFunc0(funcToHTML),
 		"_touri":         argFunc0(funcToURI),
+		"_tourid":        argFunc0(funcToURId),
 		"_tocsv":         argFunc0(funcToCSV),
 		"_totsv":         argFunc0(funcToTSV),
 		"_tosh":          argFunc0(funcToSh),
@@ -198,81 +200,81 @@ func init() {
 	}
 }
 
-func argFunc0(f func(interface{}) interface{}) function {
+func argFunc0(f func(any) any) function {
 	return function{
-		argcount0, false, func(v interface{}, _ []interface{}) interface{} {
+		argcount0, false, func(v any, _ []any) any {
 			return f(v)
 		},
 	}
 }
 
-func argFunc1(f func(_, _ interface{}) interface{}) function {
+func argFunc1(f func(_, _ any) any) function {
 	return function{
-		argcount1, false, func(v interface{}, args []interface{}) interface{} {
+		argcount1, false, func(v any, args []any) any {
 			return f(v, args[0])
 		},
 	}
 }
 
-func argFunc2(f func(_, _, _ interface{}) interface{}) function {
+func argFunc2(f func(_, _, _ any) any) function {
 	return function{
-		argcount2, false, func(v interface{}, args []interface{}) interface{} {
+		argcount2, false, func(v any, args []any) any {
 			return f(v, args[0], args[1])
 		},
 	}
 }
 
-func argFunc3(f func(_, _, _, _ interface{}) interface{}) function {
+func argFunc3(f func(_, _, _, _ any) any) function {
 	return function{
-		argcount3, false, func(v interface{}, args []interface{}) interface{} {
+		argcount3, false, func(v any, args []any) any {
 			return f(v, args[0], args[1], args[2])
 		},
 	}
 }
 
 func mathFunc(name string, f func(float64) float64) function {
-	return argFunc0(func(v interface{}) interface{} {
+	return argFunc0(func(v any) any {
 		x, ok := toFloat(v)
 		if !ok {
-			return &funcTypeError{name, v}
+			return &func0TypeError{name, v}
 		}
 		return f(x)
 	})
 }
 
 func mathFunc2(name string, f func(_, _ float64) float64) function {
-	return argFunc2(func(_, x, y interface{}) interface{} {
+	return argFunc2(func(_, x, y any) any {
 		l, ok := toFloat(x)
 		if !ok {
-			return &funcTypeError{name, x}
+			return &func0TypeError{name, x}
 		}
 		r, ok := toFloat(y)
 		if !ok {
-			return &funcTypeError{name, y}
+			return &func0TypeError{name, y}
 		}
 		return f(l, r)
 	})
 }
 
 func mathFunc3(name string, f func(_, _, _ float64) float64) function {
-	return argFunc3(func(_, a, b, c interface{}) interface{} {
+	return argFunc3(func(_, a, b, c any) any {
 		x, ok := toFloat(a)
 		if !ok {
-			return &funcTypeError{name, a}
+			return &func0TypeError{name, a}
 		}
 		y, ok := toFloat(b)
 		if !ok {
-			return &funcTypeError{name, b}
+			return &func0TypeError{name, b}
 		}
 		z, ok := toFloat(c)
 		if !ok {
-			return &funcTypeError{name, c}
+			return &func0TypeError{name, c}
 		}
 		return f(x, y, z)
 	})
 }
 
-func funcLength(v interface{}) interface{} {
+func funcLength(v any) any {
 	switch v := v.(type) {
 	case nil:
 		return 0
@@ -290,43 +292,43 @@ func funcLength(v interface{}) interface{} {
 		return new(big.Int).Abs(v)
 	case string:
 		return len([]rune(v))
-	case []interface{}:
+	case []any:
 		return len(v)
-	case map[string]interface{}:
+	case map[string]any:
 		return len(v)
 	default:
-		return &funcTypeError{"length", v}
+		return &func0TypeError{"length", v}
 	}
 }
 
-func funcUtf8ByteLength(v interface{}) interface{} {
+func funcUtf8ByteLength(v any) any {
 	s, ok := v.(string)
 	if !ok {
-		return &funcTypeError{"utf8bytelength", v}
+		return &func0TypeError{"utf8bytelength", v}
 	}
 	return len(s)
 }
 
-func funcKeys(v interface{}) interface{} {
+func funcKeys(v any) any {
 	switch v := v.(type) {
-	case []interface{}:
-		w := make([]interface{}, len(v))
+	case []any:
+		w := make([]any, len(v))
 		for i := range v {
 			w[i] = i
 		}
 		return w
-	case map[string]interface{}:
-		w := make([]interface{}, len(v))
+	case map[string]any:
+		w := make([]any, len(v))
 		for i, k := range keys(v) {
 			w[i] = k
 		}
 		return w
 	default:
-		return &funcTypeError{"keys", v}
+		return &func0TypeError{"keys", v}
 	}
 }
 
-func keys(v map[string]interface{}) []string {
+func keys(v map[string]any) []string {
 	w := make([]string, len(v))
 	var i int
 	for k := range v {
@@ -337,12 +339,12 @@ func keys(v map[string]interface{}) []string {
 	return w
 }
 
-func values(v interface{}) ([]interface{}, bool) {
+func values(v any) ([]any, bool) {
 	switch v := v.(type) {
-	case []interface{}:
+	case []any:
 		return v, true
-	case map[string]interface{}:
-		vs := make([]interface{}, len(v))
+	case map[string]any:
+		vs := make([]any, len(v))
 		for i, k := range keys(v) {
 			vs[i] = v[k]
 		}
@@ -352,13 +354,13 @@ func values(v interface{}) ([]interface{}, bool) {
 	}
 }
 
-func funcHas(v, x interface{}) interface{} {
+func funcHas(v, x any) any {
 	switch v := v.(type) {
-	case []interface{}:
+	case []any:
 		if x, ok := toInt(x); ok {
 			return 0 <= x && x < len(v)
 		}
-	case map[string]interface{}:
+	case map[string]any:
 		if x, ok := x.(string); ok {
 			_, ok := v[x]
 			return ok
@@ -366,52 +368,52 @@ func funcHas(v, x interface{}) interface{} {
 	case nil:
 		return false
 	}
-	return &hasKeyTypeError{v, x}
+	return &func1TypeError{"has", v, x}
 }
 
-func funcToEntries(v interface{}) interface{} {
+func funcToEntries(v any) any {
 	switch v := v.(type) {
-	case []interface{}:
-		w := make([]interface{}, len(v))
+	case []any:
+		w := make([]any, len(v))
 		for i, x := range v {
-			w[i] = map[string]interface{}{"key": i, "value": x}
+			w[i] = map[string]any{"key": i, "value": x}
 		}
 		return w
-	case map[string]interface{}:
-		w := make([]interface{}, len(v))
+	case map[string]any:
+		w := make([]any, len(v))
 		for i, k := range keys(v) {
-			w[i] = map[string]interface{}{"key": k, "value": v[k]}
+			w[i] = map[string]any{"key": k, "value": v[k]}
 		}
 		return w
 	default:
-		return &funcTypeError{"to_entries", v}
+		return &func0TypeError{"to_entries", v}
 	}
 }
 
-func funcFromEntries(v interface{}) interface{} {
-	vs, ok := v.([]interface{})
+func funcFromEntries(v any) any {
+	vs, ok := v.([]any)
 	if !ok {
-		return &funcTypeError{"from_entries", v}
+		return &func0TypeError{"from_entries", v}
 	}
-	w := make(map[string]interface{}, len(vs))
+	w := make(map[string]any, len(vs))
 	for _, v := range vs {
 		switch v := v.(type) {
-		case map[string]interface{}:
+		case map[string]any:
 			var (
 				key   string
-				value interface{}
+				value any
 				ok    bool
 			)
 			for _, k := range [4]string{"key", "Key", "name", "Name"} {
 				if k := v[k]; k != nil && k != false {
 					if key, ok = k.(string); !ok {
-						return &objectKeyNotStringError{k}
+						return &func0WrapError{"from_entries", vs, &objectKeyNotStringError{k}}
 					}
 					break
 				}
 			}
 			if !ok {
-				return &objectKeyNotStringError{nil}
+				return &func0WrapError{"from_entries", vs, &objectKeyNotStringError{nil}}
 			}
 			for _, k := range [2]string{"value", "Value"} {
 				if value, ok = v[k]; ok {
@@ -420,16 +422,16 @@ func funcFromEntries(v interface{}) interface{} {
 			}
 			w[key] = value
 		default:
-			return &funcTypeError{"from_entries", v}
+			return &func0TypeError{"from_entries", v}
 		}
 	}
 	return w
 }
 
-func funcAdd(v interface{}) interface{} {
+func funcAdd(v any) any {
 	vs, ok := values(v)
 	if !ok {
-		return &funcTypeError{"add", v}
+		return &func0TypeError{"add", v}
 	}
 	v = nil
 	for _, x := range vs {
@@ -447,27 +449,27 @@ func funcAdd(v interface{}) interface{} {
 				w.WriteString(x)
 				continue
 			}
-		case []interface{}:
+		case []any:
 			switch w := v.(type) {
 			case nil:
-				s := make([]interface{}, len(x))
+				s := make([]any, len(x))
 				copy(s, x)
 				v = s
 				continue
-			case []interface{}:
+			case []any:
 				v = append(w, x...)
 				continue
 			}
-		case map[string]interface{}:
+		case map[string]any:
 			switch w := v.(type) {
 			case nil:
-				m := make(map[string]interface{}, len(x))
+				m := make(map[string]any, len(x))
 				for k, e := range x {
 					m[k] = e
 				}
 				v = m
 				continue
-			case map[string]interface{}:
+			case map[string]any:
 				for k, e := range x {
 					w[k] = e
 				}
@@ -488,54 +490,54 @@ func funcAdd(v interface{}) interface{} {
 	return v
 }
 
-func funcToNumber(v interface{}) interface{} {
+func funcToNumber(v any) any {
 	switch v := v.(type) {
 	case int, float64, *big.Int:
 		return v
 	case string:
 		if !newLexer(v).validNumber() {
-			return fmt.Errorf("invalid number: %q", v)
+			return &func0WrapError{"tonumber", v, errors.New("invalid number")}
 		}
 		return toNumber(v)
 	default:
-		return &funcTypeError{"tonumber", v}
+		return &func0TypeError{"tonumber", v}
 	}
 }
 
-func toNumber(v string) interface{} {
+func toNumber(v string) any {
 	return normalizeNumber(json.Number(v))
 }
 
-func funcToString(v interface{}) interface{} {
+func funcToString(v any) any {
 	if s, ok := v.(string); ok {
 		return s
 	}
 	return funcToJSON(v)
 }
 
-func funcType(v interface{}) interface{} {
+func funcType(v any) any {
 	return TypeOf(v)
 }
 
-func funcReverse(v interface{}) interface{} {
-	vs, ok := v.([]interface{})
+func funcReverse(v any) any {
+	vs, ok := v.([]any)
 	if !ok {
-		return &funcTypeError{"reverse", v}
+		return &func0TypeError{"reverse", v}
 	}
-	ws := make([]interface{}, len(vs))
+	ws := make([]any, len(vs))
 	for i, v := range vs {
 		ws[len(ws)-i-1] = v
 	}
 	return ws
 }
 
-func funcContains(v, x interface{}) interface{} {
+func funcContains(v, x any) any {
 	return binopTypeSwitch(v, x,
-		func(l, r int) interface{} { return l == r },
-		func(l, r float64) interface{} { return l == r },
-		func(l, r *big.Int) interface{} { return l.Cmp(r) == 0 },
-		func(l, r string) interface{} { return strings.Contains(l, r) },
-		func(l, r []interface{}) interface{} {
+		func(l, r int) any { return l == r },
+		func(l, r float64) any { return l == r },
+		func(l, r *big.Int) any { return l.Cmp(r) == 0 },
+		func(l, r string) any { return strings.Contains(l, r) },
+		func(l, r []any) any {
 		R:
 			for _, r := range r {
 				for _, l := range l {
@@ -547,7 +549,7 @@ func funcContains(v, x interface{}) interface{} {
 			}
 			return true
 		},
-		func(l, r map[string]interface{}) interface{} {
+		func(l, r map[string]any) any {
 			if len(l) < len(r) {
 				return false
 			}
@@ -558,21 +560,21 @@ func funcContains(v, x interface{}) interface{} {
 			}
 			return true
 		},
-		func(l, r interface{}) interface{} {
+		func(l, r any) any {
 			if l == r {
 				return true
 			}
-			return &containsTypeError{l, r}
+			return &func1TypeError{"contains", l, r}
 		},
 	)
 }
 
-func funcIndices(v, x interface{}) interface{} {
-	return indexFunc(v, x, indices)
+func funcIndices(v, x any) any {
+	return indexFunc("indices", v, x, indices)
 }
 
-func indices(vs, xs []interface{}) interface{} {
-	var rs []interface{}
+func indices(vs, xs []any) any {
+	rs := []any{}
 	if len(xs) == 0 {
 		return rs
 	}
@@ -584,8 +586,8 @@ func indices(vs, xs []interface{}) interface{} {
 	return rs
 }
 
-func funcIndex(v, x interface{}) interface{} {
-	return indexFunc(v, x, func(vs, xs []interface{}) interface{} {
+func funcIndex(v, x any) any {
+	return indexFunc("index", v, x, func(vs, xs []any) any {
 		if len(xs) == 0 {
 			return nil
 		}
@@ -598,8 +600,8 @@ func funcIndex(v, x interface{}) interface{} {
 	})
 }
 
-func funcRindex(v, x interface{}) interface{} {
-	return indexFunc(v, x, func(vs, xs []interface{}) interface{} {
+func funcRindex(v, x any) any {
+	return indexFunc("rindex", v, x, func(vs, xs []any) any {
 		if len(xs) == 0 {
 			return nil
 		}
@@ -612,52 +614,52 @@ func funcRindex(v, x interface{}) interface{} {
 	})
 }
 
-func indexFunc(v, x interface{}, f func(_, _ []interface{}) interface{}) interface{} {
+func indexFunc(name string, v, x any, f func(_, _ []any) any) any {
 	switch v := v.(type) {
 	case nil:
 		return nil
-	case []interface{}:
+	case []any:
 		switch x := x.(type) {
-		case []interface{}:
+		case []any:
 			return f(v, x)
 		default:
-			return f(v, []interface{}{x})
+			return f(v, []any{x})
 		}
 	case string:
 		if x, ok := x.(string); ok {
 			return f(explode(v), explode(x))
 		}
-		return &expectedStringError{x}
+		return &func1TypeError{name, v, x}
 	default:
-		return &expectedArrayError{v}
+		return &func1TypeError{name, v, x}
 	}
 }
 
-func funcStartsWith(v, x interface{}) interface{} {
+func funcStartsWith(v, x any) any {
 	s, ok := v.(string)
 	if !ok {
-		return &funcTypeError{"startswith", v}
+		return &func1TypeError{"startswith", v, x}
 	}
 	t, ok := x.(string)
 	if !ok {
-		return &funcTypeError{"startswith", x}
+		return &func1TypeError{"startswith", v, x}
 	}
 	return strings.HasPrefix(s, t)
 }
 
-func funcEndsWith(v, x interface{}) interface{} {
+func funcEndsWith(v, x any) any {
 	s, ok := v.(string)
 	if !ok {
-		return &funcTypeError{"endswith", v}
+		return &func1TypeError{"endswith", v, x}
 	}
 	t, ok := x.(string)
 	if !ok {
-		return &funcTypeError{"endswith", x}
+		return &func1TypeError{"endswith", v, x}
 	}
 	return strings.HasSuffix(s, t)
 }
 
-func funcLtrimstr(v, x interface{}) interface{} {
+func funcLtrimstr(v, x any) any {
 	s, ok := v.(string)
 	if !ok {
 		return v
@@ -669,7 +671,7 @@ func funcLtrimstr(v, x interface{}) interface{} {
 	return strings.TrimPrefix(s, t)
 }
 
-func funcRtrimstr(v, x interface{}) interface{} {
+func funcRtrimstr(v, x any) any {
 	s, ok := v.(string)
 	if !ok {
 		return v
@@ -681,16 +683,16 @@ func funcRtrimstr(v, x interface{}) interface{} {
 	return strings.TrimSuffix(s, t)
 }
 
-func funcExplode(v interface{}) interface{} {
+func funcExplode(v any) any {
 	s, ok := v.(string)
 	if !ok {
-		return &funcTypeError{"explode", v}
+		return &func0TypeError{"explode", v}
 	}
 	return explode(s)
 }
 
-func explode(s string) []interface{} {
-	xs := make([]interface{}, len([]rune(s)))
+func explode(s string) []any {
+	xs := make([]any, len([]rune(s)))
 	var i int
 	for _, r := range s {
 		xs[i] = int(r)
@@ -699,10 +701,10 @@ func explode(s string) []interface{} {
 	return xs
 }
 
-func funcImplode(v interface{}) interface{} {
-	vs, ok := v.([]interface{})
+func funcImplode(v any) any {
+	vs, ok := v.([]any)
 	if !ok {
-		return &funcTypeError{"implode", v}
+		return &func0TypeError{"implode", v}
 	}
 	var sb strings.Builder
 	sb.Grow(len(vs))
@@ -710,20 +712,20 @@ func funcImplode(v interface{}) interface{} {
 		if r, ok := toInt(v); ok && 0 <= r && r <= utf8.MaxRune {
 			sb.WriteRune(rune(r))
 		} else {
-			return &funcTypeError{"implode", vs}
+			return &func0TypeError{"implode", vs}
 		}
 	}
 	return sb.String()
 }
 
-func funcSplit(v interface{}, args []interface{}) interface{} {
+func funcSplit(v any, args []any) any {
 	s, ok := v.(string)
 	if !ok {
-		return &funcTypeError{"split", v}
+		return &func0TypeError{"split", v}
 	}
 	x, ok := args[0].(string)
 	if !ok {
-		return &funcTypeError{"split", x}
+		return &func0TypeError{"split", x}
 	}
 	var ss []string
 	if len(args) == 1 {
@@ -733,7 +735,7 @@ func funcSplit(v interface{}, args []interface{}) interface{} {
 		if args[1] != nil {
 			v, ok := args[1].(string)
 			if !ok {
-				return &funcTypeError{"split", args[1]}
+				return &func0TypeError{"split", args[1]}
 			}
 			flags = v
 		}
@@ -743,17 +745,17 @@ func funcSplit(v interface{}, args []interface{}) interface{} {
 		}
 		ss = r.Split(s, -1)
 	}
-	xs := make([]interface{}, len(ss))
+	xs := make([]any, len(ss))
 	for i, s := range ss {
 		xs[i] = s
 	}
 	return xs
 }
 
-func funcASCIIDowncase(v interface{}) interface{} {
+func funcASCIIDowncase(v any) any {
 	s, ok := v.(string)
 	if !ok {
-		return &funcTypeError{"ascii_downcase", v}
+		return &func0TypeError{"ascii_downcase", v}
 	}
 	return strings.Map(func(r rune) rune {
 		if 'A' <= r && r <= 'Z' {
@@ -763,10 +765,10 @@ func funcASCIIDowncase(v interface{}) interface{} {
 	}, s)
 }
 
-func funcASCIIUpcase(v interface{}) interface{} {
+func funcASCIIUpcase(v any) any {
 	s, ok := v.(string)
 	if !ok {
-		return &funcTypeError{"ascii_upcase", v}
+		return &func0TypeError{"ascii_upcase", v}
 	}
 	return strings.Map(func(r rune) rune {
 		if 'a' <= r && r <= 'z' {
@@ -776,36 +778,36 @@ func funcASCIIUpcase(v interface{}) interface{} {
 	}, s)
 }
 
-func funcToJSON(v interface{}) interface{} {
+func funcToJSON(v any) any {
 	return jsonMarshal(v)
 }
 
-func funcFromJSON(v interface{}) interface{} {
+func funcFromJSON(v any) any {
 	s, ok := v.(string)
 	if !ok {
-		return &funcTypeError{"fromjson", v}
+		return &func0TypeError{"fromjson", v}
 	}
-	var w interface{}
+	var w any
 	dec := json.NewDecoder(strings.NewReader(s))
 	dec.UseNumber()
 	if err := dec.Decode(&w); err != nil {
-		return err
+		return &func0WrapError{"fromjson", v, err}
 	}
 	if _, err := dec.Token(); err != io.EOF {
-		return &funcTypeError{"fromjson", v}
+		return &func0TypeError{"fromjson", v}
 	}
 	return normalizeNumbers(w)
 }
 
-func funcFormat(v, x interface{}) interface{} {
+func funcFormat(v, x any) any {
 	s, ok := x.(string)
 	if !ok {
-		return &funcTypeError{"format", x}
+		return &func0TypeError{"format", x}
 	}
-	fmt := "@" + s
-	f := formatToFunc(fmt)
+	format := "@" + s
+	f := formatToFunc(format)
 	if f == nil {
-		return &formatNotFoundError{fmt}
+		return &formatNotFoundError{format}
 	}
 	return internalFuncs[f.Name].callback(v, nil)
 }
@@ -818,7 +820,7 @@ var htmlEscaper = strings.NewReplacer(
 	`"`, "&quot;",
 )
 
-func funcToHTML(v interface{}) interface{} {
+func funcToHTML(v any) any {
 	switch x := funcToString(v).(type) {
 	case string:
 		return htmlEscaper.Replace(x)
@@ -827,7 +829,7 @@ func funcToHTML(v interface{}) interface{} {
 	}
 }
 
-func funcToURI(v interface{}) interface{} {
+func funcToURI(v any) any {
 	switch x := funcToString(v).(type) {
 	case string:
 		return url.QueryEscape(x)
@@ -836,12 +838,25 @@ func funcToURI(v interface{}) interface{} {
 	}
 }
 
+func funcToURId(v any) any {
+	switch x := funcToString(v).(type) {
+	case string:
+		x, err := url.QueryUnescape(x)
+		if err != nil {
+			return &func0WrapError{"@urid", v, err}
+		}
+		return x
+	default:
+		return x
+	}
+}
+
 var csvEscaper = strings.NewReplacer(
 	`"`, `""`,
 	"\x00", `\0`,
 )
 
-func funcToCSV(v interface{}) interface{} {
+func funcToCSV(v any) any {
 	return formatJoin("csv", v, ",", func(s string) string {
 		return `"` + csvEscaper.Replace(s) + `"`
 	})
@@ -855,7 +870,7 @@ var tsvEscaper = strings.NewReplacer(
 	"\x00", `\0`,
 )
 
-func funcToTSV(v interface{}) interface{} {
+func funcToTSV(v any) any {
 	return formatJoin("tsv", v, "\t", tsvEscaper.Replace)
 }
 
@@ -864,24 +879,24 @@ var shEscaper = strings.NewReplacer(
 	"\x00", `\0`,
 )
 
-func funcToSh(v interface{}) interface{} {
-	if _, ok := v.([]interface{}); !ok {
-		v = []interface{}{v}
+func funcToSh(v any) any {
+	if _, ok := v.([]any); !ok {
+		v = []any{v}
 	}
 	return formatJoin("sh", v, " ", func(s string) string {
 		return "'" + shEscaper.Replace(s) + "'"
 	})
 }
 
-func formatJoin(typ string, v interface{}, sep string, escape func(string) string) interface{} {
-	vs, ok := v.([]interface{})
+func formatJoin(typ string, v any, sep string, escape func(string) string) any {
+	vs, ok := v.([]any)
 	if !ok {
-		return &funcTypeError{"@" + typ, v}
+		return &func0TypeError{"@" + typ, v}
 	}
 	ss := make([]string, len(vs))
 	for i, v := range vs {
 		switch v := v.(type) {
-		case []interface{}, map[string]interface{}:
+		case []any, map[string]any:
 			return &formatRowError{typ, v}
 		case string:
 			ss[i] = escape(v)
@@ -894,7 +909,7 @@ func formatJoin(typ string, v interface{}, sep string, escape func(string) strin
 	return strings.Join(ss, sep)
 }
 
-func funcToBase64(v interface{}) interface{} {
+func funcToBase64(v any) any {
 	switch x := funcToString(v).(type) {
 	case string:
 		return base64.StdEncoding.EncodeToString([]byte(x))
@@ -903,7 +918,7 @@ func funcToBase64(v interface{}) interface{} {
 	}
 }
 
-func funcToBase64d(v interface{}) interface{} {
+func funcToBase64d(v any) any {
 	switch x := funcToString(v).(type) {
 	case string:
 		if i := strings.IndexRune(x, base64.StdPadding); i >= 0 {
@@ -911,7 +926,7 @@ func funcToBase64d(v interface{}) interface{} {
 		}
 		y, err := base64.RawStdEncoding.DecodeString(x)
 		if err != nil {
-			return err
+			return &func0WrapError{"@base64d", v, err}
 		}
 		return string(y)
 	default:
@@ -919,13 +934,13 @@ func funcToBase64d(v interface{}) interface{} {
 	}
 }
 
-func funcIndex2(_, v, x interface{}) interface{} {
+func funcIndex2(_, v, x any) any {
 	switch x := x.(type) {
 	case string:
 		switch v := v.(type) {
 		case nil:
 			return nil
-		case map[string]interface{}:
+		case map[string]any:
 			return v[x]
 		default:
 			return &expectedObjectError{v}
@@ -935,23 +950,23 @@ func funcIndex2(_, v, x interface{}) interface{} {
 		switch v := v.(type) {
 		case nil:
 			return nil
-		case []interface{}:
+		case []any:
 			return index(v, i)
 		case string:
 			return indexString(v, i)
 		default:
 			return &expectedArrayError{v}
 		}
-	case []interface{}:
+	case []any:
 		switch v := v.(type) {
 		case nil:
 			return nil
-		case []interface{}:
+		case []any:
 			return indices(v, x)
 		default:
 			return &expectedArrayError{v}
 		}
-	case map[string]interface{}:
+	case map[string]any:
 		if v == nil {
 			return nil
 		}
@@ -966,7 +981,7 @@ func funcIndex2(_, v, x interface{}) interface{} {
 		return funcSlice(nil, v, end, start)
 	default:
 		switch v.(type) {
-		case []interface{}:
+		case []any:
 			return &arrayIndexNotNumberError{x}
 		case string:
 			return &stringIndexNotNumberError{x}
@@ -976,7 +991,7 @@ func funcIndex2(_, v, x interface{}) interface{} {
 	}
 }
 
-func index(vs []interface{}, i int) interface{} {
+func index(vs []any, i int) any {
 	i = clampIndex(i, -1, len(vs))
 	if 0 <= i && i < len(vs) {
 		return vs[i]
@@ -984,7 +999,7 @@ func index(vs []interface{}, i int) interface{} {
 	return nil
 }
 
-func indexString(s string, i int) interface{} {
+func indexString(s string, i int) any {
 	l := len([]rune(s))
 	i = clampIndex(i, -1, l)
 	if 0 <= i && i < l {
@@ -997,11 +1012,11 @@ func indexString(s string, i int) interface{} {
 	return nil
 }
 
-func funcSlice(_, v, e, s interface{}) (r interface{}) {
+func funcSlice(_, v, e, s any) (r any) {
 	switch v := v.(type) {
 	case nil:
 		return nil
-	case []interface{}:
+	case []any:
 		return slice(v, e, s)
 	case string:
 		return sliceString(v, e, s)
@@ -1010,7 +1025,7 @@ func funcSlice(_, v, e, s interface{}) (r interface{}) {
 	}
 }
 
-func slice(vs []interface{}, e, s interface{}) interface{} {
+func slice(vs []any, e, s any) any {
 	var start, end int
 	if s != nil {
 		if i, ok := toInt(s); ok {
@@ -1031,7 +1046,7 @@ func slice(vs []interface{}, e, s interface{}) interface{} {
 	return vs[start:end]
 }
 
-func sliceString(v string, e, s interface{}) interface{} {
+func sliceString(v string, e, s any) any {
 	var start, end int
 	l := len([]rune(v))
 	if s != nil {
@@ -1086,10 +1101,10 @@ func clampIndex(i, min, max int) int {
 	}
 }
 
-func funcFlatten(v interface{}, args []interface{}) interface{} {
+func funcFlatten(v any, args []any) any {
 	vs, ok := values(v)
 	if !ok {
-		return &funcTypeError{"flatten", v}
+		return &func0TypeError{"flatten", v}
 	}
 	var depth float64
 	if len(args) == 0 {
@@ -1097,18 +1112,18 @@ func funcFlatten(v interface{}, args []interface{}) interface{} {
 	} else {
 		depth, ok = toFloat(args[0])
 		if !ok {
-			return &funcTypeError{"flatten", args[0]}
+			return &func0TypeError{"flatten", args[0]}
 		}
 		if depth < 0 {
 			return &flattenDepthError{depth}
 		}
 	}
-	return flatten(nil, vs, depth)
+	return flatten([]any{}, vs, depth)
 }
 
-func flatten(xs, vs []interface{}, depth float64) []interface{} {
+func flatten(xs, vs []any, depth float64) []any {
 	for _, v := range vs {
-		if vs, ok := v.([]interface{}); ok && depth != 0 {
+		if vs, ok := v.([]any); ok && depth != 0 {
 			xs = flatten(xs, vs, depth-1)
 		} else {
 			xs = append(xs, v)
@@ -1118,10 +1133,10 @@ func flatten(xs, vs []interface{}, depth float64) []interface{} {
 }
 
 type rangeIter struct {
-	value, end, step interface{}
+	value, end, step any
 }
 
-func (iter *rangeIter) Next() (interface{}, bool) {
+func (iter *rangeIter) Next() (any, bool) {
 	if compare(iter.step, 0)*compare(iter.value, iter.end) >= 0 {
 		return nil, false
 	}
@@ -1130,64 +1145,64 @@ func (iter *rangeIter) Next() (interface{}, bool) {
 	return v, true
 }
 
-func funcRange(_ interface{}, xs []interface{}) interface{} {
+func funcRange(_ any, xs []any) any {
 	for _, x := range xs {
 		switch x.(type) {
 		case int, float64, *big.Int:
 		default:
-			return &funcTypeError{"range", x}
+			return &func0TypeError{"range", x}
 		}
 	}
 	return &rangeIter{xs[0], xs[1], xs[2]}
 }
 
-func funcMin(v interface{}) interface{} {
-	vs, ok := v.([]interface{})
+func funcMin(v any) any {
+	vs, ok := v.([]any)
 	if !ok {
-		return &funcTypeError{"min", v}
+		return &func0TypeError{"min", v}
 	}
 	return minMaxBy(vs, vs, true)
 }
 
-func funcMinBy(v, x interface{}) interface{} {
-	vs, ok := v.([]interface{})
+func funcMinBy(v, x any) any {
+	vs, ok := v.([]any)
 	if !ok {
-		return &funcTypeError{"min_by", v}
+		return &func1TypeError{"min_by", v, x}
 	}
-	xs, ok := x.([]interface{})
+	xs, ok := x.([]any)
 	if !ok {
-		return &funcTypeError{"min_by", x}
+		return &func1TypeError{"min_by", v, x}
 	}
 	if len(vs) != len(xs) {
-		return &lengthMismatchError{"min_by", vs, xs}
+		return &func1WrapError{"min_by", v, x, &lengthMismatchError{}}
 	}
 	return minMaxBy(vs, xs, true)
 }
 
-func funcMax(v interface{}) interface{} {
-	vs, ok := v.([]interface{})
+func funcMax(v any) any {
+	vs, ok := v.([]any)
 	if !ok {
-		return &funcTypeError{"max", v}
+		return &func0TypeError{"max", v}
 	}
 	return minMaxBy(vs, vs, false)
 }
 
-func funcMaxBy(v, x interface{}) interface{} {
-	vs, ok := v.([]interface{})
+func funcMaxBy(v, x any) any {
+	vs, ok := v.([]any)
 	if !ok {
-		return &funcTypeError{"max_by", v}
+		return &func1TypeError{"max_by", v, x}
 	}
-	xs, ok := x.([]interface{})
+	xs, ok := x.([]any)
 	if !ok {
-		return &funcTypeError{"max_by", x}
+		return &func1TypeError{"max_by", v, x}
 	}
 	if len(vs) != len(xs) {
-		return &lengthMismatchError{"max_by", vs, xs}
+		return &func1WrapError{"max_by", v, x, &lengthMismatchError{}}
 	}
 	return minMaxBy(vs, xs, false)
 }
 
-func minMaxBy(vs, xs []interface{}, isMin bool) interface{} {
+func minMaxBy(vs, xs []any, isMin bool) any {
 	if len(vs) == 0 {
 		return nil
 	}
@@ -1201,20 +1216,23 @@ func minMaxBy(vs, xs []interface{}, isMin bool) interface{} {
 }
 
 type sortItem struct {
-	value, key interface{}
+	value, key any
 }
 
-func sortItems(name string, v, x interface{}) ([]*sortItem, error) {
-	vs, ok := v.([]interface{})
+func sortItems(name string, v, x any) ([]*sortItem, error) {
+	vs, ok := v.([]any)
 	if !ok {
-		return nil, &funcTypeError{name, v}
+		if strings.HasSuffix(name, "_by") {
+			return nil, &func1TypeError{name, v, x}
+		}
+		return nil, &func0TypeError{name, v}
 	}
-	xs, ok := x.([]interface{})
+	xs, ok := x.([]any)
 	if !ok {
-		return nil, &funcTypeError{name, x}
+		return nil, &func1TypeError{name, v, x}
 	}
 	if len(vs) != len(xs) {
-		return nil, &lengthMismatchError{name, vs, xs}
+		return nil, &func1WrapError{name, v, x, &lengthMismatchError{}}
 	}
 	items := make([]*sortItem, len(vs))
 	for i, v := range vs {
@@ -1226,58 +1244,58 @@ func sortItems(name string, v, x interface{}) ([]*sortItem, error) {
 	return items, nil
 }
 
-func funcSort(v interface{}) interface{} {
+func funcSort(v any) any {
 	return sortBy("sort", v, v)
 }
 
-func funcSortBy(v, x interface{}) interface{} {
+func funcSortBy(v, x any) any {
 	return sortBy("sort_by", v, x)
 }
 
-func sortBy(name string, v, x interface{}) interface{} {
+func sortBy(name string, v, x any) any {
 	items, err := sortItems(name, v, x)
 	if err != nil {
 		return err
 	}
-	rs := make([]interface{}, len(items))
+	rs := make([]any, len(items))
 	for i, x := range items {
 		rs[i] = x.value
 	}
 	return rs
 }
 
-func funcGroupBy(v, x interface{}) interface{} {
+func funcGroupBy(v, x any) any {
 	items, err := sortItems("group_by", v, x)
 	if err != nil {
 		return err
 	}
-	var rs []interface{}
-	var last interface{}
+	rs := []any{}
+	var last any
 	for i, r := range items {
 		if i == 0 || compare(last, r.key) != 0 {
-			rs, last = append(rs, []interface{}{r.value}), r.key
+			rs, last = append(rs, []any{r.value}), r.key
 		} else {
-			rs[len(rs)-1] = append(rs[len(rs)-1].([]interface{}), r.value)
+			rs[len(rs)-1] = append(rs[len(rs)-1].([]any), r.value)
 		}
 	}
 	return rs
 }
 
-func funcUnique(v interface{}) interface{} {
+func funcUnique(v any) any {
 	return uniqueBy("unique", v, v)
 }
 
-func funcUniqueBy(v, x interface{}) interface{} {
+func funcUniqueBy(v, x any) any {
 	return uniqueBy("unique_by", v, x)
 }
 
-func uniqueBy(name string, v, x interface{}) interface{} {
+func uniqueBy(name string, v, x any) any {
 	items, err := sortItems(name, v, x)
 	if err != nil {
 		return err
 	}
-	var rs []interface{}
-	var last interface{}
+	rs := []any{}
+	var last any
 	for i, r := range items {
 		if i == 0 || compare(last, r.key) != 0 {
 			rs, last = append(rs, r.value), r.key
@@ -1286,17 +1304,17 @@ func uniqueBy(name string, v, x interface{}) interface{} {
 	return rs
 }
 
-func funcJoin(v, x interface{}) interface{} {
+func funcJoin(v, x any) any {
 	vs, ok := values(v)
 	if !ok {
-		return &funcTypeError{"join", v}
+		return &func1TypeError{"join", v, x}
 	}
 	if len(vs) == 0 {
 		return ""
 	}
 	sep, ok := x.(string)
 	if len(vs) > 1 && !ok {
-		return &funcTypeError{"join", x}
+		return &func1TypeError{"join", v, x}
 	}
 	ss := make([]string, len(vs))
 	for i, v := range vs {
@@ -1330,22 +1348,22 @@ func funcExp10(v float64) float64 {
 	return math.Pow(10, v)
 }
 
-func funcFrexp(v interface{}) interface{} {
+func funcFrexp(v any) any {
 	x, ok := toFloat(v)
 	if !ok {
-		return &funcTypeError{"frexp", v}
+		return &func0TypeError{"frexp", v}
 	}
 	f, e := math.Frexp(x)
-	return []interface{}{f, e}
+	return []any{f, e}
 }
 
-func funcModf(v interface{}) interface{} {
+func funcModf(v any) any {
 	x, ok := toFloat(v)
 	if !ok {
-		return &funcTypeError{"modf", v}
+		return &func0TypeError{"modf", v}
 	}
 	i, f := math.Modf(x)
-	return []interface{}{f, i}
+	return []any{f, i}
 }
 
 func funcLgamma(v float64) float64 {
@@ -1381,36 +1399,36 @@ func funcYn(l, r float64) float64 {
 	return math.Yn(int(l), r)
 }
 
-func funcInfinite(interface{}) interface{} {
+func funcInfinite(any) any {
 	return math.Inf(1)
 }
 
-func funcIsfinite(v interface{}) interface{} {
+func funcIsfinite(v any) any {
 	x, ok := toFloat(v)
 	return ok && !math.IsInf(x, 0)
 }
 
-func funcIsinfinite(v interface{}) interface{} {
+func funcIsinfinite(v any) any {
 	x, ok := toFloat(v)
 	return ok && math.IsInf(x, 0)
 }
 
-func funcNan(interface{}) interface{} {
+func funcNan(any) any {
 	return math.NaN()
 }
 
-func funcIsnan(v interface{}) interface{} {
+func funcIsnan(v any) any {
 	x, ok := toFloat(v)
 	if !ok {
 		if v == nil {
 			return false
 		}
-		return &funcTypeError{"isnan", v}
+		return &func0TypeError{"isnan", v}
 	}
 	return math.IsNaN(x)
 }
 
-func funcIsnormal(v interface{}) interface{} {
+func funcIsnormal(v any) any {
 	if v, ok := toFloat(v); ok {
 		e := math.Float64bits(v) & 0x7ff0000000000000 >> 52
 		return 0 < e && e < 0x7ff
@@ -1424,72 +1442,69 @@ func funcIsnormal(v interface{}) interface{} {
 // functions.
 type allocator map[uintptr]struct{}
 
-func funcAllocator(interface{}, []interface{}) interface{} {
+func funcAllocator(any, []any) any {
 	return allocator{}
 }
 
-func (a allocator) allocated(v interface{}) bool {
+func (a allocator) allocated(v any) bool {
 	_, ok := a[reflect.ValueOf(v).Pointer()]
 	return ok
 }
 
-func (a allocator) makeObject(l int) map[string]interface{} {
-	v := make(map[string]interface{}, l)
+func (a allocator) makeObject(l int) map[string]any {
+	v := make(map[string]any, l)
 	if a != nil {
 		a[reflect.ValueOf(v).Pointer()] = struct{}{}
 	}
 	return v
 }
 
-func (a allocator) makeArray(l, c int) []interface{} {
+func (a allocator) makeArray(l, c int) []any {
 	if c < l {
 		c = l
 	}
-	v := make([]interface{}, l, c)
+	v := make([]any, l, c)
 	if a != nil {
 		a[reflect.ValueOf(v).Pointer()] = struct{}{}
 	}
 	return v
 }
 
-func funcSetpath(v, p, n interface{}) interface{} {
+func funcSetpath(v, p, n any) any {
 	// There is no need to use an allocator on a single update.
 	return setpath(v, p, n, nil)
 }
 
 // Used in compiler#compileAssign and compiler#compileModify.
-func funcSetpathWithAllocator(v interface{}, args []interface{}) interface{} {
+func funcSetpathWithAllocator(v any, args []any) any {
 	return setpath(v, args[0], args[1], args[2].(allocator))
 }
 
-func setpath(v, p, n interface{}, a allocator) interface{} {
-	path, ok := p.([]interface{})
+func setpath(v, p, n any, a allocator) any {
+	path, ok := p.([]any)
 	if !ok {
-		return &funcTypeError{"setpath", p}
+		return &func1TypeError{"setpath", v, p}
 	}
-	var err error
-	if v, err = update(v, path, n, a); err != nil {
-		if err, ok := err.(*funcTypeError); ok {
-			err.name = "setpath"
-		}
-		return err
+	u, err := update(v, path, n, a)
+	if err != nil {
+		return &func2WrapError{"setpath", v, p, n, err}
 	}
-	return v
+	return u
 }
 
-func funcDelpaths(v, p interface{}) interface{} {
+func funcDelpaths(v, p any) any {
 	return delpaths(v, p, allocator{})
 }
 
 // Used in compiler#compileAssign and compiler#compileModify.
-func funcDelpathsWithAllocator(v interface{}, args []interface{}) interface{} {
+func funcDelpathsWithAllocator(v any, args []any) any {
 	return delpaths(v, args[0], args[1].(allocator))
 }
 
-func delpaths(v, p interface{}, a allocator) interface{} {
-	paths, ok := p.([]interface{})
+func delpaths(v, p any, a allocator) any {
+	paths, ok := p.([]any)
 	if !ok {
-		return &funcTypeError{"delpaths", p}
+		return &func1TypeError{"delpaths", v, p}
 	}
 	if len(paths) == 0 {
 		return v
@@ -1499,19 +1514,21 @@ func delpaths(v, p interface{}, a allocator) interface{} {
 	//   jq -n "[0, 1, 2, 3] | delpaths([[1], [2]])" #=> [0, 3].
 	var empty struct{}
 	var err error
-	for _, p := range paths {
-		path, ok := p.([]interface{})
+	u := v
+	for _, q := range paths {
+		path, ok := q.([]any)
 		if !ok {
-			return &funcTypeError{"delpaths", p}
+			return &func1WrapError{"delpaths", v, p, &expectedArrayError{q}}
 		}
-		if v, err = update(v, path, empty, a); err != nil {
-			return err
+		u, err = update(u, path, empty, a)
+		if err != nil {
+			return &func1WrapError{"delpaths", v, p, err}
 		}
 	}
-	return deleteEmpty(v)
+	return deleteEmpty(u)
 }
 
-func update(v interface{}, path []interface{}, n interface{}, a allocator) (interface{}, error) {
+func update(v any, path []any, n any, a allocator) (any, error) {
 	if len(path) == 0 {
 		return n, nil
 	}
@@ -1520,7 +1537,7 @@ func update(v interface{}, path []interface{}, n interface{}, a allocator) (inte
 		switch v := v.(type) {
 		case nil:
 			return updateObject(nil, p, path[1:], n, a)
-		case map[string]interface{}:
+		case map[string]any:
 			return updateObject(v, p, path[1:], n, a)
 		case struct{}:
 			return v, nil
@@ -1532,18 +1549,18 @@ func update(v interface{}, path []interface{}, n interface{}, a allocator) (inte
 		switch v := v.(type) {
 		case nil:
 			return updateArrayIndex(nil, i, path[1:], n, a)
-		case []interface{}:
+		case []any:
 			return updateArrayIndex(v, i, path[1:], n, a)
 		case struct{}:
 			return v, nil
 		default:
 			return nil, &expectedArrayError{v}
 		}
-	case map[string]interface{}:
+	case map[string]any:
 		switch v := v.(type) {
 		case nil:
 			return updateArraySlice(nil, p, path[1:], n, a)
-		case []interface{}:
+		case []any:
 			return updateArraySlice(v, p, path[1:], n, a)
 		case struct{}:
 			return v, nil
@@ -1552,7 +1569,7 @@ func update(v interface{}, path []interface{}, n interface{}, a allocator) (inte
 		}
 	default:
 		switch v.(type) {
-		case []interface{}:
+		case []any:
 			return nil, &arrayIndexNotNumberError{p}
 		default:
 			return nil, &objectKeyNotStringError{p}
@@ -1560,7 +1577,7 @@ func update(v interface{}, path []interface{}, n interface{}, a allocator) (inte
 	}
 }
 
-func updateObject(v map[string]interface{}, k string, path []interface{}, n interface{}, a allocator) (interface{}, error) {
+func updateObject(v map[string]any, k string, path []any, n any, a allocator) (any, error) {
 	x, ok := v[k]
 	if !ok && n == struct{}{} {
 		return v, nil
@@ -1581,13 +1598,13 @@ func updateObject(v map[string]interface{}, k string, path []interface{}, n inte
 	return w, nil
 }
 
-func updateArrayIndex(v []interface{}, i int, path []interface{}, n interface{}, a allocator) (interface{}, error) {
-	var x interface{}
+func updateArrayIndex(v []any, i int, path []any, n any, a allocator) (any, error) {
+	var x any
 	if j := clampIndex(i, -1, len(v)); j < 0 {
 		if n == struct{}{} {
 			return v, nil
 		}
-		return nil, &funcTypeError{v: i}
+		return nil, &arrayIndexNegativeError{i}
 	} else if j < len(v) {
 		i = j
 		x = v[i]
@@ -1623,7 +1640,7 @@ func updateArrayIndex(v []interface{}, i int, path []interface{}, n interface{},
 	return w, nil
 }
 
-func updateArraySlice(v []interface{}, m map[string]interface{}, path []interface{}, n interface{}, a allocator) (interface{}, error) {
+func updateArraySlice(v []any, m map[string]any, path []any, n any, a allocator) (any, error) {
 	s, ok := m["start"]
 	if !ok {
 		return nil, &expectedStartEndError{m}
@@ -1649,8 +1666,8 @@ func updateArraySlice(v []interface{}, m map[string]interface{}, path []interfac
 		return nil, err
 	}
 	switch u := u.(type) {
-	case []interface{}:
-		var w []interface{}
+	case []any:
+		var w []any
 		if len(u) == end-start && a.allocated(v) {
 			w = v
 		} else {
@@ -1661,7 +1678,7 @@ func updateArraySlice(v []interface{}, m map[string]interface{}, path []interfac
 		copy(w[start:], u)
 		return w, nil
 	case struct{}:
-		var w []interface{}
+		var w []any
 		if a.allocated(v) {
 			w = v
 		} else {
@@ -1677,11 +1694,11 @@ func updateArraySlice(v []interface{}, m map[string]interface{}, path []interfac
 	}
 }
 
-func deleteEmpty(v interface{}) interface{} {
+func deleteEmpty(v any) any {
 	switch v := v.(type) {
 	case struct{}:
 		return nil
-	case map[string]interface{}:
+	case map[string]any:
 		for k, w := range v {
 			if w == struct{}{} {
 				delete(v, k)
@@ -1690,7 +1707,7 @@ func deleteEmpty(v interface{}) interface{} {
 			}
 		}
 		return v
-	case []interface{}:
+	case []any:
 		var j int
 		for _, w := range v {
 			if w != struct{}{} {
@@ -1707,63 +1724,63 @@ func deleteEmpty(v interface{}) interface{} {
 	}
 }
 
-func funcGetpath(v, p interface{}) interface{} {
-	keys, ok := p.([]interface{})
+func funcGetpath(v, p any) any {
+	path, ok := p.([]any)
 	if !ok {
-		return &funcTypeError{"getpath", p}
+		return &func1TypeError{"getpath", v, p}
 	}
 	u := v
-	for _, x := range keys {
+	for _, x := range path {
 		switch v.(type) {
-		case nil, []interface{}, map[string]interface{}:
+		case nil, []any, map[string]any:
 			v = funcIndex2(nil, v, x)
-			if _, ok := v.(error); ok {
-				return &getpathError{u, p}
+			if err, ok := v.(error); ok {
+				return &func1WrapError{"getpath", u, p, err}
 			}
 		default:
-			return &getpathError{u, p}
+			return &func1TypeError{"getpath", u, p}
 		}
 	}
 	return v
 }
 
-func funcTranspose(v interface{}) interface{} {
-	vss, ok := v.([]interface{})
+func funcTranspose(v any) any {
+	vss, ok := v.([]any)
 	if !ok {
-		return &funcTypeError{"transpose", v}
+		return &func0TypeError{"transpose", v}
 	}
 	if len(vss) == 0 {
-		return []interface{}{}
+		return []any{}
 	}
 	var l int
 	for _, vs := range vss {
-		vs, ok := vs.([]interface{})
+		vs, ok := vs.([]any)
 		if !ok {
-			return &funcTypeError{"transpose", v}
+			return &func0TypeError{"transpose", v}
 		}
 		if k := len(vs); l < k {
 			l = k
 		}
 	}
-	wss := make([][]interface{}, l)
-	xs := make([]interface{}, l)
+	wss := make([][]any, l)
+	xs := make([]any, l)
 	for i, k := 0, len(vss); i < l; i++ {
-		s := make([]interface{}, k)
+		s := make([]any, k)
 		wss[i] = s
 		xs[i] = s
 	}
 	for i, vs := range vss {
-		for j, v := range vs.([]interface{}) {
+		for j, v := range vs.([]any) {
 			wss[j][i] = v
 		}
 	}
 	return xs
 }
 
-func funcBsearch(v, t interface{}) interface{} {
-	vs, ok := v.([]interface{})
+func funcBsearch(v, t any) any {
+	vs, ok := v.([]any)
 	if !ok {
-		return &funcTypeError{"bsearch", v}
+		return &func1TypeError{"bsearch", v, t}
 	}
 	i := sort.Search(len(vs), func(i int) bool {
 		return compare(vs[i], t) >= 0
@@ -1774,23 +1791,23 @@ func funcBsearch(v, t interface{}) interface{} {
 	return -i - 1
 }
 
-func funcGmtime(v interface{}) interface{} {
+func funcGmtime(v any) any {
 	if v, ok := toFloat(v); ok {
 		return epochToArray(v, time.UTC)
 	}
-	return &funcTypeError{"gmtime", v}
+	return &func0TypeError{"gmtime", v}
 }
 
-func funcLocaltime(v interface{}) interface{} {
+func funcLocaltime(v any) any {
 	if v, ok := toFloat(v); ok {
 		return epochToArray(v, time.Local)
 	}
-	return &funcTypeError{"localtime", v}
+	return &func0TypeError{"localtime", v}
 }
 
-func epochToArray(v float64, loc *time.Location) []interface{} {
+func epochToArray(v float64, loc *time.Location) []any {
 	t := time.Unix(int64(v), int64((v-math.Floor(v))*1e9)).In(loc)
-	return []interface{}{
+	return []any{
 		t.Year(),
 		int(t.Month()) - 1,
 		t.Day(),
@@ -1802,133 +1819,143 @@ func epochToArray(v float64, loc *time.Location) []interface{} {
 	}
 }
 
-func funcMktime(v interface{}) interface{} {
-	if a, ok := v.([]interface{}); ok {
-		t, err := arrayToTime("mktime", a, time.UTC)
-		if err != nil {
-			return err
-		}
-		return timeToEpoch(t)
+func funcMktime(v any) any {
+	a, ok := v.([]any)
+	if !ok {
+		return &func0TypeError{"mktime", v}
 	}
-	return &funcTypeError{"mktime", v}
+	t, err := arrayToTime(a, time.UTC)
+	if err != nil {
+		return &func0WrapError{"mktime", v, err}
+	}
+	return timeToEpoch(t)
 }
 
 func timeToEpoch(t time.Time) float64 {
 	return float64(t.Unix()) + float64(t.Nanosecond())/1e9
 }
 
-func funcStrftime(v, x interface{}) interface{} {
+func funcStrftime(v, x any) any {
 	if w, ok := toFloat(v); ok {
 		v = epochToArray(w, time.UTC)
 	}
-	if a, ok := v.([]interface{}); ok {
-		if format, ok := x.(string); ok {
-			t, err := arrayToTime("strftime", a, time.UTC)
-			if err != nil {
-				return err
-			}
-			return timefmt.Format(t, format)
-		}
-		return &funcTypeError{"strftime", x}
+	a, ok := v.([]any)
+	if !ok {
+		return &func1TypeError{"strftime", v, x}
+	}
+	format, ok := x.(string)
+	if !ok {
+		return &func1TypeError{"strftime", v, x}
+	}
+	t, err := arrayToTime(a, time.UTC)
+	if err != nil {
+		return &func1WrapError{"strftime", v, x, err}
 	}
-	return &funcTypeError{"strftime", v}
+	return timefmt.Format(t, format)
 }
 
-func funcStrflocaltime(v, x interface{}) interface{} {
+func funcStrflocaltime(v, x any) any {
 	if w, ok := toFloat(v); ok {
 		v = epochToArray(w, time.Local)
 	}
-	if a, ok := v.([]interface{}); ok {
-		if format, ok := x.(string); ok {
-			t, err := arrayToTime("strflocaltime", a, time.Local)
-			if err != nil {
-				return err
-			}
-			return timefmt.Format(t, format)
-		}
-		return &funcTypeError{"strflocaltime", x}
+	a, ok := v.([]any)
+	if !ok {
+		return &func1TypeError{"strflocaltime", v, x}
 	}
-	return &funcTypeError{"strflocaltime", v}
+	format, ok := x.(string)
+	if !ok {
+		return &func1TypeError{"strflocaltime", v, x}
+	}
+	t, err := arrayToTime(a, time.Local)
+	if err != nil {
+		return &func1WrapError{"strflocaltime", v, x, err}
+	}
+	return timefmt.Format(t, format)
 }
 
-func funcStrptime(v, x interface{}) interface{} {
-	if v, ok := v.(string); ok {
-		if format, ok := x.(string); ok {
-			t, err := timefmt.Parse(v, format)
-			if err != nil {
-				return err
-			}
-			var s time.Time
-			if t == s {
-				return &funcTypeError{"strptime", v}
-			}
-			return epochToArray(timeToEpoch(t), time.UTC)
-		}
-		return &funcTypeError{"strptime", x}
+func funcStrptime(v, x any) any {
+	s, ok := v.(string)
+	if !ok {
+		return &func1TypeError{"strptime", v, x}
+	}
+	format, ok := x.(string)
+	if !ok {
+		return &func1TypeError{"strptime", v, x}
+	}
+	t, err := timefmt.Parse(s, format)
+	if err != nil {
+		return &func1WrapError{"strptime", v, x, err}
+	}
+	var u time.Time
+	if t == u {
+		return &func1TypeError{"strptime", v, x}
 	}
-	return &funcTypeError{"strptime", v}
+	return epochToArray(timeToEpoch(t), time.UTC)
 }
 
-func arrayToTime(name string, a []interface{}, loc *time.Location) (time.Time, error) {
+func arrayToTime(a []any, loc *time.Location) (time.Time, error) {
 	var t time.Time
 	if len(a) != 8 {
-		return t, &funcTypeError{name, a}
+		return t, &timeArrayError{}
 	}
 	var y, m, d, h, min, sec, nsec int
-	if x, ok := toInt(a[0]); ok {
-		y = x
-	} else {
-		return t, &funcTypeError{name, a}
+	var ok bool
+	if y, ok = toInt(a[0]); !ok {
+		return t, &timeArrayError{}
 	}
-	if x, ok := toInt(a[1]); ok {
-		m = x + 1
+	if m, ok = toInt(a[1]); ok {
+		m++
 	} else {
-		return t, &funcTypeError{name, a}
+		return t, &timeArrayError{}
 	}
-	if x, ok := toInt(a[2]); ok {
-		d = x
-	} else {
-		return t, &funcTypeError{name, a}
+	if d, ok = toInt(a[2]); !ok {
+		return t, &timeArrayError{}
 	}
-	if x, ok := toInt(a[3]); ok {
-		h = x
-	} else {
-		return t, &funcTypeError{name, a}
+	if h, ok = toInt(a[3]); !ok {
+		return t, &timeArrayError{}
 	}
-	if x, ok := toInt(a[4]); ok {
-		min = x
-	} else {
-		return t, &funcTypeError{name, a}
+	if min, ok = toInt(a[4]); !ok {
+		return t, &timeArrayError{}
 	}
 	if x, ok := toFloat(a[5]); ok {
 		sec = int(x)
 		nsec = int((x - math.Floor(x)) * 1e9)
 	} else {
-		return t, &funcTypeError{name, a}
+		return t, &timeArrayError{}
+	}
+	if _, ok = toFloat(a[6]); !ok {
+		return t, &timeArrayError{}
+	}
+	if _, ok = toFloat(a[7]); !ok {
+		return t, &timeArrayError{}
 	}
 	return time.Date(y, time.Month(m), d, h, min, sec, nsec, loc), nil
 }
 
-func funcNow(interface{}) interface{} {
+func funcNow(any) any {
 	return timeToEpoch(time.Now())
 }
 
-func funcMatch(v, re, fs, testing interface{}) interface{} {
+func funcMatch(v, re, fs, testing any) any {
+	name := "match"
+	if testing == true {
+		name = "test"
+	}
 	var flags string
 	if fs != nil {
 		v, ok := fs.(string)
 		if !ok {
-			return &funcTypeError{"match", fs}
+			return &func2TypeError{name, v, re, fs}
 		}
 		flags = v
 	}
 	s, ok := v.(string)
 	if !ok {
-		return &funcTypeError{"match", v}
+		return &func2TypeError{name, v, re, fs}
 	}
 	restr, ok := re.(string)
 	if !ok {
-		return &funcTypeError{"match", v}
+		return &func2TypeError{name, v, re, fs}
 	}
 	r, err := compileRegexp(restr, flags)
 	if err != nil {
@@ -1946,16 +1973,16 @@ func funcMatch(v, re, fs, testing interface{}) interface{} {
 			xs = [][]int{got}
 		}
 	}
-	res, names := make([]interface{}, len(xs)), r.SubexpNames()
+	res, names := make([]any, len(xs)), r.SubexpNames()
 	for i, x := range xs {
-		captures := make([]interface{}, (len(x)-2)/2)
+		captures := make([]any, (len(x)-2)/2)
 		for j := 1; j < len(x)/2; j++ {
-			var name interface{}
+			var name any
 			if n := names[j]; n != "" {
 				name = n
 			}
 			if x[j*2] < 0 {
-				captures[j-1] = map[string]interface{}{
+				captures[j-1] = map[string]any{
 					"name":   name,
 					"offset": -1,
 					"length": 0,
@@ -1963,14 +1990,14 @@ func funcMatch(v, re, fs, testing interface{}) interface{} {
 				}
 				continue
 			}
-			captures[j-1] = map[string]interface{}{
+			captures[j-1] = map[string]any{
 				"name":   name,
 				"offset": len([]rune(s[:x[j*2]])),
 				"length": len([]rune(s[:x[j*2+1]])) - len([]rune(s[:x[j*2]])),
 				"string": s[x[j*2]:x[j*2+1]],
 			}
 		}
-		res[i] = map[string]interface{}{
+		res[i] = map[string]any{
 			"offset":   len([]rune(s[:x[0]])),
 			"length":   len([]rune(s[:x[1]])) - len([]rune(s[:x[0]])),
 			"string":   s[x[0]:x[1]],
@@ -2000,19 +2027,19 @@ func compileRegexp(re, flags string) (*regexp.Regexp, error) {
 	return r, nil
 }
 
-func funcCapture(v interface{}) interface{} {
-	vs, ok := v.(map[string]interface{})
+func funcCapture(v any) any {
+	vs, ok := v.(map[string]any)
 	if !ok {
 		return &expectedObjectError{v}
 	}
 	v = vs["captures"]
-	captures, ok := v.([]interface{})
+	captures, ok := v.([]any)
 	if !ok {
 		return &expectedArrayError{v}
 	}
-	w := make(map[string]interface{}, len(captures))
+	w := make(map[string]any, len(captures))
 	for _, capture := range captures {
-		if capture, ok := capture.(map[string]interface{}); ok {
+		if capture, ok := capture.(map[string]any); ok {
 			if name, ok := capture["name"].(string); ok {
 				w[name] = capture["string"]
 			}
@@ -2021,7 +2048,7 @@ func funcCapture(v interface{}) interface{} {
 	return w
 }
 
-func funcError(v interface{}, args []interface{}) interface{} {
+func funcError(v any, args []any) any {
 	if len(args) > 0 {
 		v = args[0]
 	}
@@ -2032,22 +2059,22 @@ func funcError(v interface{}, args []interface{}) interface{} {
 	return &exitCodeError{v, code, false}
 }
 
-func funcHalt(interface{}) interface{} {
+func funcHalt(any) any {
 	return &exitCodeError{nil, 0, true}
 }
 
-func funcHaltError(v interface{}, args []interface{}) interface{} {
+func funcHaltError(v any, args []any) any {
 	code := 5
 	if len(args) > 0 {
 		var ok bool
 		if code, ok = toInt(args[0]); !ok {
-			return &funcTypeError{"halt_error", args[0]}
+			return &func0TypeError{"halt_error", args[0]}
 		}
 	}
 	return &exitCodeError{v, code, true}
 }
 
-func toInt(x interface{}) (int, bool) {
+func toInt(x any) (int, bool) {
 	switch x := x.(type) {
 	case int:
 		return x, true
@@ -2078,7 +2105,7 @@ func floatToInt(x float64) int {
 	return math.MinInt
 }
 
-func toFloat(x interface{}) (float64, bool) {
+func toFloat(x any) (float64, bool) {
 	switch x := x.(type) {
 	case int:
 		return float64(x), true
diff --git a/go.dev.mod b/go.dev.mod
index 26dfb59..9a0579c 100644
--- a/go.dev.mod
+++ b/go.dev.mod
@@ -1,6 +1,6 @@
 module github.com/itchyny/gojq
 
-go 1.17
+go 1.18
 
 require (
 	github.com/itchyny/astgen-go v0.0.0-20210914105503-cc8fccf6f972 // indirect
diff --git a/go.mod b/go.mod
index 7cfd97e..8b12ad4 100644
--- a/go.mod
+++ b/go.mod
@@ -1,16 +1,16 @@
 module github.com/itchyny/gojq
 
-go 1.17
+go 1.18
 
 require (
 	github.com/google/go-cmp v0.5.4
 	github.com/itchyny/timefmt-go v0.1.5
-	github.com/mattn/go-isatty v0.0.16
+	github.com/mattn/go-isatty v0.0.19
 	github.com/mattn/go-runewidth v0.0.14
 	gopkg.in/yaml.v3 v3.0.1
 )
 
 require (
-	github.com/rivo/uniseg v0.2.0 // indirect
-	golang.org/x/sys v0.2.0 // indirect
+	github.com/rivo/uniseg v0.4.4 // indirect
+	golang.org/x/sys v0.8.0 // indirect
 )
diff --git a/go.sum b/go.sum
index b5d4dd1..5b4e692 100644
--- a/go.sum
+++ b/go.sum
@@ -2,15 +2,16 @@ github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
 github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE=
 github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8=
-github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
-github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
+github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
 github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
 github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
-github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
 github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
-golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
-golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
+github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
diff --git a/iter.go b/iter.go
index 9ee5ad6..d0bed96 100644
--- a/iter.go
+++ b/iter.go
@@ -2,11 +2,11 @@ package gojq
 
 // Iter is an interface for an iterator.
 type Iter interface {
-	Next() (interface{}, bool)
+	Next() (any, bool)
 }
 
 // NewIter creates a new [Iter] from values.
-func NewIter(values ...interface{}) Iter {
+func NewIter(values ...any) Iter {
 	switch len(values) {
 	case 0:
 		return emptyIter{}
@@ -20,16 +20,16 @@ func NewIter(values ...interface{}) Iter {
 
 type emptyIter struct{}
 
-func (emptyIter) Next() (interface{}, bool) {
+func (emptyIter) Next() (any, bool) {
 	return nil, false
 }
 
 type unitIter struct {
-	value interface{}
+	value any
 	done  bool
 }
 
-func (iter *unitIter) Next() (interface{}, bool) {
+func (iter *unitIter) Next() (any, bool) {
 	if iter.done {
 		return nil, false
 	}
@@ -37,9 +37,9 @@ func (iter *unitIter) Next() (interface{}, bool) {
 	return iter.value, true
 }
 
-type sliceIter []interface{}
+type sliceIter []any
 
-func (iter *sliceIter) Next() (interface{}, bool) {
+func (iter *sliceIter) Next() (any, bool) {
 	if len(*iter) == 0 {
 		return nil, false
 	}
diff --git a/module_loader.go b/module_loader.go
index fff442d..599e37b 100644
--- a/module_loader.go
+++ b/module_loader.go
@@ -14,11 +14,11 @@ import (
 // Implement following optional methods. Use [NewModuleLoader] to load local modules.
 //
 //	LoadModule(string) (*Query, error)
-//	LoadModuleWithMeta(string, map[string]interface{}) (*Query, error)
+//	LoadModuleWithMeta(string, map[string]any) (*Query, error)
 //	LoadInitModules() ([]*Query, error)
-//	LoadJSON(string) (interface{}, error)
-//	LoadJSONWithMeta(string, map[string]interface{}) (interface{}, error)
-type ModuleLoader interface{}
+//	LoadJSON(string) (any, error)
+//	LoadJSONWithMeta(string, map[string]any) (any, error)
+type ModuleLoader any
 
 // NewModuleLoader creates a new [ModuleLoader] reading local modules in the paths.
 func NewModuleLoader(paths []string) ModuleLoader {
@@ -58,7 +58,7 @@ func (l *moduleLoader) LoadInitModules() ([]*Query, error) {
 	return qs, nil
 }
 
-func (l *moduleLoader) LoadModuleWithMeta(name string, meta map[string]interface{}) (*Query, error) {
+func (l *moduleLoader) LoadModuleWithMeta(name string, meta map[string]any) (*Query, error) {
 	path, err := l.lookupModule(name, ".jq", meta)
 	if err != nil {
 		return nil, err
@@ -74,7 +74,7 @@ func (l *moduleLoader) LoadModuleWithMeta(name string, meta map[string]interface
 	return q, nil
 }
 
-func (l *moduleLoader) LoadJSONWithMeta(name string, meta map[string]interface{}) (interface{}, error) {
+func (l *moduleLoader) LoadJSONWithMeta(name string, meta map[string]any) (any, error) {
 	path, err := l.lookupModule(name, ".json", meta)
 	if err != nil {
 		return nil, err
@@ -84,11 +84,11 @@ func (l *moduleLoader) LoadJSONWithMeta(name string, meta map[string]interface{}
 		return nil, err
 	}
 	defer f.Close()
-	var vals []interface{}
+	vals := []any{}
 	dec := json.NewDecoder(f)
 	dec.UseNumber()
 	for {
-		var val interface{}
+		var val any
 		if err := dec.Decode(&val); err != nil {
 			if err == io.EOF {
 				break
@@ -107,7 +107,7 @@ func (l *moduleLoader) LoadJSONWithMeta(name string, meta map[string]interface{}
 	return vals, nil
 }
 
-func (l *moduleLoader) lookupModule(name, extension string, meta map[string]interface{}) (string, error) {
+func (l *moduleLoader) lookupModule(name, extension string, meta map[string]any) (string, error) {
 	paths := l.paths
 	if path := searchPath(meta); path != "" {
 		paths = append([]string{path}, paths...)
@@ -146,7 +146,7 @@ func parseModule(path, cnt string) (*Query, error) {
 	return q, nil
 }
 
-func searchPath(meta map[string]interface{}) string {
+func searchPath(meta map[string]any) string {
 	x, ok := meta["search"]
 	if !ok {
 		return ""
diff --git a/normalize.go b/normalize.go
index bd0ddda..2bfcd21 100644
--- a/normalize.go
+++ b/normalize.go
@@ -7,7 +7,7 @@ import (
 	"strings"
 )
 
-func normalizeNumber(v json.Number) interface{} {
+func normalizeNumber(v json.Number) any {
 	if i, err := v.Int64(); err == nil && math.MinInt <= i && i <= math.MaxInt {
 		return int(i)
 	}
@@ -25,7 +25,7 @@ func normalizeNumber(v json.Number) interface{} {
 	return math.Inf(1)
 }
 
-func normalizeNumbers(v interface{}) interface{} {
+func normalizeNumbers(v any) any {
 	switch v := v.(type) {
 	case json.Number:
 		return normalizeNumber(v)
@@ -68,12 +68,12 @@ func normalizeNumbers(v interface{}) interface{} {
 		return int(v)
 	case float32:
 		return float64(v)
-	case []interface{}:
+	case []any:
 		for i, x := range v {
 			v[i] = normalizeNumbers(x)
 		}
 		return v
-	case map[string]interface{}:
+	case map[string]any:
 		for k, x := range v {
 			v[k] = normalizeNumbers(x)
 		}
diff --git a/operator.go b/operator.go
index 071b3d6..73a548e 100644
--- a/operator.go
+++ b/operator.go
@@ -208,14 +208,14 @@ func (op Operator) getFunc() string {
 }
 
 func binopTypeSwitch(
-	l, r interface{},
-	callbackInts func(_, _ int) interface{},
-	callbackFloats func(_, _ float64) interface{},
-	callbackBigInts func(_, _ *big.Int) interface{},
-	callbackStrings func(_, _ string) interface{},
-	callbackArrays func(_, _ []interface{}) interface{},
-	callbackMaps func(_, _ map[string]interface{}) interface{},
-	fallback func(_, _ interface{}) interface{}) interface{} {
+	l, r any,
+	callbackInts func(_, _ int) any,
+	callbackFloats func(_, _ float64) any,
+	callbackBigInts func(_, _ *big.Int) any,
+	callbackStrings func(_, _ string) any,
+	callbackArrays func(_, _ []any) any,
+	callbackMaps func(_, _ map[string]any) any,
+	fallback func(_, _ any) any) any {
 	switch l := l.(type) {
 	case int:
 		switch r := r.(type) {
@@ -257,16 +257,16 @@ func binopTypeSwitch(
 		default:
 			return fallback(l, r)
 		}
-	case []interface{}:
+	case []any:
 		switch r := r.(type) {
-		case []interface{}:
+		case []any:
 			return callbackArrays(l, r)
 		default:
 			return fallback(l, r)
 		}
-	case map[string]interface{}:
+	case map[string]any:
 		switch r := r.(type) {
-		case map[string]interface{}:
+		case map[string]any:
 			return callbackMaps(l, r)
 		default:
 			return fallback(l, r)
@@ -276,7 +276,7 @@ func binopTypeSwitch(
 	}
 }
 
-func funcOpPlus(v interface{}) interface{} {
+func funcOpPlus(v any) any {
 	switch v := v.(type) {
 	case int:
 		return v
@@ -289,7 +289,7 @@ func funcOpPlus(v interface{}) interface{} {
 	}
 }
 
-func funcOpNegate(v interface{}) interface{} {
+func funcOpNegate(v any) any {
 	switch v := v.(type) {
 	case int:
 		return -v
@@ -302,38 +302,38 @@ func funcOpNegate(v interface{}) interface{} {
 	}
 }
 
-func funcOpAdd(_, l, r interface{}) interface{} {
+func funcOpAdd(_, l, r any) any {
 	return binopTypeSwitch(l, r,
-		func(l, r int) interface{} {
+		func(l, r int) any {
 			if v := l + r; (v >= l) == (r >= 0) {
 				return v
 			}
 			x, y := big.NewInt(int64(l)), big.NewInt(int64(r))
 			return x.Add(x, y)
 		},
-		func(l, r float64) interface{} { return l + r },
-		func(l, r *big.Int) interface{} { return new(big.Int).Add(l, r) },
-		func(l, r string) interface{} { return l + r },
-		func(l, r []interface{}) interface{} {
+		func(l, r float64) any { return l + r },
+		func(l, r *big.Int) any { return new(big.Int).Add(l, r) },
+		func(l, r string) any { return l + r },
+		func(l, r []any) any {
 			if len(l) == 0 {
 				return r
 			}
 			if len(r) == 0 {
 				return l
 			}
-			v := make([]interface{}, len(l)+len(r))
+			v := make([]any, len(l)+len(r))
 			copy(v, l)
 			copy(v[len(l):], r)
 			return v
 		},
-		func(l, r map[string]interface{}) interface{} {
+		func(l, r map[string]any) any {
 			if len(l) == 0 {
 				return r
 			}
 			if len(r) == 0 {
 				return l
 			}
-			m := make(map[string]interface{}, len(l)+len(r))
+			m := make(map[string]any, len(l)+len(r))
 			for k, v := range l {
 				m[k] = v
 			}
@@ -342,7 +342,7 @@ func funcOpAdd(_, l, r interface{}) interface{} {
 			}
 			return m
 		},
-		func(l, r interface{}) interface{} {
+		func(l, r any) any {
 			if l == nil {
 				return r
 			}
@@ -354,20 +354,20 @@ func funcOpAdd(_, l, r interface{}) interface{} {
 	)
 }
 
-func funcOpSub(_, l, r interface{}) interface{} {
+func funcOpSub(_, l, r any) any {
 	return binopTypeSwitch(l, r,
-		func(l, r int) interface{} {
+		func(l, r int) any {
 			if v := l - r; (v <= l) == (r >= 0) {
 				return v
 			}
 			x, y := big.NewInt(int64(l)), big.NewInt(int64(r))
 			return x.Sub(x, y)
 		},
-		func(l, r float64) interface{} { return l - r },
-		func(l, r *big.Int) interface{} { return new(big.Int).Sub(l, r) },
-		func(l, r string) interface{} { return &binopTypeError{"subtract", l, r} },
-		func(l, r []interface{}) interface{} {
-			v := make([]interface{}, 0, len(l))
+		func(l, r float64) any { return l - r },
+		func(l, r *big.Int) any { return new(big.Int).Sub(l, r) },
+		func(l, r string) any { return &binopTypeError{"subtract", l, r} },
+		func(l, r []any) any {
+			v := make([]any, 0, len(l))
 		L:
 			for _, l := range l {
 				for _, r := range r {
@@ -379,26 +379,26 @@ func funcOpSub(_, l, r interface{}) interface{} {
 			}
 			return v
 		},
-		func(l, r map[string]interface{}) interface{} { return &binopTypeError{"subtract", l, r} },
-		func(l, r interface{}) interface{} { return &binopTypeError{"subtract", l, r} },
+		func(l, r map[string]any) any { return &binopTypeError{"subtract", l, r} },
+		func(l, r any) any { return &binopTypeError{"subtract", l, r} },
 	)
 }
 
-func funcOpMul(_, l, r interface{}) interface{} {
+func funcOpMul(_, l, r any) any {
 	return binopTypeSwitch(l, r,
-		func(l, r int) interface{} {
+		func(l, r int) any {
 			if v := l * r; r == 0 || v/r == l {
 				return v
 			}
 			x, y := big.NewInt(int64(l)), big.NewInt(int64(r))
 			return x.Mul(x, y)
 		},
-		func(l, r float64) interface{} { return l * r },
-		func(l, r *big.Int) interface{} { return new(big.Int).Mul(l, r) },
-		func(l, r string) interface{} { return &binopTypeError{"multiply", l, r} },
-		func(l, r []interface{}) interface{} { return &binopTypeError{"multiply", l, r} },
+		func(l, r float64) any { return l * r },
+		func(l, r *big.Int) any { return new(big.Int).Mul(l, r) },
+		func(l, r string) any { return &binopTypeError{"multiply", l, r} },
+		func(l, r []any) any { return &binopTypeError{"multiply", l, r} },
 		deepMergeObjects,
-		func(l, r interface{}) interface{} {
+		func(l, r any) any {
 			if l, ok := l.(string); ok {
 				if r, ok := toFloat(r); ok {
 					return repeatString(l, r)
@@ -414,15 +414,15 @@ func funcOpMul(_, l, r interface{}) interface{} {
 	)
 }
 
-func deepMergeObjects(l, r map[string]interface{}) interface{} {
-	m := make(map[string]interface{}, len(l)+len(r))
+func deepMergeObjects(l, r map[string]any) any {
+	m := make(map[string]any, len(l)+len(r))
 	for k, v := range l {
 		m[k] = v
 	}
 	for k, v := range r {
 		if mk, ok := m[k]; ok {
-			if mk, ok := mk.(map[string]interface{}); ok {
-				if w, ok := v.(map[string]interface{}); ok {
+			if mk, ok := mk.(map[string]any); ok {
+				if w, ok := v.(map[string]any); ok {
 					v = deepMergeObjects(mk, w)
 				}
 			}
@@ -432,19 +432,19 @@ func deepMergeObjects(l, r map[string]interface{}) interface{} {
 	return m
 }
 
-func repeatString(s string, n float64) interface{} {
+func repeatString(s string, n float64) any {
 	if n <= 0.0 || len(s) > 0 && n > float64(0x10000000/len(s)) || math.IsNaN(n) {
 		return nil
 	}
-	if n < 1.0 {
+	if int(n) < 1 {
 		return s
 	}
 	return strings.Repeat(s, int(n))
 }
 
-func funcOpDiv(_, l, r interface{}) interface{} {
+func funcOpDiv(_, l, r any) any {
 	return binopTypeSwitch(l, r,
-		func(l, r int) interface{} {
+		func(l, r int) any {
 			if r == 0 {
 				if l == 0 {
 					return math.NaN()
@@ -456,7 +456,7 @@ func funcOpDiv(_, l, r interface{}) interface{} {
 			}
 			return float64(l) / float64(r)
 		},
-		func(l, r float64) interface{} {
+		func(l, r float64) any {
 			if r == 0.0 {
 				if l == 0.0 {
 					return math.NaN()
@@ -465,7 +465,7 @@ func funcOpDiv(_, l, r interface{}) interface{} {
 			}
 			return l / r
 		},
-		func(l, r *big.Int) interface{} {
+		func(l, r *big.Int) any {
 			if r.Sign() == 0 {
 				if l.Sign() == 0 {
 					return math.NaN()
@@ -478,78 +478,78 @@ func funcOpDiv(_, l, r interface{}) interface{} {
 			}
 			return bigToFloat(l) / bigToFloat(r)
 		},
-		func(l, r string) interface{} {
+		func(l, r string) any {
 			if l == "" {
-				return []interface{}{}
+				return []any{}
 			}
 			xs := strings.Split(l, r)
-			vs := make([]interface{}, len(xs))
+			vs := make([]any, len(xs))
 			for i, x := range xs {
 				vs[i] = x
 			}
 			return vs
 		},
-		func(l, r []interface{}) interface{} { return &binopTypeError{"divide", l, r} },
-		func(l, r map[string]interface{}) interface{} { return &binopTypeError{"divide", l, r} },
-		func(l, r interface{}) interface{} { return &binopTypeError{"divide", l, r} },
+		func(l, r []any) any { return &binopTypeError{"divide", l, r} },
+		func(l, r map[string]any) any { return &binopTypeError{"divide", l, r} },
+		func(l, r any) any { return &binopTypeError{"divide", l, r} },
 	)
 }
 
-func funcOpMod(_, l, r interface{}) interface{} {
+func funcOpMod(_, l, r any) any {
 	return binopTypeSwitch(l, r,
-		func(l, r int) interface{} {
+		func(l, r int) any {
 			if r == 0 {
 				return &zeroModuloError{l, r}
 			}
 			return l % r
 		},
-		func(l, r float64) interface{} {
+		func(l, r float64) any {
 			ri := floatToInt(r)
 			if ri == 0 {
 				return &zeroModuloError{l, r}
 			}
 			return floatToInt(l) % ri
 		},
-		func(l, r *big.Int) interface{} {
+		func(l, r *big.Int) any {
 			if r.Sign() == 0 {
 				return &zeroModuloError{l, r}
 			}
 			return new(big.Int).Rem(l, r)
 		},
-		func(l, r string) interface{} { return &binopTypeError{"modulo", l, r} },
-		func(l, r []interface{}) interface{} { return &binopTypeError{"modulo", l, r} },
-		func(l, r map[string]interface{}) interface{} { return &binopTypeError{"modulo", l, r} },
-		func(l, r interface{}) interface{} { return &binopTypeError{"modulo", l, r} },
+		func(l, r string) any { return &binopTypeError{"modulo", l, r} },
+		func(l, r []any) any { return &binopTypeError{"modulo", l, r} },
+		func(l, r map[string]any) any { return &binopTypeError{"modulo", l, r} },
+		func(l, r any) any { return &binopTypeError{"modulo", l, r} },
 	)
 }
 
-func funcOpAlt(_, l, r interface{}) interface{} {
+func funcOpAlt(_, l, r any) any {
 	if l == nil || l == false {
 		return r
 	}
 	return l
 }
 
-func funcOpEq(_, l, r interface{}) interface{} {
+func funcOpEq(_, l, r any) any {
 	return compare(l, r) == 0
 }
 
-func funcOpNe(_, l, r interface{}) interface{} {
+func funcOpNe(_, l, r any) any {
 	return compare(l, r) != 0
 }
 
-func funcOpGt(_, l, r interface{}) interface{} {
+func funcOpGt(_, l, r any) any {
 	return compare(l, r) > 0
 }
 
-func funcOpLt(_, l, r interface{}) interface{} {
+func funcOpLt(_, l, r any) any {
 	return compare(l, r) < 0
 }
 
-func funcOpGe(_, l, r interface{}) interface{} {
+func funcOpGe(_, l, r any) any {
 	return compare(l, r) >= 0
 }
 
-func funcOpLe(_, l, r interface{}) interface{} {
+func funcOpLe(_, l, r any) any {
 	return compare(l, r) <= 0
 }
diff --git a/option.go b/option.go
index 6ccfa9b..f1a110f 100644
--- a/option.go
+++ b/option.go
@@ -39,8 +39,7 @@ func WithVariables(variables []string) CompilerOption {
 // function. If you want to emit multiple values, call the empty function,
 // accept a filter for its argument, or call another built-in function, then
 // use LoadInitModules of the module loader.
-func WithFunction(name string, minarity, maxarity int,
-	f func(interface{}, []interface{}) interface{}) CompilerOption {
+func WithFunction(name string, minarity, maxarity int, f func(any, []any) any) CompilerOption {
 	return withFunction(name, minarity, maxarity, false, f)
 }
 
@@ -49,17 +48,15 @@ func WithFunction(name string, minarity, maxarity int,
 // returns an Iter to emit multiple values. You cannot define both iterator and
 // non-iterator functions of the same name (with possibly different arities).
 // See also [NewIter], which can be used to convert values or an error to an Iter.
-func WithIterFunction(name string, minarity, maxarity int,
-	f func(interface{}, []interface{}) Iter) CompilerOption {
+func WithIterFunction(name string, minarity, maxarity int, f func(any, []any) Iter) CompilerOption {
 	return withFunction(name, minarity, maxarity, true,
-		func(v interface{}, args []interface{}) interface{} {
+		func(v any, args []any) any {
 			return f(v, args)
 		},
 	)
 }
 
-func withFunction(name string, minarity, maxarity int, iter bool,
-	f func(interface{}, []interface{}) interface{}) CompilerOption {
+func withFunction(name string, minarity, maxarity int, iter bool, f func(any, []any) any) CompilerOption {
 	if !(0 <= minarity && minarity <= maxarity && maxarity <= 30) {
 		panic(fmt.Sprintf("invalid arity for %q: %d, %d", name, minarity, maxarity))
 	}
@@ -74,7 +71,7 @@ func withFunction(name string, minarity, maxarity int, iter bool,
 			}
 			c.customFuncs[name] = function{
 				argcount | fn.argcount, iter,
-				func(x interface{}, xs []interface{}) interface{} {
+				func(x any, xs []any) any {
 					if argcount&(1<<len(xs)) != 0 {
 						return f(x, xs)
 					}
diff --git a/option_function_test.go b/option_function_test.go
index 7e4cf55..fe13ff9 100644
--- a/option_function_test.go
+++ b/option_function_test.go
@@ -10,7 +10,7 @@ import (
 	"github.com/itchyny/gojq"
 )
 
-func toFloat(x interface{}) (float64, bool) {
+func toFloat(x any) (float64, bool) {
 	switch x := x.(type) {
 	case int:
 		return float64(x), true
@@ -31,7 +31,7 @@ func ExampleWithFunction() {
 	}
 	code, err := gojq.Compile(
 		query,
-		gojq.WithFunction("f", 0, 1, func(x interface{}, xs []interface{}) interface{} {
+		gojq.WithFunction("f", 0, 1, func(x any, xs []any) any {
 			if x, ok := toFloat(x); ok {
 				if len(xs) == 1 {
 					if y, ok := toFloat(xs[0]); ok {
@@ -50,7 +50,7 @@ func ExampleWithFunction() {
 	if err != nil {
 		log.Fatalln(err)
 	}
-	input := []interface{}{0, 1, 2.5, json.Number("10000000000000000000000000000000000000000")}
+	input := []any{0, 1, 2.5, json.Number("10000000000000000000000000000000000000000")}
 	iter := code.Run(input)
 	for {
 		v, ok := iter.Next()
diff --git a/option_iter_function_test.go b/option_iter_function_test.go
index ae005f3..a7ffc77 100644
--- a/option_iter_function_test.go
+++ b/option_iter_function_test.go
@@ -12,7 +12,7 @@ type rangeIter struct {
 	value, max int
 }
 
-func (iter *rangeIter) Next() (interface{}, bool) {
+func (iter *rangeIter) Next() (any, bool) {
 	if iter.value >= iter.max {
 		return nil, false
 	}
@@ -28,7 +28,7 @@ func ExampleWithIterFunction() {
 	}
 	code, err := gojq.Compile(
 		query,
-		gojq.WithIterFunction("f", 2, 2, func(_ interface{}, xs []interface{}) gojq.Iter {
+		gojq.WithIterFunction("f", 2, 2, func(_ any, xs []any) gojq.Iter {
 			if x, ok := xs[0].(int); ok {
 				if y, ok := xs[1].(int); ok {
 					return &rangeIter{x, y}
diff --git a/option_module_loader_test.go b/option_module_loader_test.go
index b978148..7b41d51 100644
--- a/option_module_loader_test.go
+++ b/option_module_loader_test.go
@@ -40,7 +40,7 @@ func ExampleWithModuleLoader() {
 	if err != nil {
 		log.Fatalln(err)
 	}
-	input := map[string]interface{}{"foo": 42}
+	input := map[string]any{"foo": 42}
 	iter := code.Run(input)
 	for {
 		v, ok := iter.Next()
diff --git a/option_test.go b/option_test.go
index 512b402..a1bc581 100644
--- a/option_test.go
+++ b/option_test.go
@@ -51,7 +51,7 @@ func TestWithModuleLoaderError(t *testing.T) {
 
 func TestWithModuleLoader_modulemeta(t *testing.T) {
 	query, err := gojq.Parse(`
-		"module1" | modulemeta
+		"module1", "module2" | modulemeta
 	`)
 	if err != nil {
 		t.Fatal(err)
@@ -64,32 +64,42 @@ func TestWithModuleLoader_modulemeta(t *testing.T) {
 		t.Fatal(err)
 	}
 	iter := code.Run(nil)
+	n := 0
 	for {
 		got, ok := iter.Next()
 		if !ok {
 			break
 		}
-		if expected := map[string]interface{}{
-			"deps": []interface{}{
-				map[string]interface{}{
-					"relpath": "module2",
-					"as":      "foo",
-					"is_data": false,
+		if n == 0 {
+			if expected := map[string]any{
+				"deps": []any{
+					map[string]any{
+						"relpath": "module2",
+						"as":      "foo",
+						"is_data": false,
+					},
 				},
-			},
-			"name": "module1",
-			"test": 42,
-		}; !reflect.DeepEqual(got, expected) {
-			t.Errorf("expected: %v, got: %v", expected, got)
+				"name": "module1",
+				"test": 42,
+			}; !reflect.DeepEqual(got, expected) {
+				t.Errorf("expected: %v, got: %v", expected, got)
+			}
+		} else {
+			if expected := map[string]any{
+				"deps": []any{}, // not a nil-slice
+			}; !reflect.DeepEqual(got, expected) {
+				t.Errorf("expected: %v, got: %v", expected, got)
+			}
 		}
+		n++
 	}
 }
 
 type moduleLoaderJSON struct{}
 
-func (*moduleLoaderJSON) LoadJSON(name string) (interface{}, error) {
+func (*moduleLoaderJSON) LoadJSON(name string) (any, error) {
 	if name == "module1" {
-		return []interface{}{1.0, 42, json.Number("123")}, nil
+		return []any{1.0, 42, json.Number("123")}, nil
 	}
 	return nil, fmt.Errorf("module not found: %q", name)
 }
@@ -115,7 +125,7 @@ func TestWithModuleLoader_JSON(t *testing.T) {
 		if !ok {
 			break
 		}
-		if expected := []interface{}{[]interface{}{1.0, 42, 123}, 5166}; !reflect.DeepEqual(got, expected) {
+		if expected := []any{[]any{1.0, 42, 123}, 5166}; !reflect.DeepEqual(got, expected) {
 			t.Errorf("expected: %v, got: %v", expected, got)
 		}
 	}
@@ -178,7 +188,7 @@ func TestWithEnvironLoader(t *testing.T) {
 		if !ok {
 			break
 		}
-		expected := map[string]interface{}{"foo": "42", "bar": "128", "qux": ""}
+		expected := map[string]any{"foo": "42", "bar": "128", "qux": ""}
 		if !reflect.DeepEqual(got, expected) {
 			t.Errorf("expected: %v, got: %v", expected, got)
 		}
@@ -200,7 +210,7 @@ func TestWithEnvironLoaderEmpty(t *testing.T) {
 		if !ok {
 			break
 		}
-		if expected := map[string]interface{}{}; !reflect.DeepEqual(got, expected) {
+		if expected := map[string]any{}; !reflect.DeepEqual(got, expected) {
 			t.Errorf("expected: %v, got: %v", expected, got)
 		}
 	}
@@ -287,13 +297,13 @@ func TestWithVariablesError2(t *testing.T) {
 
 func TestWithFunction(t *testing.T) {
 	options := []gojq.CompilerOption{
-		gojq.WithFunction("f", 0, 0, func(x interface{}, _ []interface{}) interface{} {
+		gojq.WithFunction("f", 0, 0, func(x any, _ []any) any {
 			if x, ok := x.(int); ok {
 				return x * 2
 			}
 			return fmt.Errorf("f cannot be applied to: %v", x)
 		}),
-		gojq.WithFunction("g", 1, 1, func(x interface{}, xs []interface{}) interface{} {
+		gojq.WithFunction("g", 1, 1, func(x any, xs []any) any {
 			if x, ok := x.(int); ok {
 				if y, ok := xs[0].(int); ok {
 					return x + y
@@ -310,7 +320,7 @@ func TestWithFunction(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	iter := code.Run([]interface{}{0, 1, 2, 3, 4})
+	iter := code.Run([]any{0, 1, 2, 3, 4})
 	n := 0
 	for {
 		v, ok := iter.Next()
@@ -354,13 +364,13 @@ func TestWithFunction(t *testing.T) {
 
 func TestWithFunctionDuplicateName(t *testing.T) {
 	options := []gojq.CompilerOption{
-		gojq.WithFunction("f", 0, 0, func(x interface{}, _ []interface{}) interface{} {
+		gojq.WithFunction("f", 0, 0, func(x any, _ []any) any {
 			if x, ok := x.(int); ok {
 				return x * 2
 			}
 			return fmt.Errorf("f cannot be applied to: %v", x)
 		}),
-		gojq.WithFunction("f", 1, 1, func(x interface{}, xs []interface{}) interface{} {
+		gojq.WithFunction("f", 1, 1, func(x any, xs []any) any {
 			if x, ok := x.(int); ok {
 				if y, ok := xs[0].(int); ok {
 					return x + y
@@ -368,13 +378,13 @@ func TestWithFunctionDuplicateName(t *testing.T) {
 			}
 			return fmt.Errorf("f cannot be applied to: %v, %v", x, xs)
 		}),
-		gojq.WithFunction("f", 0, 0, func(x interface{}, _ []interface{}) interface{} {
+		gojq.WithFunction("f", 0, 0, func(x any, _ []any) any {
 			if x, ok := x.(int); ok {
 				return x * 4
 			}
 			return fmt.Errorf("f cannot be applied to: %v", x)
 		}),
-		gojq.WithFunction("f", 2, 2, func(x interface{}, xs []interface{}) interface{} {
+		gojq.WithFunction("f", 2, 2, func(x any, xs []any) any {
 			if x, ok := x.(int); ok {
 				if y, ok := xs[0].(int); ok {
 					if z, ok := xs[1].(int); ok {
@@ -393,7 +403,7 @@ func TestWithFunctionDuplicateName(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	iter := code.Run([]interface{}{0, 1, 2, 3, 4})
+	iter := code.Run([]any{0, 1, 2, 3, 4})
 	n := 0
 	for {
 		v, ok := iter.Next()
@@ -437,7 +447,7 @@ func TestWithFunctionDuplicateName(t *testing.T) {
 
 func TestWithFunctionMultipleArities(t *testing.T) {
 	options := []gojq.CompilerOption{
-		gojq.WithFunction("f", 0, 4, func(x interface{}, xs []interface{}) interface{} {
+		gojq.WithFunction("f", 0, 4, func(x any, xs []any) any {
 			if x, ok := x.(int); ok {
 				x *= 2
 				for _, y := range xs {
@@ -449,7 +459,7 @@ func TestWithFunctionMultipleArities(t *testing.T) {
 			}
 			return fmt.Errorf("f cannot be applied to: %v, %v", x, xs)
 		}),
-		gojq.WithFunction("f", 2, 3, func(x interface{}, xs []interface{}) interface{} {
+		gojq.WithFunction("f", 2, 3, func(x any, xs []any) any {
 			if x, ok := x.(int); ok {
 				for _, y := range xs {
 					if y, ok := y.(int); ok {
@@ -460,7 +470,7 @@ func TestWithFunctionMultipleArities(t *testing.T) {
 			}
 			return fmt.Errorf("f cannot be applied to: %v, %v", x, xs)
 		}),
-		gojq.WithFunction("g", 0, 30, func(x interface{}, xs []interface{}) interface{} {
+		gojq.WithFunction("g", 0, 30, func(x any, xs []any) any {
 			return nil
 		}),
 	}
@@ -472,7 +482,7 @@ func TestWithFunctionMultipleArities(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	iter := code.Run([]interface{}{0, 1, 2, 3, 4})
+	iter := code.Run([]any{0, 1, 2, 3, 4})
 	n := 0
 	for {
 		v, ok := iter.Next()
@@ -515,25 +525,25 @@ func TestWithFunctionMultipleArities(t *testing.T) {
 }
 
 type valueError struct {
-	v interface{}
+	v any
 }
 
 func (err *valueError) Error() string {
 	return "error: " + fmt.Sprint(err.v)
 }
 
-func (err *valueError) Value() interface{} {
+func (err *valueError) Value() any {
 	return err.v
 }
 
 func TestWithFunctionValueError(t *testing.T) {
-	expected := map[string]interface{}{"foo": 42}
+	expected := map[string]any{"foo": 42}
 	query, err := gojq.Parse("try f catch .")
 	if err != nil {
 		t.Fatal(err)
 	}
 	code, err := gojq.Compile(query,
-		gojq.WithFunction("f", 0, 0, func(x interface{}, _ []interface{}) interface{} {
+		gojq.WithFunction("f", 0, 0, func(x any, _ []any) any {
 			return &valueError{expected}
 		}),
 	)
@@ -558,7 +568,7 @@ func TestWithFunctionCompileArgsError(t *testing.T) {
 		t.Fatal(err)
 	}
 	_, err = gojq.Compile(query,
-		gojq.WithFunction("f", 0, 1, func(interface{}, []interface{}) interface{} {
+		gojq.WithFunction("f", 0, 1, func(any, []any) any {
 			return 0
 		}),
 	)
@@ -581,7 +591,7 @@ func TestWithFunctionArityError(t *testing.T) {
 				}
 			}()
 			t.Fatal(gojq.Compile(query,
-				gojq.WithFunction("f", tc.min, tc.max, func(interface{}, []interface{}) interface{} {
+				gojq.WithFunction("f", tc.min, tc.max, func(any, []any) any {
 					return 0
 				}),
 			))
@@ -595,10 +605,10 @@ func TestWithIterFunction(t *testing.T) {
 		t.Fatal(err)
 	}
 	code, err := gojq.Compile(query,
-		gojq.WithIterFunction("f", 0, 0, func(interface{}, []interface{}) gojq.Iter {
+		gojq.WithIterFunction("f", 0, 0, func(any, []any) gojq.Iter {
 			return gojq.NewIter(1, 2, 3)
 		}),
-		gojq.WithIterFunction("g", 2, 2, func(_ interface{}, xs []interface{}) gojq.Iter {
+		gojq.WithIterFunction("g", 2, 2, func(_ any, xs []any) gojq.Iter {
 			if x, ok := xs[0].(int); ok {
 				if y, ok := xs[1].(int); ok {
 					return &rangeIter{x, y}
@@ -606,7 +616,7 @@ func TestWithIterFunction(t *testing.T) {
 			}
 			return gojq.NewIter(fmt.Errorf("g cannot be applied to: %v", xs))
 		}),
-		gojq.WithIterFunction("h", 0, 0, func(interface{}, []interface{}) gojq.Iter {
+		gojq.WithIterFunction("h", 0, 0, func(any, []any) gojq.Iter {
 			return gojq.NewIter()
 		}),
 	)
@@ -636,7 +646,7 @@ func TestWithIterFunctionError(t *testing.T) {
 		t.Fatal(err)
 	}
 	code, err := gojq.Compile(query,
-		gojq.WithIterFunction("f", 0, 0, func(interface{}, []interface{}) gojq.Iter {
+		gojq.WithIterFunction("f", 0, 0, func(any, []any) gojq.Iter {
 			return gojq.NewIter(1, errors.New("error"), 3)
 		}),
 	)
@@ -677,7 +687,7 @@ func TestWithIterFunctionPathIndexing(t *testing.T) {
 		t.Fatal(err)
 	}
 	code, err := gojq.Compile(query,
-		gojq.WithIterFunction("f", 0, 0, func(interface{}, []interface{}) gojq.Iter {
+		gojq.WithIterFunction("f", 0, 0, func(any, []any) gojq.Iter {
 			return gojq.NewIter(0, 1, 2)
 		}),
 	)
@@ -690,7 +700,7 @@ func TestWithIterFunctionPathIndexing(t *testing.T) {
 		if !ok {
 			break
 		}
-		if expected := []interface{}{1, 1, 1}; !reflect.DeepEqual(v, expected) {
+		if expected := []any{1, 1, 1}; !reflect.DeepEqual(v, expected) {
 			t.Errorf("expected: %v, got: %v", expected, v)
 		}
 	}
@@ -702,7 +712,7 @@ func TestWithIterFunctionPathInputValue(t *testing.T) {
 		t.Fatal(err)
 	}
 	code, err := gojq.Compile(query,
-		gojq.WithIterFunction("f", 0, 0, func(v interface{}, _ []interface{}) gojq.Iter {
+		gojq.WithIterFunction("f", 0, 0, func(v any, _ []any) gojq.Iter {
 			return gojq.NewIter(v, v, v)
 		}),
 	)
@@ -715,7 +725,7 @@ func TestWithIterFunctionPathInputValue(t *testing.T) {
 		if !ok {
 			break
 		}
-		if expected := map[string]interface{}{"x": 1}; !reflect.DeepEqual(v, expected) {
+		if expected := map[string]any{"x": 1}; !reflect.DeepEqual(v, expected) {
 			t.Errorf("expected: %v, got: %v", expected, v)
 		}
 	}
@@ -727,7 +737,7 @@ func TestWithIterFunctionPathEmpty(t *testing.T) {
 		t.Fatal(err)
 	}
 	code, err := gojq.Compile(query,
-		gojq.WithIterFunction("f", 0, 0, func(interface{}, []interface{}) gojq.Iter {
+		gojq.WithIterFunction("f", 0, 0, func(any, []any) gojq.Iter {
 			return gojq.NewIter()
 		}),
 	)
@@ -740,7 +750,7 @@ func TestWithIterFunctionPathEmpty(t *testing.T) {
 		if !ok {
 			break
 		}
-		if expected := map[string]interface{}{"x": 0}; !reflect.DeepEqual(v, expected) {
+		if expected := map[string]any{"x": 0}; !reflect.DeepEqual(v, expected) {
 			t.Errorf("expected: %v, got: %v", expected, v)
 		}
 	}
@@ -752,8 +762,8 @@ func TestWithIterFunctionInvalidPathError(t *testing.T) {
 		t.Fatal(err)
 	}
 	code, err := gojq.Compile(query,
-		gojq.WithIterFunction("f", 0, 0, func(interface{}, []interface{}) gojq.Iter {
-			return gojq.NewIter(map[string]interface{}{"x": 1})
+		gojq.WithIterFunction("f", 0, 0, func(any, []any) gojq.Iter {
+			return gojq.NewIter(map[string]any{"x": 1})
 		}),
 	)
 	if err != nil {
@@ -779,7 +789,7 @@ func TestWithIterFunctionPathError(t *testing.T) {
 		t.Fatal(err)
 	}
 	code, err := gojq.Compile(query,
-		gojq.WithIterFunction("f", 0, 0, func(interface{}, []interface{}) gojq.Iter {
+		gojq.WithIterFunction("f", 0, 0, func(any, []any) gojq.Iter {
 			return gojq.NewIter(errors.New("error"))
 		}),
 	)
@@ -812,10 +822,10 @@ func TestWithIterFunctionDefineError(t *testing.T) {
 		}
 	}()
 	t.Fatal(gojq.Compile(query,
-		gojq.WithFunction("f", 0, 0, func(interface{}, []interface{}) interface{} {
+		gojq.WithFunction("f", 0, 0, func(any, []any) any {
 			return 0
 		}),
-		gojq.WithIterFunction("f", 0, 0, func(interface{}, []interface{}) gojq.Iter {
+		gojq.WithIterFunction("f", 0, 0, func(any, []any) gojq.Iter {
 			return gojq.NewIter()
 		}),
 	))
@@ -838,7 +848,7 @@ func TestWithFunctionWithModuleLoader(t *testing.T) {
 		t.Fatal(err)
 	}
 	code, err := gojq.Compile(query,
-		gojq.WithFunction("f", 0, 0, func(x interface{}, _ []interface{}) interface{} {
+		gojq.WithFunction("f", 0, 0, func(x any, _ []any) any {
 			if x, ok := x.(int); ok {
 				return x * 2
 			}
@@ -849,7 +859,7 @@ func TestWithFunctionWithModuleLoader(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	iter := code.Run([]interface{}{0, 1, 2, 3, 4})
+	iter := code.Run([]any{0, 1, 2, 3, 4})
 	n := 0
 	for {
 		v, ok := iter.Next()
diff --git a/parser.go b/parser.go
index 145a493..1e5e50a 100644
--- a/parser.go
+++ b/parser.go
@@ -38,7 +38,7 @@ func prependFuncDef(xs []*FuncDef, x *FuncDef) []*FuncDef {
 //line parser.go.y:33
 type yySymType struct {
 	yys      int
-	value    interface{}
+	value    any
 	token    string
 	operator Operator
 }
diff --git a/parser.go.y b/parser.go.y
index e03b14b..380c3cf 100644
--- a/parser.go.y
+++ b/parser.go.y
@@ -31,7 +31,7 @@ func prependFuncDef(xs []*FuncDef, x *FuncDef) []*FuncDef {
 %}
 
 %union {
-  value    interface{}
+  value    any
   token    string
   operator Operator
 }
diff --git a/preview.go b/preview.go
index 763d510..e082eb5 100644
--- a/preview.go
+++ b/preview.go
@@ -8,18 +8,18 @@ import "unicode/utf8"
 //
 // This method is used by error messages of built-in operators and functions,
 // and accepts only limited types (nil, bool, int, float64, *big.Int, string,
-// []interface{}, and map[string]interface{}). Note that the maximum width and
-// trailing strings on truncation may be changed in the future.
-func Preview(v interface{}) string {
+// []any, and map[string]any). Note that the maximum width and trailing strings
+// on truncation may be changed in the future.
+func Preview(v any) string {
 	bs := jsonLimitedMarshal(v, 32)
 	if l := 30; len(bs) > l {
 		var trailing string
 		switch v.(type) {
 		case string:
 			trailing = ` ..."`
-		case []interface{}:
+		case []any:
 			trailing = " ...]"
-		case map[string]interface{}:
+		case map[string]any:
 			trailing = " ...}"
 		default:
 			trailing = " ..."
@@ -33,7 +33,7 @@ func Preview(v interface{}) string {
 	return string(bs)
 }
 
-func jsonLimitedMarshal(v interface{}, n int) (bs []byte) {
+func jsonLimitedMarshal(v any, n int) (bs []byte) {
 	w := &limitedWriter{buf: make([]byte, n)}
 	defer func() {
 		_ = recover()
@@ -51,7 +51,7 @@ type limitedWriter struct {
 func (w *limitedWriter) Write(bs []byte) (int, error) {
 	n := copy(w.buf[w.off:], bs)
 	if w.off += n; w.off == len(w.buf) {
-		panic(nil)
+		panic(struct{}{})
 	}
 	return n, nil
 }
@@ -59,7 +59,7 @@ func (w *limitedWriter) Write(bs []byte) (int, error) {
 func (w *limitedWriter) WriteByte(b byte) error {
 	w.buf[w.off] = b
 	if w.off++; w.off == len(w.buf) {
-		panic(nil)
+		panic(struct{}{})
 	}
 	return nil
 }
@@ -67,7 +67,7 @@ func (w *limitedWriter) WriteByte(b byte) error {
 func (w *limitedWriter) WriteString(s string) (int, error) {
 	n := copy(w.buf[w.off:], s)
 	if w.off += n; w.off == len(w.buf) {
-		panic(nil)
+		panic(struct{}{})
 	}
 	return n, nil
 }
diff --git a/preview_test.go b/preview_test.go
index 29af6e8..5b6c878 100644
--- a/preview_test.go
+++ b/preview_test.go
@@ -11,7 +11,7 @@ import (
 
 func TestPreview(t *testing.T) {
 	testCases := []struct {
-		value    interface{}
+		value    any
 		expected string
 	}{
 		{
@@ -71,35 +71,35 @@ func TestPreview(t *testing.T) {
 			`"01234567 ..."`,
 		},
 		{
-			[]interface{}{},
+			[]any{},
 			"[]",
 		},
 		{
-			[]interface{}{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},
+			[]any{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},
 			"[0,1,2,3,4,5,6,7,8,9,10,11,12]",
 		},
 		{
-			[]interface{}{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13},
+			[]any{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13},
 			"[0,1,2,3,4,5,6,7,8,9,10,1 ...]",
 		},
 		{
-			[]interface{}{[]interface{}{[]interface{}{[]interface{}{[]interface{}{[]interface{}{[]interface{}{[]interface{}{nil, nil, nil}}}}}}}},
+			[]any{[]any{[]any{[]any{[]any{[]any{[]any{[]any{nil, nil, nil}}}}}}}},
 			"[[[[[[[[null,null,null]]]]]]]]",
 		},
 		{
-			[]interface{}{[]interface{}{[]interface{}{[]interface{}{[]interface{}{[]interface{}{[]interface{}{[]interface{}{nil, nil, nil, nil}}}}}}}},
+			[]any{[]any{[]any{[]any{[]any{[]any{[]any{[]any{nil, nil, nil, nil}}}}}}}},
 			"[[[[[[[[null,null,null,nu ...]",
 		},
 		{
-			map[string]interface{}{},
+			map[string]any{},
 			"{}",
 		},
 		{
-			map[string]interface{}{"0": map[string]interface{}{"1": map[string]interface{}{"2": map[string]interface{}{"3": []interface{}{nil}}}}},
+			map[string]any{"0": map[string]any{"1": map[string]any{"2": map[string]any{"3": []any{nil}}}}},
 			`{"0":{"1":{"2":{"3":[null]}}}}`,
 		},
 		{
-			map[string]interface{}{"0": map[string]interface{}{"1": map[string]interface{}{"2": map[string]interface{}{"3": map[string]interface{}{"4": map[string]interface{}{}}}}}},
+			map[string]any{"0": map[string]any{"1": map[string]any{"2": map[string]any{"3": map[string]any{"4": map[string]any{}}}}}},
 			`{"0":{"1":{"2":{"3":{"4": ...}`,
 		},
 	}
diff --git a/query.go b/query.go
index 4bba2d2..5f20b4f 100644
--- a/query.go
+++ b/query.go
@@ -21,12 +21,12 @@ type Query struct {
 //
 // It is safe to call this method in goroutines, to reuse a parsed [*Query].
 // But for arguments, do not give values sharing same data between goroutines.
-func (e *Query) Run(v interface{}) Iter {
+func (e *Query) Run(v any) Iter {
 	return e.RunWithContext(context.Background(), v)
 }
 
 // RunWithContext runs the query with context.
-func (e *Query) RunWithContext(ctx context.Context, v interface{}) Iter {
+func (e *Query) RunWithContext(ctx context.Context, v any) Iter {
 	code, err := Compile(e)
 	if err != nil {
 		return NewIter(err)
@@ -92,14 +92,14 @@ func (e *Query) minify() {
 	}
 }
 
-func (e *Query) toIndexKey() interface{} {
+func (e *Query) toIndexKey() any {
 	if e.Term == nil {
 		return nil
 	}
 	return e.Term.toIndexKey()
 }
 
-func (e *Query) toIndices(xs []interface{}) []interface{} {
+func (e *Query) toIndices(xs []any) []any {
 	if e.Term == nil {
 		return nil
 	}
@@ -314,7 +314,7 @@ func (e *Term) toFunc() string {
 	}
 }
 
-func (e *Term) toIndexKey() interface{} {
+func (e *Term) toIndexKey() any {
 	switch e.Type {
 	case TermTypeNumber:
 		return toNumber(e.Number)
@@ -330,7 +330,7 @@ func (e *Term) toIndexKey() interface{} {
 	}
 }
 
-func (e *Term) toIndices(xs []interface{}) []interface{} {
+func (e *Term) toIndices(xs []any) []any {
 	switch e.Type {
 	case TermTypeIndex:
 		if xs = e.Index.toIndices(xs); xs == nil {
@@ -351,7 +351,7 @@ func (e *Term) toIndices(xs []interface{}) []interface{} {
 	return xs
 }
 
-func (e *Term) toNumber() interface{} {
+func (e *Term) toNumber() any {
 	if e.Type == TermTypeNumber {
 		return toNumber(e.Number)
 	}
@@ -379,7 +379,7 @@ func (e *Unary) minify() {
 	e.Term.minify()
 }
 
-func (e *Unary) toNumber() interface{} {
+func (e *Unary) toNumber() any {
 	v := e.Term.toNumber()
 	if v != nil && e.Op == OpSub {
 		v = funcOpNegate(v)
@@ -514,7 +514,7 @@ func (e *Index) minify() {
 	}
 }
 
-func (e *Index) toIndexKey() interface{} {
+func (e *Index) toIndexKey() any {
 	if e.Name != "" {
 		return e.Name
 	} else if e.Str != nil {
@@ -524,7 +524,7 @@ func (e *Index) toIndexKey() interface{} {
 	} else if !e.IsSlice {
 		return e.Start.toIndexKey()
 	} else {
-		var start, end interface{}
+		var start, end any
 		ok := true
 		if e.Start != nil {
 			start = e.Start.toIndexKey()
@@ -535,13 +535,13 @@ func (e *Index) toIndexKey() interface{} {
 			ok = end != nil
 		}
 		if ok {
-			return map[string]interface{}{"start": start, "end": end}
+			return map[string]any{"start": start, "end": end}
 		}
 	}
 	return nil
 }
 
-func (e *Index) toIndices(xs []interface{}) []interface{} {
+func (e *Index) toIndices(xs []any) []any {
 	if k := e.toIndexKey(); k != nil {
 		return append(xs, k)
 	}
@@ -795,7 +795,7 @@ func (e *Suffix) toTerm() *Term {
 	}
 }
 
-func (e *Suffix) toIndices(xs []interface{}) []interface{} {
+func (e *Suffix) toIndices(xs []any) []any {
 	if e.Index == nil {
 		return nil
 	}
@@ -1057,7 +1057,7 @@ func (e *ConstTerm) writeTo(s *strings.Builder) {
 	}
 }
 
-func (e *ConstTerm) toValue() interface{} {
+func (e *ConstTerm) toValue() any {
 	if e.Object != nil {
 		return e.Object.ToValue()
 	} else if e.Array != nil {
@@ -1101,12 +1101,12 @@ func (e *ConstObject) writeTo(s *strings.Builder) {
 	s.WriteString(" }")
 }
 
-// ToValue converts the object to map[string]interface{}.
-func (e *ConstObject) ToValue() map[string]interface{} {
+// ToValue converts the object to map[string]any.
+func (e *ConstObject) ToValue() map[string]any {
 	if e == nil {
 		return nil
 	}
-	v := make(map[string]interface{}, len(e.KeyVals))
+	v := make(map[string]any, len(e.KeyVals))
 	for _, e := range e.KeyVals {
 		key := e.Key
 		if key == "" {
@@ -1162,8 +1162,8 @@ func (e *ConstArray) writeTo(s *strings.Builder) {
 	s.WriteByte(']')
 }
 
-func (e *ConstArray) toValue() []interface{} {
-	v := make([]interface{}, len(e.Elems))
+func (e *ConstArray) toValue() []any {
+	v := make([]any, len(e.Elems))
 	for i, e := range e.Elems {
 		v[i] = e.toValue()
 	}
diff --git a/query_test.go b/query_test.go
index 9a71be4..87c4b52 100644
--- a/query_test.go
+++ b/query_test.go
@@ -23,7 +23,7 @@ func ExampleQuery_Run() {
 	if err != nil {
 		log.Fatalln(err)
 	}
-	input := map[string]interface{}{"foo": []interface{}{1, 2, 3}}
+	input := map[string]any{"foo": []any{1, 2, 3}}
 	iter := query.Run(input)
 	for {
 		v, ok := iter.Next()
@@ -72,7 +72,7 @@ func TestQueryRun_Errors(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	iter := query.Run([]interface{}{0, 1, 2, 3, 4})
+	iter := query.Run([]any{0, 1, 2, 3, 4})
 	n := 0
 	for {
 		v, ok := iter.Next()
@@ -98,7 +98,7 @@ func TestQueryRun_ObjectError(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	iter := query.Run([]interface{}{0, "x", []interface{}{}})
+	iter := query.Run([]any{0, "x", []any{}})
 	for {
 		v, ok := iter.Next()
 		if !ok {
@@ -109,7 +109,7 @@ func TestQueryRun_ObjectError(t *testing.T) {
 			if !strings.Contains(err.Error(), expected) {
 				t.Errorf("expected: %v, got: %v", expected, err)
 			}
-		} else if expected := map[string]interface{}{"x": 1}; !reflect.DeepEqual(v, expected) {
+		} else if expected := map[string]any{"x": 1}; !reflect.DeepEqual(v, expected) {
 			t.Errorf("expected: %v, got: %v", expected, v)
 		}
 	}
@@ -120,7 +120,7 @@ func TestQueryRun_IndexError(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	iter := query.Run([]interface{}{0})
+	iter := query.Run([]any{0})
 	for {
 		v, ok := iter.Next()
 		if !ok {
@@ -196,7 +196,7 @@ func TestQueryRun_Strings(t *testing.T) {
 		if err, ok := v.(error); ok {
 			t.Fatal(err)
 		}
-		if expected := []interface{}{
+		if expected := []any{
 			0x00, int('\\'), 0x1f, int('"'), int('\n'), int('\n'), int('\n'),
 			int('\n'), int('\n'), int('\n'), int('/'), 0x7f, 0xfffd, 128516,
 		}; !reflect.DeepEqual(v, expected) {
@@ -210,7 +210,7 @@ func TestQueryRun_NumericTypes(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	iter := query.Run([]interface{}{
+	iter := query.Run([]any{
 		int64(1), int32(1), int16(1), int8(1), uint64(1), uint32(1), uint16(1), uint8(1), uint(math.MaxUint),
 		int64(math.MaxInt64), int64(math.MinInt64), uint64(math.MaxUint64), uint32(math.MaxUint32),
 		new(big.Int).SetUint64(math.MaxUint64), new(big.Int).SetUint64(math.MaxUint32),
@@ -250,6 +250,32 @@ func TestQueryRun_Input(t *testing.T) {
 	}
 }
 
+func TestQueryRun_NonNilSlice(t *testing.T) {
+	for _, f := range []string{"keys", "map(.)", "to_entries", "arrays",
+		"reverse", "flatten", "sort", "sort_by(.)", "group_by(.)", "unique",
+		"unique_by(.)", "transpose", "nth(.)", "indices([])", "path(.)"} {
+		t.Run(f, func(t *testing.T) {
+			query, err := gojq.Parse("[] | " + f)
+			if err != nil {
+				t.Fatal(err)
+			}
+			iter := query.Run(nil)
+			for {
+				v, ok := iter.Next()
+				if !ok {
+					break
+				}
+				if err, ok := v.(error); ok {
+					t.Fatal(err)
+				}
+				if expected := []any{}; !reflect.DeepEqual(v, expected) {
+					t.Errorf("expected: %#v, got: %#v", expected, v)
+				}
+			}
+		})
+	}
+}
+
 func TestQueryRun_Race(t *testing.T) {
 	query, err := gojq.Parse("range(10)")
 	if err != nil {
@@ -327,3 +353,27 @@ func BenchmarkParse(b *testing.B) {
 		}
 	}
 }
+
+func FuzzQueryRun(f *testing.F) {
+	f.Fuzz(func(t *testing.T, src string) {
+		if len(src) > 16 {
+			t.SkipNow()
+		}
+		q, err := gojq.Parse(src)
+		if err != nil {
+			t.SkipNow()
+		}
+		code, err := gojq.Compile(q)
+		if err != nil {
+			t.SkipNow()
+		}
+		ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
+		t.Cleanup(cancel)
+		iter := code.RunWithContext(ctx, nil)
+		for {
+			if _, ok := iter.Next(); !ok {
+				break
+			}
+		}
+	})
+}
diff --git a/release.go b/release.go
index 1144485..c34dfb4 100644
--- a/release.go
+++ b/release.go
@@ -5,7 +5,7 @@ package gojq
 
 type codeinfo struct{}
 
-func (c *compiler) appendCodeInfo(interface{}) {}
+func (c *compiler) appendCodeInfo(any) {}
 
 func (c *compiler) deleteCodeInfo(string) {}
 
diff --git a/stack.go b/stack.go
index 50445fc..a0e265c 100644
--- a/stack.go
+++ b/stack.go
@@ -7,7 +7,7 @@ type stack struct {
 }
 
 type block struct {
-	value interface{}
+	value any
 	next  int
 }
 
@@ -15,7 +15,7 @@ func newStack() *stack {
 	return &stack{index: -1, limit: -1}
 }
 
-func (s *stack) push(v interface{}) {
+func (s *stack) push(v any) {
 	b := block{v, s.index}
 	i := s.index + 1
 	if i <= s.limit {
@@ -29,13 +29,13 @@ func (s *stack) push(v interface{}) {
 	}
 }
 
-func (s *stack) pop() interface{} {
+func (s *stack) pop() any {
 	b := s.data[s.index]
 	s.index = b.next
 	return b.value
 }
 
-func (s *stack) top() interface{} {
+func (s *stack) top() any {
 	return s.data[s.index].value
 }
 
diff --git a/type.go b/type.go
index 578a6f4..bb388e2 100644
--- a/type.go
+++ b/type.go
@@ -8,9 +8,8 @@ import (
 // TypeOf returns the jq-flavored type name of v.
 //
 // This method is used by built-in type/0 function, and accepts only limited
-// types (nil, bool, int, float64, *big.Int, string, []interface{},
-// and map[string]interface{}).
-func TypeOf(v interface{}) string {
+// types (nil, bool, int, float64, *big.Int, string, []any, and map[string]any).
+func TypeOf(v any) string {
 	switch v.(type) {
 	case nil:
 		return "null"
@@ -20,9 +19,9 @@ func TypeOf(v interface{}) string {
 		return "number"
 	case string:
 		return "string"
-	case []interface{}:
+	case []any:
 		return "array"
-	case map[string]interface{}:
+	case map[string]any:
 		return "object"
 	default:
 		panic(fmt.Sprintf("invalid type: %[1]T (%[1]v)", v))
diff --git a/type_test.go b/type_test.go
index c3da1cf..ef917a0 100644
--- a/type_test.go
+++ b/type_test.go
@@ -11,7 +11,7 @@ import (
 
 func TestTypeOf(t *testing.T) {
 	testCases := []struct {
-		value    interface{}
+		value    any
 		expected string
 	}{
 		{nil, "null"},
@@ -24,8 +24,8 @@ func TestTypeOf(t *testing.T) {
 		{math.Inf(-1), "number"},
 		{big.NewInt(10), "number"},
 		{"string", "string"},
-		{[]interface{}{}, "array"},
-		{map[string]interface{}{}, "object"},
+		{[]any{}, "array"},
+		{map[string]any{}, "object"},
 	}
 	for _, tc := range testCases {
 		t.Run(fmt.Sprintf("%v", tc.value), func(t *testing.T) {

More details

Full run details

Historical runs