1
1
// This is the synchronous version of the optimizer; which the Async one should be based on.
2
2
import { isDeterministic } from './compiler.js'
3
3
import { map } from './async_iterators.js'
4
+ import { isSync , Sync } from './constants.js'
5
+ import declareSync from './utilities/declareSync.js'
4
6
5
7
/**
6
8
* Turns an expression like { '+': [1, 2] } into a function that can be called with data.
@@ -14,6 +16,7 @@ function getMethod (logic, engine, methodName, above) {
14
16
const method = engine . methods [ methodName ]
15
17
const called = method . asyncMethod ? method . asyncMethod : method . method ? method . method : method
16
18
19
+ // Todo: Like "deterministic", we should add "sync" to the method object to determine if the structure can be run synchronously.
17
20
if ( method . traverse === false ) {
18
21
const args = logic [ methodName ]
19
22
return ( data , abv ) => called ( args , data , abv || above , engine )
@@ -23,12 +26,27 @@ function getMethod (logic, engine, methodName, above) {
23
26
24
27
if ( Array . isArray ( args ) ) {
25
28
const optimizedArgs = args . map ( l => optimize ( l , engine , above ) )
29
+
30
+ if ( isSync ( optimizedArgs ) && ( method . method || method [ Sync ] ) ) {
31
+ const called = method . method ? method . method : method
32
+ return declareSync ( ( data , abv ) => {
33
+ const evaluatedArgs = optimizedArgs . map ( l => typeof l === 'function' ? l ( data , abv ) : l )
34
+ return called ( evaluatedArgs , data , abv || above , engine )
35
+ } , true )
36
+ }
37
+
26
38
return async ( data , abv ) => {
27
39
const evaluatedArgs = await map ( optimizedArgs , l => typeof l === 'function' ? l ( data , abv ) : l )
28
40
return called ( evaluatedArgs , data , abv || above , engine )
29
41
}
30
42
} else {
31
43
const optimizedArgs = optimize ( args , engine , above )
44
+
45
+ if ( isSync ( optimizedArgs ) && ( method . method || method [ Sync ] ) ) {
46
+ const called = method . method ? method . method : method
47
+ return declareSync ( ( data , abv ) => called ( typeof optimizedArgs === 'function' ? optimizedArgs ( data , abv ) : optimizedArgs , data , abv || above , engine ) , true )
48
+ }
49
+
32
50
return async ( data , abv ) => {
33
51
return called ( typeof optimizedArgs === 'function' ? await optimizedArgs ( data , abv ) : optimizedArgs , data , abv || above , engine )
34
52
}
@@ -45,6 +63,7 @@ function getMethod (logic, engine, methodName, above) {
45
63
export function optimize ( logic , engine , above = [ ] ) {
46
64
if ( Array . isArray ( logic ) ) {
47
65
const arr = logic . map ( l => optimize ( l , engine , above ) )
66
+ if ( isSync ( arr ) ) return declareSync ( ( data , abv ) => arr . map ( l => typeof l === 'function' ? l ( data , abv ) : l ) , true )
48
67
return async ( data , abv ) => map ( arr , l => typeof l === 'function' ? l ( data , abv ) : l )
49
68
} ;
50
69
@@ -63,6 +82,14 @@ export function optimize (logic, engine, above = []) {
63
82
const result = getMethod ( logic , engine , methodName , above )
64
83
if ( deterministic ) {
65
84
let computed
85
+
86
+ if ( isSync ( result ) ) {
87
+ return declareSync ( ( ) => {
88
+ if ( ! computed ) computed = result ( )
89
+ return computed
90
+ } , true )
91
+ }
92
+
66
93
// For async, it's a little less straightforward since it could be a promise,
67
94
// so we'll make it a closure.
68
95
return async ( ) => {
0 commit comments