react-native-divkit 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (322) hide show
  1. package/LICENSE +176 -0
  2. package/README.md +340 -0
  3. package/dist/DivKit.d.ts +68 -0
  4. package/dist/DivKit.d.ts.map +1 -0
  5. package/dist/DivKit.js +400 -0
  6. package/dist/DivKit.js.map +1 -0
  7. package/dist/actions/array.d.ts +8 -0
  8. package/dist/actions/array.d.ts.map +1 -0
  9. package/dist/actions/array.js +139 -0
  10. package/dist/actions/array.js.map +1 -0
  11. package/dist/actions/copyToClipboard.d.ts +22 -0
  12. package/dist/actions/copyToClipboard.d.ts.map +1 -0
  13. package/dist/actions/copyToClipboard.js +63 -0
  14. package/dist/actions/copyToClipboard.js.map +1 -0
  15. package/dist/actions/dict.d.ts +6 -0
  16. package/dist/actions/dict.d.ts.map +1 -0
  17. package/dist/actions/dict.js +58 -0
  18. package/dist/actions/dict.js.map +1 -0
  19. package/dist/actions/index.d.ts +11 -0
  20. package/dist/actions/index.d.ts.map +1 -0
  21. package/dist/actions/index.js +11 -0
  22. package/dist/actions/index.js.map +1 -0
  23. package/dist/actions/updateStructure.d.ts +6 -0
  24. package/dist/actions/updateStructure.d.ts.map +1 -0
  25. package/dist/actions/updateStructure.js +116 -0
  26. package/dist/actions/updateStructure.js.map +1 -0
  27. package/dist/components/DivComponent.d.ts +29 -0
  28. package/dist/components/DivComponent.d.ts.map +1 -0
  29. package/dist/components/DivComponent.js +62 -0
  30. package/dist/components/DivComponent.js.map +1 -0
  31. package/dist/components/container/DivContainer.d.ts +26 -0
  32. package/dist/components/container/DivContainer.d.ts.map +1 -0
  33. package/dist/components/container/DivContainer.js +172 -0
  34. package/dist/components/container/DivContainer.js.map +1 -0
  35. package/dist/components/container/index.d.ts +3 -0
  36. package/dist/components/container/index.d.ts.map +1 -0
  37. package/dist/components/container/index.js +2 -0
  38. package/dist/components/container/index.js.map +1 -0
  39. package/dist/components/image/DivImage.d.ts +29 -0
  40. package/dist/components/image/DivImage.d.ts.map +1 -0
  41. package/dist/components/image/DivImage.js +122 -0
  42. package/dist/components/image/DivImage.js.map +1 -0
  43. package/dist/components/image/index.d.ts +3 -0
  44. package/dist/components/image/index.d.ts.map +1 -0
  45. package/dist/components/image/index.js +2 -0
  46. package/dist/components/image/index.js.map +1 -0
  47. package/dist/components/index.d.ts +14 -0
  48. package/dist/components/index.d.ts.map +1 -0
  49. package/dist/components/index.js +11 -0
  50. package/dist/components/index.js.map +1 -0
  51. package/dist/components/state/DivState.d.ts +26 -0
  52. package/dist/components/state/DivState.d.ts.map +1 -0
  53. package/dist/components/state/DivState.js +121 -0
  54. package/dist/components/state/DivState.js.map +1 -0
  55. package/dist/components/state/index.d.ts +3 -0
  56. package/dist/components/state/index.d.ts.map +1 -0
  57. package/dist/components/state/index.js +2 -0
  58. package/dist/components/state/index.js.map +1 -0
  59. package/dist/components/text/DivText.d.ts +28 -0
  60. package/dist/components/text/DivText.d.ts.map +1 -0
  61. package/dist/components/text/DivText.js +143 -0
  62. package/dist/components/text/DivText.js.map +1 -0
  63. package/dist/components/text/index.d.ts +3 -0
  64. package/dist/components/text/index.d.ts.map +1 -0
  65. package/dist/components/text/index.js +2 -0
  66. package/dist/components/text/index.js.map +1 -0
  67. package/dist/components/utilities/Outer.d.ts +17 -0
  68. package/dist/components/utilities/Outer.d.ts.map +1 -0
  69. package/dist/components/utilities/Outer.js +210 -0
  70. package/dist/components/utilities/Outer.js.map +1 -0
  71. package/dist/components/utilities/Unknown.d.ts +11 -0
  72. package/dist/components/utilities/Unknown.d.ts.map +1 -0
  73. package/dist/components/utilities/Unknown.js +50 -0
  74. package/dist/components/utilities/Unknown.js.map +1 -0
  75. package/dist/components/utilities/index.d.ts +5 -0
  76. package/dist/components/utilities/index.d.ts.map +1 -0
  77. package/dist/components/utilities/index.js +3 -0
  78. package/dist/components/utilities/index.js.map +1 -0
  79. package/dist/context/ActionContext.d.ts +25 -0
  80. package/dist/context/ActionContext.d.ts.map +1 -0
  81. package/dist/context/ActionContext.js +20 -0
  82. package/dist/context/ActionContext.js.map +1 -0
  83. package/dist/context/DivKitContext.d.ts +33 -0
  84. package/dist/context/DivKitContext.d.ts.map +1 -0
  85. package/dist/context/DivKitContext.js +14 -0
  86. package/dist/context/DivKitContext.js.map +1 -0
  87. package/dist/context/EnabledContext.d.ts +31 -0
  88. package/dist/context/EnabledContext.d.ts.map +1 -0
  89. package/dist/context/EnabledContext.js +31 -0
  90. package/dist/context/EnabledContext.js.map +1 -0
  91. package/dist/context/StateContext.d.ts +57 -0
  92. package/dist/context/StateContext.d.ts.map +1 -0
  93. package/dist/context/StateContext.js +20 -0
  94. package/dist/context/StateContext.js.map +1 -0
  95. package/dist/context/index.d.ts +9 -0
  96. package/dist/context/index.d.ts.map +1 -0
  97. package/dist/context/index.js +9 -0
  98. package/dist/context/index.js.map +1 -0
  99. package/dist/expressions/bigint.d.ts +8 -0
  100. package/dist/expressions/bigint.d.ts.map +1 -0
  101. package/dist/expressions/bigint.js +31 -0
  102. package/dist/expressions/bigint.js.map +1 -0
  103. package/dist/expressions/const.d.ts +15 -0
  104. package/dist/expressions/const.d.ts.map +1 -0
  105. package/dist/expressions/const.js +15 -0
  106. package/dist/expressions/const.js.map +1 -0
  107. package/dist/expressions/eval.d.ts +77 -0
  108. package/dist/expressions/eval.d.ts.map +1 -0
  109. package/dist/expressions/eval.js +459 -0
  110. package/dist/expressions/eval.js.map +1 -0
  111. package/dist/expressions/expressions.d.ts +7 -0
  112. package/dist/expressions/expressions.d.ts.map +1 -0
  113. package/dist/expressions/expressions.js +3191 -0
  114. package/dist/expressions/expressions.js.map +1 -0
  115. package/dist/expressions/funcs/array.d.ts +2 -0
  116. package/dist/expressions/funcs/array.d.ts.map +1 -0
  117. package/dist/expressions/funcs/array.js +381 -0
  118. package/dist/expressions/funcs/array.js.map +1 -0
  119. package/dist/expressions/funcs/colors.d.ts +2 -0
  120. package/dist/expressions/funcs/colors.d.ts.map +1 -0
  121. package/dist/expressions/funcs/colors.js +75 -0
  122. package/dist/expressions/funcs/colors.js.map +1 -0
  123. package/dist/expressions/funcs/customFuncs.d.ts +8 -0
  124. package/dist/expressions/funcs/customFuncs.d.ts.map +1 -0
  125. package/dist/expressions/funcs/customFuncs.js +114 -0
  126. package/dist/expressions/funcs/customFuncs.js.map +1 -0
  127. package/dist/expressions/funcs/datetime.d.ts +2 -0
  128. package/dist/expressions/funcs/datetime.d.ts.map +1 -0
  129. package/dist/expressions/funcs/datetime.js +182 -0
  130. package/dist/expressions/funcs/datetime.js.map +1 -0
  131. package/dist/expressions/funcs/dict.d.ts +2 -0
  132. package/dist/expressions/funcs/dict.d.ts.map +1 -0
  133. package/dist/expressions/funcs/dict.js +170 -0
  134. package/dist/expressions/funcs/dict.js.map +1 -0
  135. package/dist/expressions/funcs/funcs.d.ts +80 -0
  136. package/dist/expressions/funcs/funcs.d.ts.map +1 -0
  137. package/dist/expressions/funcs/funcs.js +146 -0
  138. package/dist/expressions/funcs/funcs.js.map +1 -0
  139. package/dist/expressions/funcs/index.d.ts +2 -0
  140. package/dist/expressions/funcs/index.d.ts.map +1 -0
  141. package/dist/expressions/funcs/index.js +23 -0
  142. package/dist/expressions/funcs/index.js.map +1 -0
  143. package/dist/expressions/funcs/interval.d.ts +2 -0
  144. package/dist/expressions/funcs/interval.d.ts.map +1 -0
  145. package/dist/expressions/funcs/interval.js +61 -0
  146. package/dist/expressions/funcs/interval.js.map +1 -0
  147. package/dist/expressions/funcs/math.d.ts +2 -0
  148. package/dist/expressions/funcs/math.d.ts.map +1 -0
  149. package/dist/expressions/funcs/math.js +324 -0
  150. package/dist/expressions/funcs/math.js.map +1 -0
  151. package/dist/expressions/funcs/std.d.ts +2 -0
  152. package/dist/expressions/funcs/std.d.ts.map +1 -0
  153. package/dist/expressions/funcs/std.js +293 -0
  154. package/dist/expressions/funcs/std.js.map +1 -0
  155. package/dist/expressions/funcs/stored.d.ts +4 -0
  156. package/dist/expressions/funcs/stored.d.ts.map +1 -0
  157. package/dist/expressions/funcs/stored.js +62 -0
  158. package/dist/expressions/funcs/stored.js.map +1 -0
  159. package/dist/expressions/funcs/strings.d.ts +2 -0
  160. package/dist/expressions/funcs/strings.d.ts.map +1 -0
  161. package/dist/expressions/funcs/strings.js +158 -0
  162. package/dist/expressions/funcs/strings.js.map +1 -0
  163. package/dist/expressions/funcs/trigonometry.d.ts +2 -0
  164. package/dist/expressions/funcs/trigonometry.d.ts.map +1 -0
  165. package/dist/expressions/funcs/trigonometry.js +92 -0
  166. package/dist/expressions/funcs/trigonometry.js.map +1 -0
  167. package/dist/expressions/json.d.ts +18 -0
  168. package/dist/expressions/json.d.ts.map +1 -0
  169. package/dist/expressions/json.js +271 -0
  170. package/dist/expressions/json.js.map +1 -0
  171. package/dist/expressions/parserCache.d.ts +4 -0
  172. package/dist/expressions/parserCache.d.ts.map +1 -0
  173. package/dist/expressions/parserCache.js +23 -0
  174. package/dist/expressions/parserCache.js.map +1 -0
  175. package/dist/expressions/simpleUnescapeString.d.ts +2 -0
  176. package/dist/expressions/simpleUnescapeString.d.ts.map +1 -0
  177. package/dist/expressions/simpleUnescapeString.js +61 -0
  178. package/dist/expressions/simpleUnescapeString.js.map +1 -0
  179. package/dist/expressions/utils.d.ts +29 -0
  180. package/dist/expressions/utils.d.ts.map +1 -0
  181. package/dist/expressions/utils.js +236 -0
  182. package/dist/expressions/utils.js.map +1 -0
  183. package/dist/expressions/variable.d.ts +82 -0
  184. package/dist/expressions/variable.d.ts.map +1 -0
  185. package/dist/expressions/variable.js +337 -0
  186. package/dist/expressions/variable.js.map +1 -0
  187. package/dist/expressions/walk.d.ts +7 -0
  188. package/dist/expressions/walk.d.ts.map +1 -0
  189. package/dist/expressions/walk.js +39 -0
  190. package/dist/expressions/walk.js.map +1 -0
  191. package/dist/hooks/index.d.ts +8 -0
  192. package/dist/hooks/index.d.ts.map +1 -0
  193. package/dist/hooks/index.js +11 -0
  194. package/dist/hooks/index.js.map +1 -0
  195. package/dist/hooks/useAction.d.ts +102 -0
  196. package/dist/hooks/useAction.d.ts.map +1 -0
  197. package/dist/hooks/useAction.js +116 -0
  198. package/dist/hooks/useAction.js.map +1 -0
  199. package/dist/hooks/useDerivedFromVars.d.ts +72 -0
  200. package/dist/hooks/useDerivedFromVars.d.ts.map +1 -0
  201. package/dist/hooks/useDerivedFromVars.js +100 -0
  202. package/dist/hooks/useDerivedFromVars.js.map +1 -0
  203. package/dist/hooks/useVariable.d.ts +86 -0
  204. package/dist/hooks/useVariable.d.ts.map +1 -0
  205. package/dist/hooks/useVariable.js +130 -0
  206. package/dist/hooks/useVariable.js.map +1 -0
  207. package/dist/index.d.ts +30 -0
  208. package/dist/index.d.ts.map +1 -0
  209. package/dist/index.js +28 -0
  210. package/dist/index.js.map +1 -0
  211. package/dist/stores/createObservable.d.ts +38 -0
  212. package/dist/stores/createObservable.d.ts.map +1 -0
  213. package/dist/stores/createObservable.js +49 -0
  214. package/dist/stores/createObservable.js.map +1 -0
  215. package/dist/utils/applyTemplate.d.ts +8 -0
  216. package/dist/utils/applyTemplate.d.ts.map +1 -0
  217. package/dist/utils/applyTemplate.js +94 -0
  218. package/dist/utils/applyTemplate.js.map +1 -0
  219. package/dist/utils/correctColor.d.ts +18 -0
  220. package/dist/utils/correctColor.d.ts.map +1 -0
  221. package/dist/utils/correctColor.js +79 -0
  222. package/dist/utils/correctColor.js.map +1 -0
  223. package/dist/utils/escapeRegExp.d.ts +2 -0
  224. package/dist/utils/escapeRegExp.d.ts.map +1 -0
  225. package/dist/utils/escapeRegExp.js +4 -0
  226. package/dist/utils/escapeRegExp.js.map +1 -0
  227. package/dist/utils/formatDate.d.ts +6 -0
  228. package/dist/utils/formatDate.d.ts.map +1 -0
  229. package/dist/utils/formatDate.js +325 -0
  230. package/dist/utils/formatDate.js.map +1 -0
  231. package/dist/utils/padLeft.d.ts +2 -0
  232. package/dist/utils/padLeft.d.ts.map +1 -0
  233. package/dist/utils/padLeft.js +7 -0
  234. package/dist/utils/padLeft.js.map +1 -0
  235. package/dist/utils/uniq.d.ts +2 -0
  236. package/dist/utils/uniq.d.ts.map +1 -0
  237. package/dist/utils/uniq.js +4 -0
  238. package/dist/utils/uniq.js.map +1 -0
  239. package/dist/utils/wrapError.d.ts +10 -0
  240. package/dist/utils/wrapError.d.ts.map +1 -0
  241. package/dist/utils/wrapError.js +9 -0
  242. package/dist/utils/wrapError.js.map +1 -0
  243. package/package.json +58 -0
  244. package/src/DivKit.tsx +542 -0
  245. package/src/actions/array.ts +170 -0
  246. package/src/actions/copyToClipboard.ts +82 -0
  247. package/src/actions/dict.ts +71 -0
  248. package/src/actions/index.ts +11 -0
  249. package/src/actions/updateStructure.ts +134 -0
  250. package/src/components/DivComponent.tsx +75 -0
  251. package/src/components/README.md +230 -0
  252. package/src/components/container/DivContainer.tsx +222 -0
  253. package/src/components/container/index.ts +2 -0
  254. package/src/components/image/DivImage.tsx +172 -0
  255. package/src/components/image/index.ts +2 -0
  256. package/src/components/index.ts +20 -0
  257. package/src/components/state/DivState.tsx +146 -0
  258. package/src/components/state/index.ts +2 -0
  259. package/src/components/text/DivText.tsx +186 -0
  260. package/src/components/text/index.ts +2 -0
  261. package/src/components/utilities/Outer.tsx +239 -0
  262. package/src/components/utilities/README.md +175 -0
  263. package/src/components/utilities/Unknown.tsx +60 -0
  264. package/src/components/utilities/index.ts +4 -0
  265. package/src/context/ActionContext.tsx +37 -0
  266. package/src/context/DivKitContext.tsx +54 -0
  267. package/src/context/EnabledContext.tsx +50 -0
  268. package/src/context/StateContext.tsx +75 -0
  269. package/src/context/index.ts +33 -0
  270. package/src/expressions/ast.d.ts +101 -0
  271. package/src/expressions/bigint.ts +38 -0
  272. package/src/expressions/const.ts +16 -0
  273. package/src/expressions/eval.ts +669 -0
  274. package/src/expressions/expressions.peggy +235 -0
  275. package/src/expressions/expressions.ts +2854 -0
  276. package/src/expressions/funcs/array.ts +412 -0
  277. package/src/expressions/funcs/colors.ts +100 -0
  278. package/src/expressions/funcs/customFuncs.ts +139 -0
  279. package/src/expressions/funcs/datetime.ts +232 -0
  280. package/src/expressions/funcs/dict.ts +207 -0
  281. package/src/expressions/funcs/funcs.ts +323 -0
  282. package/src/expressions/funcs/index.ts +23 -0
  283. package/src/expressions/funcs/interval.ts +76 -0
  284. package/src/expressions/funcs/math.ts +395 -0
  285. package/src/expressions/funcs/std.ts +392 -0
  286. package/src/expressions/funcs/stored.ts +62 -0
  287. package/src/expressions/funcs/strings.ts +200 -0
  288. package/src/expressions/funcs/trigonometry.ts +108 -0
  289. package/src/expressions/json.ts +367 -0
  290. package/src/expressions/parserCache.ts +32 -0
  291. package/src/expressions/simpleUnescapeString.ts +57 -0
  292. package/src/expressions/utils.ts +271 -0
  293. package/src/expressions/variable.ts +429 -0
  294. package/src/expressions/walk.ts +43 -0
  295. package/src/hooks/README.md +265 -0
  296. package/src/hooks/index.ts +28 -0
  297. package/src/hooks/useAction.ts +152 -0
  298. package/src/hooks/useDerivedFromVars.ts +187 -0
  299. package/src/hooks/useVariable.ts +157 -0
  300. package/src/index.ts +97 -0
  301. package/src/stores/createObservable.ts +64 -0
  302. package/src/types/alignment.d.ts +13 -0
  303. package/src/types/background.d.ts +71 -0
  304. package/src/types/base.d.ts +224 -0
  305. package/src/types/border.d.ts +46 -0
  306. package/src/types/componentContext.d.ts +98 -0
  307. package/src/types/container.d.ts +40 -0
  308. package/src/types/edgeInserts.d.ts +9 -0
  309. package/src/types/general.d.ts +3 -0
  310. package/src/types/image.d.ts +33 -0
  311. package/src/types/imageScale.d.ts +1 -0
  312. package/src/types/layoutParams.d.ts +27 -0
  313. package/src/types/sizes.d.ts +37 -0
  314. package/src/types/state.d.ts +19 -0
  315. package/src/types/text.d.ts +126 -0
  316. package/src/utils/applyTemplate.ts +145 -0
  317. package/src/utils/correctColor.ts +102 -0
  318. package/src/utils/escapeRegExp.ts +3 -0
  319. package/src/utils/formatDate.ts +385 -0
  320. package/src/utils/padLeft.ts +6 -0
  321. package/src/utils/uniq.ts +3 -0
  322. package/src/utils/wrapError.ts +21 -0
