Skip to content

Commit 452aa1a

Browse files
Merge pull request #27 from json-logic/proposals/arithmetic
Add Arithmetic Proposal
2 parents 38cffb3 + 5a69641 commit 452aa1a

File tree

6 files changed

+891
-0
lines changed

6 files changed

+891
-0
lines changed

ACCEPTED_PROPOSALS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ Define JSON Logic on the JSON Data Model | - Defines JSON Logic on the data mode
77
`val` and context replacements | - Deprecates `var`, `missing` and `missing_some` to the legacy extension <br/> <br/> - Defines `val`, `exists` and `??` | https://github.com/orgs/json-logic/discussions/18 | [`val.json`](tests/val.json), [`exists.json`](tests/exists.json), [`coalesce.json`](tests/coalesce.json) | 1
88
Amend Test Specification / Error Handling | - Defines that errors like `NaN` should bubble up the AST and halt execution, unless handled. <br/><br/> - Extends the test specification to be able to test for errors. <br/><br/> - Introduces two new operators, `throw` and `try` <br/><br/> - Defines that division by zero results in a `NaN` error. | https://github.com/orgs/json-logic/discussions/20 | [`throw.json`](tests/throw.json), [`try.json`](tests/try.json) | 1
99
Linear Time Ruling | - Establishes a guideline for selecting enabled by default JSON Logic operators. <br/><br/> - All JSON Logic Core operators must be definable to run in a worst case Linear Time; ≤ Θ(n).<br/><br/> - Community Extensions may be recognized with operators that exceed this, but they must not be recommended for enablement by default. <br /><br/> - This is not an implementation mandate, rather a guideline for TC and Organization members to select JSON Logic operators in a way that mitigates denial of service attacks when rules are executed from an untrusted source. | https://github.com/orgs/json-logic/discussions/24 | N/A | 3
10+
Arithmetic Operators | - The first proposal of several to evaluate existing operators and define any ambiguous behavior / improve consistency of the operators. <br/><br/> - Defined various `NaN` error states (invalid string coercions, divisions by zero) <br/><br/> - Defined Zero Argument and Single Argument and Variadic behavior for each operator (`+`, `-`, `*`, `/`, `%`) <br/><br/> - The variadic operators are treated as `foldLeft` <br/> <br/> - Defined numeric coercion rules. | https://github.com/orgs/json-logic/discussions/21 | [plus.json](tests/plus.json), [minus.json](tests/minus.json), [multiply.json](tests/multiply.json), [divide.json](tests/divide.json), [modulo.json](tests/modulo.json) | 1

