:toc:

= Custom Syntax Elements

This section systematically outlines the interfaces and capabilities in QLExpress4 for customizing syntax elements.

== Overview

* Custom functions
** Implement the CustomFunction interface
** Use Java functional interfaces
** Register via annotation scanning
** Add via QLExpress script
** Implement QLFunctionalVarargs
* Custom operators
** Implement CustomBinaryOperator
** Replace built-in operators
** Use Java functional interfaces
** Add aliases
** Implement QLFunctionalVarargs
* Extension functions
** Extend ExtensionFunction
** Implement QLFunctionalVarargs
* Aliases for operators and functions

== Custom Functions

=== Implement the CustomFunction interface

[source,java,indent=0]
----
include::../src/test/java/com/alibaba/qlexpress4/test/function/HelloFunction.java[]
----

[source,java,indent=0]
----
include::../src/test/java/com/alibaba/qlexpress4/Express4RunnerTest.java[tag=customComplexFunction]
----

=== Use Java functional interfaces

[source,java,indent=0]
----
include::../src/test/java/com/alibaba/qlexpress4/docs/CustomItemsDocTest.java[tag=addFunctionWithJavaFunctional]
----

=== Register via annotations

[source,java,indent=0]
----
include::../src/test/java/com/alibaba/qlexpress4/Express4RunnerTest.java[tag=annoObj]
----

[source,java,indent=0]
----
include::../src/test/java/com/alibaba/qlexpress4/Express4RunnerTest.java[tag=addFunctionByAnnotationObject]
----

=== Add via QLExpress script

[source,java,indent=0]
----
include::../src/test/java/com/alibaba/qlexpress4/docs/CustomItemsDocTest.java[tag=joinFunctionVarargsObj]
----

=== Implement QLFunctionalVarargs

[source,java,indent=0]
----
include::../src/test/java/com/alibaba/qlexpress4/docs/CustomItemsDocTest.java[tag=addFunctionByVarargs]
----

[source,java,indent=0]
----
include::../src/test/java/com/alibaba/qlexpress4/docs/CustomItemsDocTest.java[tag=addFunctionByVarargs]
----

== Custom Operators

=== Implement CustomBinaryOperator and set precedence

[source,java,indent=0]
----
include::../src/test/java/com/alibaba/qlexpress4/docs/CustomItemsDocTest.java[tag=addOperatorWithPrecedence]
----

=== Replace built-in operators

[source,java,indent=0]
----
include::../src/test/java/com/alibaba/qlexpress4/docs/CustomItemsDocTest.java[tag=replaceDefaultOperator]
----

=== Use Java functional interfaces

[source,java,indent=0]
----
include::../src/test/java/com/alibaba/qlexpress4/docs/CustomItemsDocTest.java[tag=addOperatorBiFunction]
----

=== Implement QLFunctionalVarargs

[source,java,indent=0]
----
include::../src/test/java/com/alibaba/qlexpress4/docs/CustomItemsDocTest.java[tag=addOperatorByVarargs]
----

== Extension Functions

=== Extend ExtensionFunction

[source,java,indent=0]
----
include::../src/test/java/com/alibaba/qlexpress4/Express4RunnerTest.java[tag=defineExtensionFunctionByExtensionFunction]
----

=== Implement QLFunctionalVarargs

[source,java,indent=0]
----
include::../src/test/java/com/alibaba/qlexpress4/Express4RunnerTest.java[tag=defineExtensionFunctionByQLFunctionalVarargs]
----

== QLFunctionalVarargs: One object defines three kinds of operations

The same QLFunctionalVarargs object can serve as the implementation of a function, an operator, and an extension function at the same time, making it easy to reuse unified semantics and implementation across multiple places. This capability comes from the interface’s varargs design; see the example and interface definition below. For background discussion, refer to link:https://github.com/alibaba/QLExpress/issues/407[issue407]:

[source,java,indent=0]
----
include::../src/test/java/com/alibaba/qlexpress4/docs/CustomItemsDocTest.java[tag=qlfunctionalvarargsAllInOne]
----

=== Interface definition

[source,java,indent=0]
----
include::../src/main/java/com/alibaba/qlexpress4/api/QLFunctionalVarargs.java[]
----

== Aliases for operators and functions (keyword aliases also supported)

[source,java,indent=0]
----
include::../src/test/java/com/alibaba/qlexpress4/Express4RunnerTest.java[tag=addAlias]
----

== Notes and recommendations

- Under the QLFunctionalVarargs calling convention, when invoking an extension function the first actual argument is the receiver object, followed by the call arguments; functions and operators do not include a receiver.
- Set the precedence of custom operators according to the intended expression semantics to avoid confusion with existing rules.
- Annotation-based registration only processes public methods, and duplicate names will fail to register; the batch registration result contains both success and failure lists.

