Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More advanced custom function tutorial #1108

Merged
merged 32 commits into from
Dec 20, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
2889c31
Start writing a custom function example for GREET()
sequba Nov 23, 2022
0f4bcdf
Export FunctionArgumentType enum
sequba Nov 23, 2022
7b3c860
Move custom function tests from square-plugin-example.spec.ts to cust…
sequba Nov 23, 2022
6d0af2e
Add unit tests for custom functions implemented with runFunction
sequba Nov 23, 2022
70c1b49
WIP
sequba Nov 24, 2022
9e67e69
Update the code snippets in the custom functions guide to match the n…
sequba Dec 2, 2022
9e3dbb3
Add info about unit tests to the custom functions guide
sequba Dec 2, 2022
0f25ddf
Merge branch 'develop' into feature/issue-779
sequba Dec 6, 2022
82d0e8b
Rewrite custom function options section in custom functions guide
sequba Dec 6, 2022
fbc1ca9
Export ArraySize class
sequba Dec 10, 2022
60c0ce5
Update custom-functions guide after changes in the demo
sequba Dec 10, 2022
01144a9
Structural changes in the custom-functions guide
sequba Dec 10, 2022
f1615da
Move SimpleRangeValue from ./src/interpreter to ./src so that the typ…
sequba Dec 13, 2022
8d4fca3
Describe DOUBLE_RANGE function in the custom-functions guide
sequba Dec 13, 2022
6b5992d
Use ArraySize in the example of arraySizeMethod in the custom-functio…
sequba Dec 13, 2022
ee375f7
Add changelog entry
sequba Dec 13, 2022
0ab7465
Add the description for the arraySizeMethod option
sequba Dec 13, 2022
b9c6868
Rephrase a few sentences in the custom-functions guide
sequba Dec 14, 2022
fb5e5aa
Improve the description of returnNumberType option in the custom-func…
sequba Dec 14, 2022
befa807
Add default values to the custom function options description
sequba Dec 14, 2022
4f62223
Add possible values to the argumentType description in the custom-fuc…
sequba Dec 14, 2022
ea0f41b
Reduce content duplication on custom function name translations
sequba Dec 14, 2022
682f5d5
Minor improvements to custom-functions guide
sequba Dec 14, 2022
3fa9d33
Merge branch 'develop' into feature/issue-779
sequba Dec 14, 2022
bfbb0f0
grammarly fixes
sequba Dec 14, 2022
56fe511
Reformat table
sequba Dec 14, 2022
32556e4
Improve the description of the vectorization feature
sequba Dec 15, 2022
a6b1e57
Merge branch 'develop' into feature/issue-779
sequba Dec 20, 2022
aef856b
code review fixes
sequba Dec 20, 2022
f629630
Change translations object to be standalone instead of a static prope…
sequba Dec 20, 2022
efe66ef
Use FunctionArgumentType enum in custom functions guide
sequba Dec 20, 2022
318d094
Fix typo
sequba Dec 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/guide/custom-functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Expand the function library of your application, by adding custom functions.

## Add a custom function

As an example, let's create a function that returns the number of letters in the word "HyperFormula".
As an example, let's create a function that accepts a username as a string argument and returns a personalized greeting.

<iframe
src="https://codesandbox.io/embed/github/handsontable/hyperformula-demos/tree/2.2.x/custom-functions?autoresize=1&fontsize=11&hidenavigation=1&theme=light&view=preview"
Expand Down
4 changes: 2 additions & 2 deletions src/ArraySize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {SimpleCellAddress} from './Cell'
import {Config} from './Config'
import {FunctionRegistry} from './interpreter/FunctionRegistry'
import {InterpreterState} from './interpreter/InterpreterState'
import {ArgumentTypes} from './interpreter/plugin/FunctionPlugin'
import {FunctionArgumentType} from './interpreter/plugin/FunctionPlugin'
import {Ast, AstNodeType, ProcedureAst} from './parser'

