class NamedFunction extends java.lang.Object implements Scope
By virtue of the fact that rules can be added to the execute list, functions support the ability to embed complex logic including control flow (e.g. conditional execution and looping) and actions. Almost all of the capabilities of rules can be used including nesting. The sole exception is that rule types are completely ignored (even if specified explicitly using an attribute). This makes sense since there should be no limitation on when this function can be called. Such support allows one to create "callable" rules using functions.
Please note that variable and return value initializers (the
init
attribute) are executed at the time that the function
is loaded rather than at runtime. This means that parameters that are
passed to the function CANNOT be accessed in such initializers since the
parameters will not yet have values until the function is actually called.
Known limitation: currently, recursive calls to a single named function are not supported, since only one local variable pool per named function is maintained in the symbol resolver. This limitation includes direct recursion (named function calls itself) as well as indirect recursion (named function calls some other function which eventually calls original named function). This limitation may be removed in future development.
Modifier and Type | Field and Description |
---|---|
private java.util.Deque<Scope> |
enclosingScopes
Stack of enclosing scopes; scopes associated with call stack
|
private java.util.List |
expr
The list of expressions to execute.
|
private java.util.List<java.lang.String> |
params
List of parameter names.
|
private java.lang.String |
returnVar
The name of the return variable or
null if the result
of the last expression evaluation should be returned. |
Constructor and Description |
---|
NamedFunction(RuleContainer parent,
java.lang.String expr)
Constructor which assigns this container's enclosing scope and the
infix text of the first expression for this function.
|
Modifier and Type | Method and Description |
---|---|
void |
cleanup()
Termination hook to allow resources to be cleaned up when this object is
about to go out of service.
|
java.lang.Object |
execute(Scope callerScope,
java.lang.Object[] args)
Execute this named function, handling all user provided parameter
assignments before the actual execution.
|
Scope |
getEnclosingScope()
Return the scope of the object in whose scope this function currently
is enclosed.
|
void |
registerExpression(java.lang.String text)
Register a new expression for this named function.
|
void |
registerParameter(java.lang.String name,
java.lang.Class<?> type)
Register a new parameter for this named expression.
|
void |
registerReturn(java.lang.String name,
java.lang.Class<?> type,
java.lang.String expression)
Register a variable which will be returned from this function.
|
Rule |
registerRule(java.lang.String expression,
int type,
java.lang.String file,
int line)
Register a rule in the list of expressions/rules that the function
will execute in order.
|
void |
registerVariable(java.lang.String name,
java.lang.Class<?> type,
java.lang.String expression)
Register a new user-defined local variable with this function.
|
private java.util.List<java.lang.String> params
private java.util.Deque<Scope> enclosingScopes
private java.util.List expr
private java.lang.String returnVar
null
if the result
of the last expression evaluation should be returned.NamedFunction(RuleContainer parent, java.lang.String expr)
parent
- Rule container which provides enclosing scope to this user
function. May be null
.expr
- The infix text of the expression associated with this
instance.public Scope getEnclosingScope()
getEnclosingScope
in interface Scope
null
.public void registerExpression(java.lang.String text)
text
- The infix text of the expression.public void registerParameter(java.lang.String name, java.lang.Class<?> type)
name
- Name by which this parameter will be referenced in the
expression.type
- Data type of the variable. Cannot be null
.SymbolException
- if the parameter's name is already in use in this container's
scope.java.lang.IllegalArgumentException
- if type
is not provided.public void registerReturn(java.lang.String name, java.lang.Class<?> type, java.lang.String expression)
type
and expression
are provided,
type
must match the return type of
expression
.name
- Name by which this variable will be referenced in expressions.type
- Data type of the variable. May be null
if and
only if expression
is not null
and expression
's return type is not
null
.expression
- Expression which will be used to initialize the variable each
time it is reset
by the pattern engine. May be null
if and only
if type
is not null
.SymbolException
- if the variable's name is already in use in this container's
scope.ExpressionException
- if type
is a class which is not assignable from
expression
's return type.java.lang.IllegalArgumentException
- if type
is not provided and it cannot be
determined from expression
.SymbolResolver.resetVariables(com.goldencode.expr.Scope, boolean)
public void registerVariable(java.lang.String name, java.lang.Class<?> type, java.lang.String expression)
type
and expression
are provided,
type
must match the return type of
expression
.name
- Name by which this variable will be referenced in expressions.type
- Data type of the variable. May be null
if and
only if expression
is not null
and expression
's return type is not
null
.expression
- Expression which will be used to initialize the variable each
time it is reset
by the pattern engine. May be null
if and only
if type
is not null
.SymbolException
- if the variable's name is already in use in this function's
scope.ExpressionException
- if type
is a class which is not assignable from
expression
's return type.java.lang.IllegalArgumentException
- if type
is not provided and it cannot be
determined from expression
.SymbolResolver.resetVariables(com.goldencode.expr.Scope, boolean)
public Rule registerRule(java.lang.String expression, int type, java.lang.String file, int line)
expression
- Logical expression which will be compiled into the condition
expression of the rule.type
- Type of rule to add: init, walk, post, etc., using the
RULE_*
constants.file
- The file the rule is defined in, used for tracing.line
- The file line the rule is defined at, used for tracing.java.lang.IllegalArgumentException
- if the rule type is unrecognized.public java.lang.Object execute(Scope callerScope, java.lang.Object[] args)
registerExpression(java.lang.String)
) and
rules (defined via registerRule(java.lang.String, int, java.lang.String, int)
) in the order in which they
were added. Rules are not simple expressions but instead they can
encode complex logical control flow (conditional processing and
looping) in addition to an arbitrary action execution. This means
that there is no single return value that can be captured from a
rule. For this reason, if a rule needs to be used to set a return
value for the function, then an explicit assignment will be needed.
If no explicit assignment to the return variable has occurred, then
the result of the last executed expression will be used as the return
value.callerScope
- Scope of the caller; becomes this function's current,
enclosing scope for the duration of this execution.args
- The array of Object
instances of the correct
data type and in the correct order to match our parameter
list. Each element of the array will be assigned into the
matching parameter in our parameter list before the expressions
are executed.ExpressionException
- if the expression cannot be compiled.java.lang.IllegalArgumentException
- if the number of passed parameters is different than the
number of expected parameters.java.lang.IllegalStateException
- if this named function appears anywhere in the call stack
leading up to this invocation.public void cleanup()