tests/divide.json

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
[
2+
"# Collection of Divide Operator Tests",
3+
{
4+
"description": "Divide",
5+
"rule": { "/": [4, 2] },
6+
"result": 2,
7+
"data": null
8+
},
9+
{
10+
"description": "Divide to Decimal",
11+
"rule": { "/": [2, 4] },
12+
"result": 0.5,
13+
"data": null,
14+
"decimal": true
15+
},
16+
{
17+
"description": "Divide with Multiple Operands",
18+
"rule": { "/": [8, 2, 2] },
19+
"result": 2,
20+
"data": null
21+
},
22+
{
23+
"description": "Divide with Multiple Operands (2)",
24+
"rule": { "/": [2, 2, 1] },
25+
"result": 1,
26+
"data": null
27+
},
28+
{
29+
"description": "Divide with Negative Numbers",
30+
"rule": { "/": [-1, 2] },
31+
"result": -0.5,
32+
"data": null,
33+
"decimal": true
34+
},
35+
{
36+
"description": "Divide with Strings",
37+
"rule": { "/": ["8", "2", "2"] },
38+
"result": 2,
39+
"data": null
40+
},
41+
{
42+
"description": "Divide with Booleans",
43+
"rule": { "/": [false, true] },
44+
"result": 0,
45+
"data": null
46+
},
47+
{
48+
"description": "Divide with Multiple Value Types",
49+
"rule": { "/": ["8", true, 2] },
50+
"result": 4,
51+
"data": null
52+
},
53+
{
54+
"description": "Divide with Multiple Value Types (2)",
55+
"rule": { "/": ["1", 1] },
56+
"result": 1,
57+
"data": null
58+
},
59+
{
60+
"description": "Divide with Single Operand (Number)",
61+
"rule": { "/": [1] },
62+
"result": 1,
63+
"data": null
64+
},
65+
{
66+
"description": "Divide with zero operands is an error",
67+
"rule": { "/": [] },
68+
"error": { "type": "Invalid Arguments" },
69+
"data": null
70+
},
71+
{
72+
"description": "Divide with Single Operand, Direct (Number)",
73+
"rule": { "/": 1 },
74+
"result": 1,
75+
"data": null
76+
},
77+
{
78+
"description": "Divide with Single Operand, Direct (0)",
79+
"rule": { "/": 0 },
80+
"error": { "type": "NaN" },
81+
"data": null
82+
},
83+
{
84+
"description": "Divide Operator with Single Operand (Number)",
85+
"rule": { "/": [1] },
86+
"result": 1,
87+
"data": null
88+
},
89+
{
90+
"description": "Divide Operator with Single Operand (Negative Number)",
91+
"rule": { "/": [-1] },
92+
"result": -1,
93+
"data": null
94+
},
95+
{
96+
"description": "Divide Operator with Single Operand, Direct (Number)",
97+
"rule": { "/": 1 },
98+
"result": 1,
99+
"data": null
100+
},
101+
{
102+
"description": "Divide Operator with Single Operand, Direct (2)",
103+
"rule": { "/": 2 },
104+
"result": 0.5,
105+
"decimal": true,
106+
"data": null
107+
},
108+
{
109+
"description": "Divide Operator with Single Operand, Direct (0)",
110+
"rule": { "/": 0 },
111+
"error": { "type": "NaN" },
112+
"data": null
113+
},
114+
{
115+
"description": "Divide Operator with Single Operand (String)",
116+
"rule": { "/": ["1"] },
117+
"result": 1,
118+
"data": null
119+
},
120+
{
121+
"description": "Divide Operator with Single Operand, Direct (Negative Number String)",
122+
"rule": { "/": "-1" },
123+
"result": -1,
124+
"data": null
125+
},
126+
127+
{
128+
"description": "Divide Operator with Single Operand, Direct (String 0)",
129+
"rule": { "/": "0" },
130+
"error": { "type": "NaN" },
131+
"data": null
132+
},
133+
{
134+
"description": "Divide Operator with Single Operand, Direct (true)",
135+
"rule": { "/": true },
136+
"result": 1,
137+
"data": null
138+
},
139+
{
140+
"description": "Divide Operator with Single Operand, Direct (false)",
141+
"rule": { "/": false },
142+
"error": { "type": "NaN" },
143+
"data": null
144+
},
145+
{
146+
"description": "Divide Operator with Single Operand, Direct (Empty String)",
147+
"rule": { "/": "" },
148+
"error": { "type": "NaN" },
149+
"data": null
150+
},
151+
{
152+
"description": "Divide Operator with a Single Operand, Direct (null)",
153+
"rule": { "/": null },
154+
"error": { "type": "NaN" },
155+
"data": null
156+
},
157+
{
158+
"description": "Divide with val",
159+
"rule": { "/": [{ "val": "x" }, { "val": "y" }] },
160+
"data": { "x": 8, "y": 2 },
161+
"result": 4
162+
},
163+
{
164+
"description": "Divide by Zero",
165+
"rule": { "/": [0, 0] },
166+
"error": { "type": "NaN" },
167+
"data": null
168+
},
169+
{
170+
"description": "Divide with String produces NaN",
171+
"rule": { "/": [1, "a"] },
172+
"error": { "type": "NaN" },
173+
"data": null
174+
},
175+
{
176+
"description": "Divide with Array produces NaN",
177+
"rule": { "/": [1, [1]] },
178+
"error": { "type": "NaN" },
179+
"data": null
180+
},
181+
{
182+
"description": "Any division by zero should return NaN",
183+
"rule": { "/": [1, 0] },
184+
"error": { "type": "NaN" },
185+
"data": null
186+
},
187+
{
188+
"description": "Any division by zero should return NaN (2)",
189+
"rule": { "/": [8, 2, 0] },
190+
"error": { "type": "NaN" },
191+
"data": null
192+
}
193+
]