export class ArraySize {
Expand Down Expand Up @@ -156,7 +156,7 @@ export class ArraySizePredictor {
let maxWidth = 1
let maxHeight = 1
for (let i = 0; i < subChecks.length; i++) {
if (argumentDefinitions[i].argumentType !== ArgumentTypes.RANGE && argumentDefinitions[i].argumentType !== ArgumentTypes.ANY) {
if (argumentDefinitions[i].argumentType !== FunctionArgumentType.RANGE && argumentDefinitions[i].argumentType !== FunctionArgumentType.ANY) {
maxHeight = Math.max(maxHeight, subChecks[i].height)
maxWidth = Math.max(maxWidth, subChecks[i].width)
}
Expand Down
8 changes: 6 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,17 @@ import {ExportedCellChange, ExportedChange, ExportedNamedExpressionChange} from
import {HyperFormula} from './HyperFormula'
import {RawTranslationPackage} from './i18n'
import enGB from './i18n/languages/enGB'
import {FunctionArgument, FunctionPlugin, FunctionPluginDefinition} from './interpreter'
import {FunctionArgument, FunctionPlugin, FunctionPluginDefinition, FunctionArgumentType} from './interpreter'
import {FormatInfo} from './interpreter/InterpreterValue'
import * as plugins from './interpreter/plugin'
import {SimpleRangeValue} from './interpreter/SimpleRangeValue'
import {NamedExpression, NamedExpressionOptions} from './NamedExpressions'
import {SerializedNamedExpression} from './Serialization'
import {Sheet, SheetDimensions, Sheets} from './Sheet'

/** @internal */
/**
* Aggregate class for default export
*/
class HyperFormulaNS extends HyperFormula {
public static HyperFormula = HyperFormula
public static ErrorType = ErrorType
Expand All @@ -71,6 +73,7 @@ class HyperFormulaNS extends HyperFormula {
public static ExpectedOneOfValuesError = ExpectedOneOfValuesError
public static ExpectedValueOfTypeError = ExpectedValueOfTypeError
public static FunctionPlugin = FunctionPlugin
public static FunctionArgumentType = FunctionArgumentType
public static FunctionPluginValidationError = FunctionPluginValidationError
public static InvalidAddressError = InvalidAddressError
public static InvalidArgumentsError = InvalidArgumentsError
Expand Down Expand Up @@ -146,6 +149,7 @@ export {
ExpectedOneOfValuesError,
ExpectedValueOfTypeError,
FunctionPlugin,
FunctionArgumentType,
FunctionPluginValidationError,
InvalidAddressError,
InvalidArgumentsError,
Expand Down
6 changes: 4 additions & 2 deletions src/interpreter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {
FunctionMetadata,
FunctionPlugin,
FunctionPluginDefinition,
ImplementedFunctions
ImplementedFunctions,
FunctionArgumentType,
} from './plugin/FunctionPlugin'

export {
Expand All @@ -18,5 +19,6 @@ export {
FunctionPlugin,
ImplementedFunctions,
FunctionMetadata,
FunctionTranslationsPackage
FunctionTranslationsPackage,
FunctionArgumentType,
}
4 changes: 2 additions & 2 deletions src/interpreter/plugin/AbsPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
import {InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
import {FunctionArgumentType, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'

export class AbsPlugin extends FunctionPlugin implements FunctionPluginTypecheck<AbsPlugin> {
public static implementedFunctions = {
'ABS': {
method: 'abs',
parameters: [
{argumentType: ArgumentTypes.NUMBER}
{argumentType: FunctionArgumentType.NUMBER}
]
},
}
Expand Down
14 changes: 7 additions & 7 deletions src/interpreter/plugin/ArrayPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {coerceScalarToBoolean} from '../ArithmeticHelper'
import {InterpreterState} from '../InterpreterState'
import {InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {SimpleRangeValue} from '../SimpleRangeValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
import {FunctionArgumentType, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'

export class ArrayPlugin extends FunctionPlugin implements FunctionPluginTypecheck<ArrayPlugin> {
public static implementedFunctions = {
Expand All @@ -20,16 +20,16 @@ export class ArrayPlugin extends FunctionPlugin implements FunctionPluginTypeche
arraySizeMethod: 'arrayformulaArraySize',
arrayFunction: true,
parameters: [
{argumentType: ArgumentTypes.ANY}
{argumentType: FunctionArgumentType.ANY}
],
},
'ARRAY_CONSTRAIN': {
method: 'arrayconstrain',
arraySizeMethod: 'arrayconstrainArraySize',
parameters: [
{argumentType: ArgumentTypes.RANGE},
{argumentType: ArgumentTypes.INTEGER, minValue: 1},
{argumentType: ArgumentTypes.INTEGER, minValue: 1},
{argumentType: FunctionArgumentType.RANGE},
{argumentType: FunctionArgumentType.INTEGER, minValue: 1},
{argumentType: FunctionArgumentType.INTEGER, minValue: 1},
],
vectorizationForbidden: true,
},
Expand All @@ -38,8 +38,8 @@ export class ArrayPlugin extends FunctionPlugin implements FunctionPluginTypeche
arraySizeMethod: 'filterArraySize',
arrayFunction: true,
parameters: [
{argumentType: ArgumentTypes.RANGE},
{argumentType: ArgumentTypes.RANGE},
{argumentType: FunctionArgumentType.RANGE},
{argumentType: FunctionArgumentType.RANGE},
],
repeatLastArgs: 1,
}
Expand Down
10 changes: 5 additions & 5 deletions src/interpreter/plugin/BitShiftPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {ErrorMessage} from '../../error-message'
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
import {InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
import {FunctionArgumentType, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'

const MAX_48BIT_INTEGER = 281474976710655
const SHIFT_MIN_POSITIONS = -53
Expand All @@ -19,15 +19,15 @@ export class BitShiftPlugin extends FunctionPlugin implements FunctionPluginType
'BITLSHIFT': {
method: 'bitlshift',
parameters: [
{argumentType: ArgumentTypes.INTEGER, minValue: 0},
{argumentType: ArgumentTypes.INTEGER, minValue: SHIFT_MIN_POSITIONS, maxValue: SHIFT_MAX_POSITIONS},
{argumentType: FunctionArgumentType.INTEGER, minValue: 0},
{argumentType: FunctionArgumentType.INTEGER, minValue: SHIFT_MIN_POSITIONS, maxValue: SHIFT_MAX_POSITIONS},
]
},
'BITRSHIFT': {
method: 'bitrshift',
parameters: [
{argumentType: ArgumentTypes.INTEGER, minValue: 0},
{argumentType: ArgumentTypes.INTEGER, minValue: SHIFT_MIN_POSITIONS, maxValue: SHIFT_MAX_POSITIONS},
{argumentType: FunctionArgumentType.INTEGER, minValue: 0},
{argumentType: FunctionArgumentType.INTEGER, minValue: SHIFT_MIN_POSITIONS, maxValue: SHIFT_MAX_POSITIONS},
]
},
}
Expand Down
14 changes: 7 additions & 7 deletions src/interpreter/plugin/BitwiseLogicOperationsPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,29 @@
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
import {InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
import {FunctionArgumentType, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'

export class BitwiseLogicOperationsPlugin extends FunctionPlugin implements FunctionPluginTypecheck<BitwiseLogicOperationsPlugin> {
public static implementedFunctions = {
'BITAND': {
method: 'bitand',
parameters: [
{argumentType: ArgumentTypes.INTEGER, minValue: 0},
{argumentType: ArgumentTypes.INTEGER, minValue: 0},
{argumentType: FunctionArgumentType.INTEGER, minValue: 0},
{argumentType: FunctionArgumentType.INTEGER, minValue: 0},
]
},
'BITOR': {
method: 'bitor',
parameters: [
{argumentType: ArgumentTypes.INTEGER, minValue: 0},
{argumentType: ArgumentTypes.INTEGER, minValue: 0},
{argumentType: FunctionArgumentType.INTEGER, minValue: 0},
{argumentType: FunctionArgumentType.INTEGER, minValue: 0},
]
},
'BITXOR': {
method: 'bitxor',
parameters: [
{argumentType: ArgumentTypes.INTEGER, minValue: 0},
{argumentType: ArgumentTypes.INTEGER, minValue: 0},
{argumentType: FunctionArgumentType.INTEGER, minValue: 0},
{argumentType: FunctionArgumentType.INTEGER, minValue: 0},
]
},
}
Expand Down
34 changes: 17 additions & 17 deletions src/interpreter/plugin/BooleanPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {ErrorMessage} from '../../error-message'
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
import {InternalNoErrorScalarValue, InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
import {FunctionArgumentType, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'

/**
* Interpreter plugin containing boolean functions
Expand All @@ -26,69 +26,69 @@ export class BooleanPlugin extends FunctionPlugin implements FunctionPluginTypec
'IF': {
method: 'conditionalIf',
parameters: [
{argumentType: ArgumentTypes.BOOLEAN},
{argumentType: ArgumentTypes.SCALAR, passSubtype: true},
{argumentType: ArgumentTypes.SCALAR, defaultValue: false, passSubtype: true},
{argumentType: FunctionArgumentType.BOOLEAN},
{argumentType: FunctionArgumentType.SCALAR, passSubtype: true},
{argumentType: FunctionArgumentType.SCALAR, defaultValue: false, passSubtype: true},
],
},
'AND': {
method: 'and',
parameters: [
{argumentType: ArgumentTypes.BOOLEAN},
{argumentType: FunctionArgumentType.BOOLEAN},
],
repeatLastArgs: 1,
expandRanges: true,
},
'OR': {
method: 'or',
parameters: [
{argumentType: ArgumentTypes.BOOLEAN},
{argumentType: FunctionArgumentType.BOOLEAN},
],
repeatLastArgs: 1,
expandRanges: true,
},
'XOR': {
method: 'xor',
parameters: [
{argumentType: ArgumentTypes.BOOLEAN},
{argumentType: FunctionArgumentType.BOOLEAN},
],
repeatLastArgs: 1,
expandRanges: true,
},
'NOT': {
method: 'not',
parameters: [
{argumentType: ArgumentTypes.BOOLEAN},
{argumentType: FunctionArgumentType.BOOLEAN},
]
},
'SWITCH': {
method: 'switch',
parameters: [
{argumentType: ArgumentTypes.NOERROR},
{argumentType: ArgumentTypes.SCALAR, passSubtype: true},
{argumentType: ArgumentTypes.SCALAR, passSubtype: true},
{argumentType: FunctionArgumentType.NOERROR},
{argumentType: FunctionArgumentType.SCALAR, passSubtype: true},
{argumentType: FunctionArgumentType.SCALAR, passSubtype: true},
],
repeatLastArgs: 1,
},
'IFERROR': {
method: 'iferror',
parameters: [
{argumentType: ArgumentTypes.SCALAR, passSubtype: true},
{argumentType: ArgumentTypes.SCALAR, passSubtype: true},
{argumentType: FunctionArgumentType.SCALAR, passSubtype: true},
{argumentType: FunctionArgumentType.SCALAR, passSubtype: true},
]
},
'IFNA': {
method: 'ifna',
parameters: [
{argumentType: ArgumentTypes.SCALAR, passSubtype: true},
{argumentType: ArgumentTypes.SCALAR, passSubtype: true},
{argumentType: FunctionArgumentType.SCALAR, passSubtype: true},
{argumentType: FunctionArgumentType.SCALAR, passSubtype: true},
]
},
'CHOOSE': {
method: 'choose',
parameters: [
{argumentType: ArgumentTypes.INTEGER, minValue: 1},
{argumentType: ArgumentTypes.SCALAR, passSubtype: true},
{argumentType: FunctionArgumentType.INTEGER, minValue: 1},
{argumentType: FunctionArgumentType.SCALAR, passSubtype: true},
],
repeatLastArgs: 1,
},
Expand Down
6 changes: 3 additions & 3 deletions src/interpreter/plugin/CharPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@ import {ErrorMessage} from '../../error-message'
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
import {InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
import {FunctionArgumentType, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'

export class CharPlugin extends FunctionPlugin implements FunctionPluginTypecheck<CharPlugin> {
public static implementedFunctions = {
'CHAR': {
method: 'char',
parameters: [
{argumentType: ArgumentTypes.NUMBER}
{argumentType: FunctionArgumentType.NUMBER}
],
},
'UNICHAR': {
method: 'unichar',
parameters: [
{argumentType: ArgumentTypes.NUMBER}
{argumentType: FunctionArgumentType.NUMBER}
],
},
}
Expand Down
6 changes: 3 additions & 3 deletions src/interpreter/plugin/CodePlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@ import {ErrorMessage} from '../../error-message'
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
import {InterpreterValue} from '../InterpreterValue'
import {ArgumentTypes, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'
import {FunctionArgumentType, FunctionPlugin, FunctionPluginTypecheck} from './FunctionPlugin'

export class CodePlugin extends FunctionPlugin implements FunctionPluginTypecheck<CodePlugin> {
public static implementedFunctions = {
'CODE': {
method: 'code',
parameters: [
{argumentType: ArgumentTypes.STRING}
{argumentType: FunctionArgumentType.STRING}
]
},
'UNICODE': {
method: 'unicode',
parameters: [
{argumentType: ArgumentTypes.STRING}
{argumentType: FunctionArgumentType.STRING}
]
},
}
Expand Down
Loading