Skip to content

Commit 9529c12

Browse files
committed
Optimize the comparison operators for the interpreted optimizer
1 parent a91fab1 commit 9529c12

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

defaultMethods.js

+1
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,7 @@ function createComparator (name, func) {
853853
for (let i = 2; i < data.length; i++) res = buildState.compile`(${res} && prev ${opStr} ${data[i]})`
854854
return res
855855
},
856+
[OriginalImpl]: true,
856857
[Sync]: (data, buildState) => isSyncDeep(data, buildState.engine, buildState),
857858
deterministic: (data, buildState) => isDeterministic(data, buildState.engine, buildState),
858859
lazy: true

optimizer.js

+45
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,19 @@ function getMethod (logic, engine, methodName, above) {
7777
}
7878
}
7979

80+
const comparisons = {
81+
'<': (a, b) => a < b,
82+
'<=': (a, b) => a <= b,
83+
'>': (a, b) => a > b,
84+
'>=': (a, b) => a >= b,
85+
// eslint-disable-next-line eqeqeq
86+
'==': (a, b) => a == b,
87+
'===': (a, b) => a === b,
88+
// eslint-disable-next-line eqeqeq
89+
'!=': (a, b) => a != b,
90+
'!==': (a, b) => a !== b
91+
}
92+
8093
/**
8194
* Macro-type replacements to lift inefficient logic into more efficient forms.
8295
*/
@@ -101,6 +114,38 @@ function checkIdioms (logic, engine, above) {
101114
}
102115
}
103116

117+
// Hyper-Optimizations for Comparison Operators.
118+
for (const comparison in comparisons) {
119+
if (logic[comparison] && Array.isArray(logic[comparison]) && engine.methods[comparison][OriginalImpl]) {
120+
const comparisonFunc = comparisons[comparison]
121+
if (logic[comparison].length === 2) {
122+
const [a, b] = logic[comparison]
123+
const A = optimize(a, engine, above)
124+
const B = optimize(b, engine, above)
125+
if (typeof A === 'function' && typeof B === 'function') return (data, abv) => comparisonFunc(A(data, abv), B(data, abv))
126+
if (typeof A === 'function') return (data, abv) => comparisonFunc(A(data, abv), B)
127+
if (typeof B === 'function') return (data, abv) => comparisonFunc(A, B(data, abv))
128+
return () => comparisonFunc(A, B)
129+
}
130+
131+
if (logic[comparison].length === 3) {
132+
const [a, b, c] = logic[comparison]
133+
const A = optimize(a, engine, above)
134+
const B = optimize(b, engine, above)
135+
const C = optimize(c, engine, above)
136+
let prev
137+
if (typeof A === 'function' && typeof B === 'function' && typeof C === 'function') return (data, abv) => comparisonFunc(A(data, abv), (prev = B(data, abv))) && comparisonFunc(prev, C(data, abv))
138+
if (typeof A === 'function' && typeof B === 'function') return (data, abv) => comparisonFunc(A(data, abv), (prev = B(data, abv))) && comparisonFunc(prev, C)
139+
if (typeof A === 'function' && typeof C === 'function') return (data, abv) => comparisonFunc(A(data, abv), B) && comparisonFunc(B, C(data, abv))
140+
if (typeof B === 'function' && typeof C === 'function') return (data, abv) => comparisonFunc(A, (prev = B(data, abv))) && comparisonFunc(prev, C(data, abv))
141+
if (typeof A === 'function') return (data, abv) => comparisonFunc(A(data, abv), B) && comparisonFunc(B, C)
142+
if (typeof B === 'function') return (data, abv) => comparisonFunc(A, (prev = B(data, abv))) && comparisonFunc(prev, C)
143+
if (typeof C === 'function') return (data, abv) => comparisonFunc(A, B) && comparisonFunc(B, C(data, abv))
144+
return () => comparisonFunc(A, B) && comparisonFunc(B, C)
145+
}
146+
}
147+
}
148+
104149
if (logic.reduce && Array.isArray(logic.reduce)) {
105150
let [root, mapper, defaultValue] = logic.reduce
106151
if (mapper['+'] && mapper['+'].length === 2 && (mapper['+'][0] || 0).var && (mapper['+'][1] || 0).var) {

0 commit comments

Comments
 (0)