Skip to content

Move function.h under ast/ as app_function.h and grammar-match the function call nodes - #1542

Merged
trueqbit merged 3 commits into
devfrom
refactor/move-function-h-under-ast
Sep 20, 2026
Merged

trueqbit merged 3 commits into
devfrom
refactor/move-function-h-under-ast

Conversation

@trueqbit

Copy link
Copy Markdown
Collaborator

Summary

Two commits, both about the application-defined function machinery and its place in the vocabulary layer.

1. dev/function.h → dev/ast/app_function.h. The header holds the call node of an application-defined function together with the definition machinery that generates it (func<UDF>, "name"_scalar) — the same shape as ast/builtin_function.h, so it belongs next to it. The definition object and the call node are named after it, app_function<UDF> and app_function_call<UDF, Args...>, mirroring builtin_function / builtin_function_call; function and function_call said nothing in internal. "Application-defined" is SQLite's own term (sqlite3_create_function). The header specializes the operand and grammar traits in place, so it is now registered in node_definitions.h, which it had been missing from.

2. is_app_function_call + is_builtin_function_call, and the rule behind them. The consumers of the app-function call node — ast_iterator, column_result_t, node_tuple, statement_serializer, udf_existence_checker — pattern-matched and decomposed the concrete node. They now grammar-match on a new is_app_function_call trait and read through udf_type_t / args_tuple_t, and no longer include the node header at all. The built-in side gets the same treatment: is_builtin_function_v (a primary-false template with a pattern partial specialization per call node) becomes is_builtin_function_call_v, one closed definition over is_base_template_of<builtin_function_call, T> that also covers the derived aggregate node; is_operator_argument_v is enabled on the grammar trait for both. The rename says what the trait classifies: the call node, not the definition object.

docs/internals/vocabulary-layer.md gains two sections stating the rule — a node's own trait is one closed definition over a type predicate, a joined axis is a SFINAE enabler on the node's grammar trait, and consumers grammar-match and read through the projections rather than pattern-matching the node — and AGENTS.md carries the short form.

No public API changes: func<>, "x"_scalar, the orm_* concepts and storage.create_*_function() are untouched.

Test plan

  • tests/static_tests/function_static_tests.cpp: is_app_function_call_v positive for scalar and aggregate call nodes, negative for the UDF type and the definition object; is_operator_argument_v on both nodes.
  • tests/static_tests/builtin_function_static_tests.cpp: renamed assertions.
  • Full suite compiles and runs locally.

🤖 Generated with Claude Code

The header holds the call node of an application-defined function together
with the definition machinery that generates it (`func<UDF>`, `"name"_scalar`),
the same shape as `ast/builtin_function.h`. Name the definition object and the
call node after it — `app_function<UDF>` and `app_function_call<UDF, Args...>`,
mirroring `builtin_function` and `builtin_function_call` — since `function` and
`function_call` say nothing in `internal`.

It also specializes the operand and grammar traits in place, so register it in
node_definitions.h, which it was missing from.

Co-Authored-By: Claude Opus 5
…ument the rule

The consumers of `app_function_call` — ast_iterator, column_result_t, node_tuple,
statement_serializer and udf_existence_checker — pattern-matched and decomposed
the concrete node. Give the node a grammar trait, `is_app_function_call`, and
let its consumers match on it and read through `udf_type_t` and `args_tuple_t`.

The built-in side gets the same treatment: `is_builtin_function_v` was a
primary-false template with a pattern partial specialization per call node; it
is now `is_builtin_function_call_v`, one closed definition over
`is_base_template_of<builtin_function_call, T>` that also covers the derived
aggregate call node, and `is_operator_argument_v` is enabled on it. The rename
says what the trait classifies: the call node, not the definition object.

The vocabulary document now states the rule both nodes follow: a node's own
trait is one closed definition over a type predicate, a joined axis is a SFINAE
enabler on the node's grammar trait, and consumers grammar-match and read
through the projections rather than pattern-matching and decomposing the node.

Co-Authored-By: Claude Opus 5
@trueqbit
trueqbit requested a review from fnc12 September 20, 2026 14:03
@trueqbit
trueqbit merged commit 27e2ab8 into dev Sep 20, 2026
20 checks passed
@trueqbit
trueqbit deleted the refactor/move-function-h-under-ast branch September 20, 2026 18:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants