When an evaluator is constructed with an expression, we already gain static information unrelated to the variable mapping we receive later when actually evaluating. We could try to 'compile' some of this information in the evaluator object, so that it can be reused for multiple evaluations of the same expression with different mappings.
Some possible optimizations we could do:
Optimize the expression: Some expressions will be inefficient, contain redundant comparisons, or whatever calculating that is unnecessary. A trivial example would be "true"^^xsd:boolean && "false"^^xsd:boolean, which could be replaced with "false"^^xsd:boolean. Actual possibilities are ofcourse significantly more complex, but I would assume there is very decent literature available/
We might delegate optimizing the expression the user, but there are various reasons we don't want to assume the user is an automated intelligent component.
Deduce type information: We can deduce type information relevant to casting which would allow us to already specify some internals related to casting of RDF terms to internal representation, removing the need to do this repeatedly during evaluation. Possible scenario's:
There are literals already present in the expression
There are functions present in the expression which take arguments of a limited set of types
Calculate functions on literals: For various reasons, users might use an internal SPARQL function on a constant literal. We could very easily replace this at compilation with the function result.
Deduce need for async: There is a limited set of expression functionality with a strong need for async evaluation. At compile time we could already set up the necessary flags and functions, resulting in less branching during evaluation.
Generate JS for an expression (once) and use eval() with the mapping somehow put in there for quick evaluation. Using this we are possibly able to generate a 'flat' (little branching and recursion) expression directly interpretable by JS.
Translate the expression tree to a stack (once), and evaluate as such (prefix), the reduced branching would maybe improve performance
When an evaluator is constructed with an expression, we already gain static information unrelated to the variable mapping we receive later when actually evaluating. We could try to 'compile' some of this information in the evaluator object, so that it can be reused for multiple evaluations of the same expression with different mappings.
Some possible optimizations we could do:
"true"^^xsd:boolean && "false"^^xsd:boolean
, which could be replaced with"false"^^xsd:boolean
. Actual possibilities are ofcourse significantly more complex, but I would assume there is very decent literature available/ We might delegate optimizing the expression the user, but there are various reasons we don't want to assume the user is an automated intelligent component.