tests/minus.json

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
[
2+
"# Collection of Minus Operator Tests",
3+
{
4+
"description": "Subtraction",
5+
"rule": { "-": [1, 2] },
6+
"result": -1,
7+
"data": null
8+
},
9+
{
10+
"description": "Subtraction (2)",
11+
"rule": { "-": [5, 12] },
12+
"result": -7,
13+
"data": null
14+
},
15+
{
16+
"description": "Subtraction with Multiple Operands",
17+
"rule": { "-": [1, 2, 3, 4] },
18+
"result": -8,
19+
"data": null
20+
},
21+
{
22+
"description": "Subtraction with Negative Numbers",
23+
"rule": { "-": [-1, 0, 5] },
24+
"result": -6,
25+
"data": null
26+
},
27+
{
28+
"description": "Subtraction with Strings",
29+
"rule": { "-": ["1", "2", "3"] },
30+
"result": -4,
31+
"data": null
32+
},
33+
{
34+
"description": "Subtraction with Booleans",
35+
"rule": { "-": [true, false, true] },
36+
"result": 0,
37+
"data": null
38+
},
39+
{
40+
"description": "Subtraction with Multiple Value Types",
41+
"rule": { "-": [1, "2", 3, "4", "", true, false, null] },
42+
"result": -9,
43+
"data": null
44+
},
45+
{
46+
"description": "Minus Operator with Single Operand (Number)",
47+
"rule": { "-": [1] },
48+
"result": -1,
49+
"data": null
50+
},
51+
{
52+
"description": "Minus Operator with Single Operand (Negative Number)",
53+
"rule": { "-": [-1] },
54+
"result": 1,
55+
"data": null
56+
},
57+
{
58+
"description": "Minus with zero operands is an error",
59+
"rule": { "-": [] },
60+
"error": { "type": "Invalid Arguments" },
61+
"data": null
62+
},
63+
{
64+
"description": "Minus Operator with Single Operand, Direct (Number)",
65+
"rule": { "-": 1 },
66+
"result": -1,
67+
"data": null
68+
},
69+
{
70+
"description": "Minus Operator with Single Operand, Direct (0)",
71+
"rule": { "-": 0 },
72+
"result": 0,
73+
"data": null
74+
},
75+
{
76+
"description": "Minus Operator with Single Operand (String)",
77+
"rule": { "-": ["1"] },
78+
"result": -1,
79+
"data": null
80+
},
81+
{
82+
"description": "Minus Operator with Single Operand, Direct (Negative Number String)",
83+
"rule": { "-": "-1" },
84+
"result": 1,
85+
"data": null
86+
},
87+
88+
{
89+
"description": "Minus Operator with Single Operand, Direct (String 0)",
90+
"rule": { "-": "0" },
91+
"result": 0,
92+
"data": null
93+
},
94+
{
95+
"description": "Minus Operator with Single Operand, Direct (true)",
96+
"rule": { "-": true },
97+
"result": -1,
98+
"data": null
99+
},
100+
{
101+
"description": "Minus Operator with Single Operand, Direct (false)",
102+
"rule": { "-": false },
103+
"result": 0,
104+
"data": null
105+
},
106+
{
107+
"description": "Minus Operator with Single Operand, Direct (Empty String)",
108+
"rule": { "-": "" },
109+
"result": 0,
110+
"data": null
111+
},
112+
{
113+
"description": "Minus Operator with a Single Operand, Direct (null)",
114+
"rule": { "-": null },
115+
"result": 0,
116+
"data": null
117+
},
118+
{
119+
"description": "Subtraction with val",
120+
"rule": { "-": [{ "val": "x" }, { "val": "y" }] },
121+
"data": { "x": 1, "y": 2 },
122+
"result": -1
123+
},
124+
{
125+
"description": "Subtraction with string produces NaN",
126+
"rule": { "-": ["Hey", 1] },
127+
"error": { "type": "NaN" },
128+
"data": null
129+
},
130+
{
131+
"description": "Subtraction with Array produces NaN",
132+
"rule": { "-": [[1], 1] },
133+
"error": { "type": "NaN" },
134+
"data": null
135+
}
136+
]

0 commit comments

Comments
 (0)