@@ -0,0 +1,669 @@
1
+ /* eslint-disable max-depth */
2
+ /* eslint-disable no-else-return */
3
+
4
+ import type {
5
+ BinaryExpression, BooleanLiteral, CallExpression, CompareOperator,
6
+ ConditionalExpression, EqualityOperator, FactorOperator, IntegerLiteral,
7
+ LogicalExpression,
8
+ MethodExpression,
9
+ Node, NumberLiteral, StringLiteral, SumOperator,
10
+ TemplateLiteral,
11
+ TryExpression,
12
+ UnaryExpression, Variable
13
+ } from './ast';
14
+ import type { WrappedError } from '../utils/wrapError';
15
+ import { convertArgs, findBestMatchedFunc, type Func, funcByArgs, type FuncMatch, type FuncMatchError, funcs, methodByArgs, methods } from './funcs/funcs';
16
+ import {
17
+ checkIntegerOverflow,
18
+ evalError,
19
+ evalOuterError,
20
+ FuncError,
21
+ integerToNumber,
22
+ roundInteger,
23
+ typeToString,
24
+ valToInternal,
25
+ valToPreview,
26
+ valToString
27
+ } from './utils';
28
+ import { BOOLEAN, DATETIME, INTEGER, NUMBER, STRING } from './const';
29
+ import { register } from './funcs';
30
+ import { Variable as VariableInstance, variableToValue, type VariableType } from './variable';
31
+ import { toBigInt } from './bigint';
32
+ import type { Store } from '../../typings/store';
33
+ import type { CustomFunctions } from './funcs/customFuncs';
34
+
35
+ export type VariablesMap = Map<string, VariableInstance>;
36
+
37
+ export type EvalTypes = 'string' | 'number' | 'integer' | 'boolean' | 'color' | 'url' | 'datetime' | 'dict' | 'array' | 'function';
38
+
39
+ export type EvalTypesWithoutDatetime = 'string' | 'number' | 'integer' | 'boolean' | 'color' | 'url' | 'dict' | 'array' | 'function';
40
+
41
+ export interface EvalValueBase {
42
+ type: string;
43
+ value: unknown;
44
+ }
45
+
46
+ export interface StringValue extends EvalValueBase {
47
+ type: 'string';
48
+ value: string;
49
+ }
50
+
51
+ export interface UrlValue extends EvalValueBase {
52
+ type: 'url';
53
+ value: string;
54
+ }
55
+
56
+ export interface ColorValue extends EvalValueBase {
57
+ type: 'color';
58
+ value: string;
59
+ }
60
+
61
+ export interface NumberValue extends EvalValueBase {
62
+ type: 'number';
63
+ value: number;
64
+ }
65
+
66
+ export interface IntegerValue extends EvalValueBase {
67
+ type: 'integer';
68
+ value: bigint;
69
+ }
70
+
71
+ export interface BooleanValue extends EvalValueBase {
72
+ type: 'boolean';
73
+ value: number;
74
+ }
75
+
76
+ export interface DatetimeValue extends EvalValueBase {
77
+ type: 'datetime';
78
+ value: Date;
79
+ }
80
+
81
+ export interface DictValue extends EvalValueBase {
82
+ type: 'dict';
83
+ value: object;
84
+ }
85
+
86
+ export interface ArrayValue extends EvalValueBase {
87
+ type: 'array';
88
+ value: unknown[];
89
+ }
90
+
91
+ export interface FuncValue extends EvalValueBase {
92
+ type: 'function';
93
+ value: Func[];
94
+ }
95
+
96
+ export type EvalValue = StringValue | UrlValue | ColorValue | NumberValue | IntegerValue |
97
+ BooleanValue | DatetimeValue | DictValue | ArrayValue | FuncValue;
98
+
99
+ export interface EvalError {
100
+ type: 'error';
101
+ value: string;
102
+ }
103
+
104
+ export type EvalResult = EvalValue | EvalError;
105
+
106
+ export interface EvalContext {
107
+ variables: VariablesMap;
108
+ customFunctions: CustomFunctions | undefined;
109
+ warnings: WrappedError[];
110
+ store?: Store;
111
+ weekStartDay: number;
112
+ storeUsedVars?: Set<VariableInstance<any, VariableType, any>>;
113
+ }
114
+
115
+ register();
116
+
117
+ function evalStringLiteral(_ctx: EvalContext, expr: StringLiteral): EvalValue {
118
+ return {
119
+ type: STRING,
120
+ value: expr.value
121
+ };
122
+ }
123
+
124
+ function evalNumberLiteral(_ctx: EvalContext, expr: NumberLiteral): EvalValue {
125
+ return {
126
+ type: NUMBER,
127
+ value: expr.value
128
+ };
129
+ }
130
+
131
+ function evalIntegerLiteral(ctx: EvalContext, expr: IntegerLiteral): EvalValue {
132
+ checkIntegerOverflow(ctx, expr.value);
133
+
134
+ return {
135
+ type: INTEGER,
136
+ value: expr.value
137
+ };
138
+ }
139
+
140
+ function evalBooleanLiteral(_ctx: EvalContext, expr: BooleanLiteral): EvalValue {
141
+ return {
142
+ type: BOOLEAN,
143
+ value: expr.value ? 1 : 0
144
+ };
145
+ }
146
+
147
+ function evalUnary(ctx: EvalContext, expr: UnaryExpression): EvalValue {
148
+ const val = valToInternal(evalAny(ctx, expr.argument));
149
+
150
+ switch (expr.operator) {
151
+ case '!':
152
+ if (val.type === BOOLEAN) {
153
+ return {
154
+ type: BOOLEAN,
155
+ value: val.value ? 0 : 1
156
+ };
157
+ } else {
158
+ evalError(`${expr.operator}${valToPreview(val)}`, 'A Boolean is expected after a unary not.');
159
+ }
160
+ case '+':
161
+ case '-':
162
+ const mul = expr.operator === '+' ? 1 : -1;
163
+
164
+ if (val.type === INTEGER) {
165
+ const value = val.value * toBigInt(mul);
166
+
167
+ checkIntegerOverflow(ctx, value);
168
+
169
+ return {
170
+ type: INTEGER,
171
+ value
172
+ };
173
+ } else if (val.type === NUMBER) {
174
+ return {
175
+ type: NUMBER,
176
+ value: val.value * mul
177
+ };
178
+ } else {
179
+ evalError(
180
+ `${expr.operator}${valToPreview(val)}`,
181
+ `A Number is expected after a unary ${expr.operator === '+' ? 'plus' : 'minus'}.`
182
+ );
183
+ }
184
+ }
185
+ }
186
+
187
+ function evalConditional(ctx: EvalContext, expr: ConditionalExpression): EvalValue {
188
+ const test = valToInternal(evalAny(ctx, expr.test));
189
+ if (test.type === BOOLEAN) {
190
+ if (test.value) {
191
+ return evalAny(ctx, expr.consequent);
192
+ } else {
193
+ return evalAny(ctx, expr.alternate);
194
+ }
195
+ } else {
196
+ evalError(
197
+ `${valToPreview(test)} ? ${valToPreview(evalAny(ctx, expr.consequent))} : ${valToPreview(evalAny(ctx, expr.alternate))}`,
198
+ 'Ternary must be called with a Boolean value as a condition.'
199
+ );
200
+ }
201
+ }
202
+
203
+ function evalTry(ctx: EvalContext, expr: TryExpression): EvalValue {
204
+ try {
205
+ return evalAny(ctx, expr.test);
206
+ } catch (_err) {
207
+ return evalAny(ctx, expr.alternate);
208
+ }
209
+ }
210
+
211
+ function evalTemplateLiteral(ctx: EvalContext, expr: TemplateLiteral): EvalValue {
212
+ let result = '';
213
+
214
+ if (expr.quasis.length === 2 && expr.quasis[0].value === '' && expr.quasis[1].value === '') {
215
+ return evalAny(ctx, expr.expressions[0]);
216
+ }
217
+
218
+ for (let i = 0; i < expr.expressions.length; ++i) {
219
+ result += expr.quasis[i].value;
220
+ result += valToString(evalAny(ctx, expr.expressions[i]), true);
221
+ }
222
+ result += expr.quasis[expr.quasis.length - 1].value;
223
+
224
+ return {
225
+ type: STRING,
226
+ value: result
227
+ };
228
+ }
229
+
230
+ function evalLogicalExpression(ctx: EvalContext, expr: LogicalExpression): EvalValue {
231
+ const left = valToInternal(evalAny(ctx, expr.left));
232
+ if (left.type !== BOOLEAN) {
233
+ evalError(
234
+ `${valToPreview(left)} ${expr.operator} ...`,
235
+ `'${expr.operator}' must be called with boolean operands.`
236
+ );
237
+ }
238
+
239
+ if (expr.operator === '||' && left.value) {
240
+ return left;
241
+ }
242
+ if (expr.operator === '&&' && !left.value) {
243
+ return {
244
+ type: BOOLEAN,
245
+ value: 0
246
+ };
247
+ }
248
+
249
+ const right = valToInternal(evalAny(ctx, expr.right));
250
+ if (right.type !== BOOLEAN) {
251
+ evalError(
252
+ `${valToPreview(left)} ${expr.operator} ${valToPreview(right)}`,
253
+ `Operator '${expr.operator}' cannot be applied to different types: Boolean and ${typeToString(right.type)}.`
254
+ );
255
+ }
256
+
257
+ return {
258
+ type: BOOLEAN,
259
+ value: right.value
260
+ };
261
+ }
262
+
263
+ function evalBinaryEquality<T extends EvalValue>(operator: EqualityOperator, left: T, right: T): EvalValue {
264
+ let res: boolean;
265
+
266
+ if (left.type === DATETIME && right.type === DATETIME) {
267
+ res = left.value.getTime() === right.value.getTime();
268
+ } else {
269
+ res = left.value === right.value;
270
+ }
271
+
272
+ if (operator === '!=') {
273
+ res = !res;
274
+ }
275
+
276
+ return {
277
+ type: BOOLEAN,
278
+ value: res ? 1 : 0
279
+ };
280
+ }
281
+
282
+ function evalBinaryCompare<T extends EvalValue>(operator: CompareOperator, left: T, right: T): EvalValue {
283
+ if (
284
+ left.type !== NUMBER && left.type !== INTEGER && left.type !== DATETIME ||
285
+ right.type !== NUMBER && right.type !== INTEGER && right.type !== DATETIME
286
+ ) {
287
+ evalError(
288
+ `${valToPreview(left)} ${operator} ${valToPreview(right)}`,
289
+ `Operator '${operator}' cannot be applied to ${typeToString(left.type)} type.`
290
+ );
291
+ }
292
+
293
+ let res: boolean;
294
+ const leftVal = left.type === DATETIME ? left.value.getTime() : left.value;
295
+ const rightVal = right.type === DATETIME ? right.value.getTime() : right.value;
296
+
297
+ if (operator === '>') {
298
+ res = leftVal > rightVal;
299
+ } else if (operator === '>=') {
300
+ res = leftVal >= rightVal;
301
+ } else if (operator === '<') {
302
+ res = leftVal < rightVal;
303
+ } else {
304
+ res = leftVal <= rightVal;
305
+ }
306
+
307
+ return {
308
+ type: BOOLEAN,
309
+ value: res ? 1 : 0
310
+ };
311
+ }
312
+
313
+ function evalBinarySum<T extends EvalValue>(ctx: EvalContext, operator: SumOperator, left: T, right: T): EvalValue {
314
+ if (left.type !== STRING && left.type !== NUMBER && left.type !== INTEGER) {
315
+ evalError(
316
+ `${valToPreview(left)} ${operator} ${valToPreview(right)}`,
317
+ `Operator '${operator}' cannot be applied to ${typeToString(left.type)} type.`
318
+ );
319
+ }
320
+
321
+ if (left.type === STRING) {
322
+ if (operator === '-') {
323
+ evalError(
324
+ `${valToPreview(left)} - ${valToPreview(right)}`,
325
+ `Operator '${operator}' cannot be applied to ${typeToString(left.type)} type.`
326
+ );
327
+ }
328
+ return {
329
+ type: STRING,
330
+ value: left.value + right.value
331
+ };
332
+ }
333
+
334
+ let res: number | bigint = operator === '+' ?
335
+ (left.value as bigint) + (right.value as bigint) :
336
+ (left.value as bigint) - (right.value as bigint);
337
+
338
+ // integer
339
+ if (left.type === INTEGER) {
340
+ try {
341
+ res = roundInteger(ctx, res);
342
+ checkIntegerOverflow(ctx, res);
343
+ } catch (err: any) {
344
+ evalError(
345
+ `${valToPreview(left)} ${operator} ${valToPreview(right)}`,
346
+ err.message
347
+ );
348
+ }
349
+ }
350
+
351
+ return {
352
+ type: left.type,
353
+ value: res as any
354
+ };
355
+ }
356
+
357
+ function evalBinaryFactor<T extends EvalValue>(
358
+ ctx: EvalContext,
359
+ operator: FactorOperator,
360
+ left: T,
361
+ right: T
362
+ ): EvalValue {
363
+ if (left.type !== INTEGER && left.type !== NUMBER) {
364
+ evalError(
365
+ `${valToPreview(left)} ${operator} ${valToPreview(right)}`,
366
+ `Operator '${operator}' cannot be applied to ${typeToString(left.type)} type.`
367
+ );
368
+ }
369
+
370
+ let res: number | bigint;
371
+ if (operator === '*') {
372
+ // bigint | number actually
373
+ res = (left.value as bigint) * (right.value as bigint);
374
+ } else if (operator === '/' || operator === '%') {
375
+ if (Number(right.value) === 0) {
376
+ evalError(
377
+ `${valToPreview(left)} ${operator} ${valToPreview(right)}`,
378
+ 'Division by zero is not supported.'
379
+ );
380
+ }
381
+ if (operator === '/') {
382
+ // bigint | number actually
383
+ res = (left.value as bigint) / (right.value as bigint);
384
+ } else {
385
+ // bigint | number actually
386
+ res = (left.value as bigint) % (right.value as bigint);
387
+ }
388
+ } else {
389
+ throw new Error(`Unsupported operation ${operator}`);
390
+ }
391
+
392
+ if (left.type === INTEGER) {
393
+ try {
394
+ res = roundInteger(ctx, res);
395
+ checkIntegerOverflow(ctx, res);
396
+ } catch (err: any) {
397
+ evalError(
398
+ `${valToPreview(left)} ${operator} ${valToPreview(right)}`,
399
+ err.message
400
+ );
401
+ }
402
+ }
403
+
404
+ return {
405
+ type: left.type,
406
+ value: res as any
407
+ };
408
+ }
409
+
410
+ function evalBinaryExpression(ctx: EvalContext, expr: BinaryExpression): EvalValue {
411
+ const operator = expr.operator;
412
+ let left = evalAny(ctx, expr.left);
413
+ let right = evalAny(ctx, expr.right);
414
+
415
+ if (
416
+ left.type === 'number' && right.type === 'integer' ||
417
+ left.type === 'integer' && right.type === 'number'
418
+ ) {
419
+ if (left.type === 'integer') {
420
+ left = integerToNumber(left);
421
+ } else if (right.type === 'integer') {
422
+ right = integerToNumber(right);
423
+ }
424
+ }
425
+
426
+ if (left.type !== right.type) {
427
+ evalError(
428
+ `${valToPreview(left)} ${expr.operator} ${valToPreview(right)}`,
429
+ `Operator '${operator}' cannot be applied to different types: ${typeToString(left.type)} and ${typeToString(right.type)}.`
430
+ );
431
+ }
432
+
433
+ if (operator === '==' || operator === '!=') {
434
+ return evalBinaryEquality(operator, left, right);
435
+ } else if (operator === '>' || operator === '>=' || operator === '<' || operator === '<=') {
436
+ return evalBinaryCompare(operator, left, right);
437
+ } else if (operator === '+' || operator === '-') {
438
+ return evalBinarySum(ctx, operator, left, right);
439
+ } else if (operator === '/' || operator === '*' || operator === '%') {
440
+ return evalBinaryFactor(ctx, operator, left, right);
441
+ }
442
+
443
+ throw new Error(`Unsupported operation ${operator}`);
444
+ }
445
+
446
+ function argsToStr(args: EvalValue[]): string {
447
+ return args.map(valToPreview).join(', ');
448
+ }
449
+
450
+ function evalCallExpression(ctx: EvalContext, expr: CallExpression): EvalValue {
451
+ const funcName = expr.callee.name;
452
+
453
+ let func: Func | undefined;
454
+
455
+ let args = expr.arguments.map(arg => evalAny(ctx, arg));
456
+ const funcKey = funcName + ':' + args.map(arg => arg.type).join('#');
457
+ let findRes: FuncMatch | undefined;
458
+
459
+ if (ctx.customFunctions) {
460
+ findRes = findBestMatchedFunc(ctx.customFunctions, funcName, args);
461
+ }
462
+
463
+ if (!findRes || !('func' in findRes)) {
464
+ if (funcByArgs.has(funcKey)) {
465
+ findRes = {
466
+ func: funcByArgs.get(funcKey) as Func,
467
+ conversions: 0
468
+ };
469
+ } else {
470
+ const builtInFindRes = findBestMatchedFunc(funcs, funcName, args);
471
+
472
+ // Assign errors only there is no match error in user defined funcs
473
+ if ('func' in builtInFindRes || !findRes || findRes.type === 'missing') {
474
+ findRes = builtInFindRes;
475
+ }
476
+ }
477
+ }
478
+
479
+ if (findRes) {
480
+ if ('expected' in findRes || 'type' in findRes && findRes.type === 'missing') {
481
+ logFunctionMatchError(funcName, args, findRes);
482
+ }
483
+ func = findRes.func;
484
+
485
+ if (findRes.conversions) {
486
+ args = convertArgs(func, args);
487
+ }
488
+ }
489
+
490
+ if (!func) {
491
+ throw new Error('Function not found');
492
+ }
493
+
494
+ try {
495
+ return func.cb(ctx, ...args);
496
+ } catch (err: any) {
497
+ if (err && err instanceof FuncError) {
498
+ throw err;
499
+ }
500
+
501
+ const prefix = `${funcName}(${argsToStr(args)})`;
502
+ evalError(prefix, err.message);
503
+ }
504
+ }
505
+
506
+ export function logFunctionMatchError(
507
+ funcName: string,
508
+ args: EvalValue[],
509
+ findRes: FuncMatchError,
510
+ isOuterFunc = false
511
+ ): never {
512
+ const argsType = args.map(arg => typeToString(arg.type)).join(', ');
513
+ const prefix = `${funcName}(${argsToStr(args)})`;
514
+ const makeError: (msg: string, details: string) => never =
515
+ isOuterFunc ? evalOuterError : evalError;
516
+
517
+ if (findRes.type === 'few' && args.length === 0 && findRes.hasOverloads) {
518
+ makeError(prefix, 'Function requires non empty argument list.');
519
+ } else if (findRes.type === 'many' || findRes.type === 'few' || findRes.type === 'mismatch') {
520
+ if (findRes.hasOverloads) {
521
+ makeError(prefix, `Function has no matching overload for given argument types: ${argsType}.`);
522
+ } else {
523
+ // eslint-disable-next-line no-lonely-if
524
+ if (findRes.type === 'many' || findRes.type === 'few') {
525
+ if (findRes.def.args.some(arg => typeof arg === 'object' && arg.isVararg)) {
526
+ makeError(prefix, `At least ${findRes.def.args.length} argument(s) expected.`);
527
+ } else {
528
+ makeError(prefix, `Exactly ${findRes.def.args.length} argument(s) expected.`);
529
+ }
530
+ } else {
531
+ const expectedArgs = findRes.def.args.map(arg => typeToString(typeof arg === 'string' ? arg : arg.type)).join(', ');
532
+ makeError(prefix, `Invalid argument type: expected ${expectedArgs}, got ${argsType}.`);
533
+ }
534
+ }
535
+ } else {
536
+ makeError(prefix, `Unknown function name: ${funcName}.`);
537
+ }
538
+ }
539
+
540
+ function evalMethodExpression(ctx: EvalContext, expr: MethodExpression): EvalValue {
541
+ const methodName = expr.method.name;
542
+
543
+ let func: Func | undefined;
544
+
545
+ let args = [expr.object, ...expr.arguments].map(arg => evalAny(ctx, arg));
546
+ const methodKey = methodName + ':' + args.map(arg => arg.type).join('#');
547
+
548
+ if (!methodByArgs.has(methodKey)) {
549
+ const findRes = findBestMatchedFunc(methods, methodName, args);
550
+ if ('expected' in findRes || 'type' in findRes && findRes.type === 'missing') {
551
+ const argsType = args.slice(1).map(arg => typeToString(arg.type)).join(', ');
552
+ const prefix = `${methodName}(${argsToStr(args.slice(1))})`;
553
+
554
+ if (findRes.type === 'few' && args.length === 1) {
555
+ evalError(prefix, 'Method requires non empty argument list.');
556
+ } else if (findRes.type === 'many') {
557
+ evalError(prefix, `Method has no matching overload for given argument types: ${argsType}.`);
558
+ } else if (findRes.type === 'few' || findRes.type === 'mismatch') {
559
+ evalError(prefix, `Method has no matching overload for given argument types: ${argsType}.`);
560
+ } else {
561
+ evalError(prefix, `Unknown method name: ${methodName}.`);
562
+ }
563
+ }
564
+ func = findRes.func;
565
+
566
+ if (findRes.conversions) {
567
+ args = convertArgs(func, args);
568
+ }
569
+ } else {
570
+ func = methodByArgs.get(methodKey);
571
+ }
572
+
573
+ if (!func) {
574
+ throw new Error('Method not found');
575
+ }
576
+
577
+ try {
578
+ return func.cb(ctx, ...args);
579
+ } catch (err: any) {
580
+ if (err && err instanceof FuncError) {
581
+ throw err;
582
+ }
583
+
584
+ const prefix = `${methodName}(${argsToStr(args.slice(1))})`;
585
+ evalError(prefix, err.message);
586
+ }
587
+ }
588
+
589
+ function evalVariable(ctx: EvalContext, expr: Variable): EvalValue {
590
+ const varName = expr.id.name;
591
+ const customFuncs = ctx.customFunctions?.get(varName);
592
+ if (customFuncs) {
593
+ return {
594
+ type: 'function',
595
+ value: customFuncs
596
+ };
597
+ }
598
+
599
+ const variable = ctx.variables.get(varName);
600
+
601
+ if (variable) {
602
+ return variableToValue(variable);
603
+ }
604
+
605
+ throw new Error(`Variable '${varName}' is missing.`);
606
+ }
607
+
608
+ const EVAL_MAP = {
609
+ StringLiteral: evalStringLiteral,
610
+ NumberLiteral: evalNumberLiteral,
611
+ IntegerLiteral: evalIntegerLiteral,
612
+ BooleanLiteral: evalBooleanLiteral,
613
+ UnaryExpression: evalUnary,
614
+ ConditionalExpression: evalConditional,
615
+ TryExpression: evalTry,
616
+ TemplateLiteral: evalTemplateLiteral,
617
+ LogicalExpression: evalLogicalExpression,
618
+ BinaryExpression: evalBinaryExpression,
619
+ CallExpression: evalCallExpression,
620
+ MethodExpression: evalMethodExpression,
621
+ Variable: evalVariable
622
+ };
623
+
624
+ export function evalAny(ctx: EvalContext, expr: Node): EvalValue {
625
+ if (expr.type in EVAL_MAP) {
626
+ return EVAL_MAP[expr.type](ctx, expr as any);
627
+ }
628
+ throw new Error('Unsupported expression');
629
+ }
630
+
631
+ export function evalExpression(
632
+ vars: VariablesMap,
633
+ customFunctions: CustomFunctions | undefined,
634
+ store: Store | undefined,
635
+ expr: Node,
636
+ opts?: {
637
+ weekStartDay?: number;
638
+ }
639
+ ): {
640
+ result: EvalResult;
641
+ warnings: WrappedError[];
642
+ usedVars?: Set<VariableInstance<any, VariableType, any>>;
643
+ } {
644
+ try {
645
+ const ctx: EvalContext = {
646
+ variables: vars,
647
+ customFunctions,
648
+ warnings: [],
649
+ store,
650
+ weekStartDay: opts?.weekStartDay || 0
651
+ };
652
+
653
+ const result = evalAny(ctx, expr);
654
+
655
+ return {
656
+ result,
657
+ warnings: ctx.warnings,
658
+ usedVars: ctx.storeUsedVars
659
+ };
660
+ } catch (err: any) {
661
+ return {
662
+ result: {
663
+ type: 'error',
664
+ value: err.message
665
+ },
666
+ warnings: []
667
+ };
668
+ }
669
+ }