Added LAMBDA (tdf#138749) function Added ISOMITTED (tdf#164510) function Rewrote LET to work with the new LAMBDA Change-Id: I45dbf18c43e56c788848f60cd8380dd8d7c476b5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/206265 Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org> Tested-by: Xisco Fauli <xiscofauli@libreoffice.org>
5.6 KiB
Callable
A callable is a formula data type that represents code that can be called on a (possibly empty) set of arguments to produce a result.
Using Callables
The following elements are involved in using callables:
-
The
StackVarenum providessvCallableto identify callable objects. -
The
FormulaCallableTokenclass allows you to create callable tokens. Pass aFormulaCallableRefto the constructor. UseGetCallableto retrieve the reference. -
The
FormulaCallableclass contains the data for a callable object. It is an abstract base class; you should not instantiate it directly. UseFormulaCallableRefto refer to these objects. -
Three subclasses of
FormulaCallablehave been implemented:-
The
FormulaBuiltInFunctionrepresents a function that is provided by Calc.-
The
FormulaBuiltInFunctionclass stores a table of references to functions that have been accessed. The class should not be instantiated directly. -
If you have an
OpCode, you can retrieve the correspondingFormulaBuiltInFunctionreference by callingFormulaBuiltInFunction::Get().
-
-
The
FormulaExternalFunctionclass represents a function that is external to Calc. These are provided by means of add-ins.- Pass the name of the external function to the constructor to instantiate an object.
-
The
ScFormulaFunctionclass represents a function that has been built using aLAMBDAformula.- To instantiate a
ScFormulaFunction, pass a reference to the interpreter containing theLAMBDA, along with anOUStringvector naming the parameters, and a reference to theTokenArraythat theLAMBDAbody comes from, along with the positions of the beginning and end of theLAMBDAbody within that array.
- To instantiate a
-
The
ScMacroFunctionclass represents a function that is defined as a macro.- Pass the
ScInterpreterand the name of the macro to the constructor to instantiate an object.
- Pass the
-
-
The
OpCodeenum providesocCallas a left-associative binary operator. This operator is automatically inserted byScCompilerbetween the callable name (or expression) and the opening parenthesis of the argument list. The next phase of the compiler (inFormulaCompiler) acts on thatOpCodeto properly build the call in RPN form. -
To execute a
FormulaCallable, useScInterpreter'sScCallmethod. Provide a reference to theFormulaCallable, along with either a vector of arguments (FormulaConstTokenRef) or the number of arguments to extract from the top of the interpreter's stack. The result is placed on the top of the stack.
How it Works
Constructing
-
ScCompiler::CompileStringidentifies the use of a built-in operator without a following parenthesis, and inserts aFormulaBuiltInFunctionthere instead. If a (left) parenthesis does follow the reference to a built-in operator, itsOpCodeis used instead. This makes things more efficient during interpretation. -
ScCompiler::CompileStringalso identifies the use of an external function without a following parenthesis, and inserts aFormulaExternalFunctionthere instead. As with a built-in function, if an external function is called immediately, no callable is created. -
The
LAMBDAoperator (ocLambda) is dealt with (mostly) like other jump operators. See ../sc/README.Lambda.md for details. When anocLambdais interpreted, aScFormulaFunctionis built, which can be called by the interpreter viaScInterpreter::ScCall. -
Macro references produce
ocMacrotokens (inScCompiler::CompileString), which generateScMacroFunctionobjects when interpreted.ScInterpreter::ScCallcan call these.
Compiling
-
ScCompiler::CompileStringidentifies when an open parenthesis appears after either a closing parenthesis, a reference, or a name that doesn't match a built-in operator, and injectsocCallinto the output token stream before continuing. -
FormulaCompiler::CompileTokenArrayincludesCallLinein its binary operator precedence rules.CallLinedetectsocCalland builds the necessary RPN syntax for a call.
Interpreting
-
ScInterpreter::ScCallcollects the arguments provided and theFormulaCallablereference, and passes them on to the otherScInterpreter::ScCallmethods. -
There are two versions of
ScInterpreter::ScCallwhich, combined, are capable of calling the different types of functions. The first accepts aFormulaCallableand an integer, which indicates how many arguments are being passed to it on the stack. The other accepts a vector ofFormulaConstTokenRefobjects, which supplies the argument list directly. The idea is to be able to call whichever method corresponds to the most convenient means of passing the arguments, and let the two versions ofScInterpreter::ScCallfigure out how to actually make the call. -
If a
FormulaCallableneeds to be called by any other means, one of the versions of theScInterpereter::ScCallmethod that accepts arguments may be used. The result appears on the top of the stack.
Subclassing
A subclass must implement a GetOpCode method, whose result uniquely determines
which subclass it is. FormulaBuiltInFunction returns an OpCode corresponding
to one of the built-in operators. FormulaExternalFunction returns ocExternal,
ScFormulaFunction returns ocLambda, and ScMacroFunction returns ocMacro.
The versions of ScInterpreter::ScCall use this information to determine which
subclass is being called, and perform the actions necessary to implement the
call. Note that each subclass has a preferred means of receiving arguments; the
other version of ScInterpreter::ScCall just sets up the arguments and calls
the preferred version.