3
3
4
4
import {
5
5
isSync ,
6
- // Override is required for the compiler to operate as intended.
7
- Override ,
8
- Sync
6
+ Sync ,
7
+ Compiled
9
8
} from './constants.js'
10
9
import declareSync from './utilities/declareSync.js'
11
10
12
11
// asyncIterators is required for the compiler to operate as intended.
13
12
import asyncIterators from './async_iterators.js'
14
13
14
+ /**
15
+ * Provides a simple way to compile logic into a function that can be run.
16
+ * @param {string[] } strings
17
+ * @param {...any } items
18
+ * @returns {{ [Compiled]: string } }
19
+ */
20
+ function compileTemplate ( strings , ...items ) {
21
+ let res = ''
22
+ for ( let i = 0 ; i < strings . length ; i ++ ) {
23
+ res += strings [ i ]
24
+ if ( i < items . length ) {
25
+ if ( typeof items [ i ] === 'function' ) {
26
+ this . methods . push ( items [ i ] )
27
+ res += 'methods[' + ( this . methods . length - 1 ) + ']'
28
+ } else if ( items [ i ] && typeof items [ i ] [ Compiled ] !== 'undefined' ) res += items [ i ] [ Compiled ]
29
+ else res += buildString ( items [ i ] , this )
30
+ }
31
+ }
32
+ return { [ Compiled ] : res }
33
+ }
34
+
15
35
/**
16
36
* @typedef BuildState
17
37
* Used to keep track of the compilation.
18
38
* @property {* } [engine]
19
39
* @property {Object } [notTraversed]
20
- * @property {Object } [functions]
21
40
* @property {Object } [methods]
22
41
* @property {Object } [state]
23
42
* @property {Array } [processing]
24
43
* @property {* } [async]
25
44
* @property {Array } [above]
26
45
* @property {Boolean } [asyncDetected]
27
46
* @property {* } [values]
28
- * @property {Boolean } [useContext]
29
47
* @property {Boolean } [avoidInlineAsync]
30
48
* @property {string } [extraArguments]
31
- *
49
+ * @property { (strings: string[], ...items: any[]) => { compiled: string } } [compile] A function that can be used to compile a template.
32
50
*/
33
51
34
52
/**
@@ -117,11 +135,7 @@ function isDeepSync (method, engine) {
117
135
function buildString ( method , buildState = { } ) {
118
136
const {
119
137
notTraversed = [ ] ,
120
- functions = { } ,
121
- // methods = [],
122
- // state,
123
138
async,
124
- // above = [],
125
139
processing = [ ] ,
126
140
values = [ ] ,
127
141
engine
@@ -150,7 +164,6 @@ function buildString (method, buildState = {}) {
150
164
}
151
165
152
166
const func = method && Object . keys ( method ) [ 0 ]
153
- buildState . useContext = buildState . useContext || ( engine . methods [ func ] || { } ) . useContext
154
167
155
168
if ( method && typeof method === 'object' ) {
156
169
if ( ! func ) return pushValue ( method )
@@ -159,7 +172,6 @@ function buildString (method, buildState = {}) {
159
172
if ( engine . isData ( method , func ) ) return pushValue ( method , true )
160
173
throw new Error ( `Method '${ func } ' was not found in the Logic Engine.` )
161
174
}
162
- functions [ func ] = functions [ func ] || 2
163
175
164
176
if (
165
177
! buildState . engine . disableInline &&
@@ -175,31 +187,25 @@ function buildString (method, buildState = {}) {
175
187
}
176
188
177
189
if ( engine . methods [ func ] && engine . methods [ func ] . compile ) {
178
- const str = engine . methods [ func ] . compile ( method [ func ] , buildState )
190
+ let str = engine . methods [ func ] . compile ( method [ func ] , buildState )
191
+ if ( str [ Compiled ] ) str = str [ Compiled ]
179
192
180
193
if ( ( str || '' ) . startsWith ( 'await' ) ) buildState . asyncDetected = true
181
194
182
195
if ( str !== false ) return str
183
196
}
184
197
185
198
if ( typeof engine . methods [ func ] === 'function' ) {
186
- functions [ func ] = 1
187
199
asyncDetected = ! isSync ( engine . methods [ func ] )
188
-
189
- return makeAsync ( `gen["${ func } "](` + buildString ( method [ func ] , buildState ) + ')' )
200
+ return makeAsync ( `engine.methods["${ func } "](` + buildString ( method [ func ] , buildState ) + ', context, above, engine)' )
190
201
} else {
191
202
if ( engine . methods [ func ] && ( typeof engine . methods [ func ] . traverse === 'undefined' ? true : engine . methods [ func ] . traverse ) ) {
192
- functions [ func ] = 1
193
203
asyncDetected = Boolean ( async && engine . methods [ func ] && engine . methods [ func ] . asyncMethod )
194
-
195
- return makeAsync ( `gen["${ func } "](` + buildString ( method [ func ] , buildState ) + ')' )
204
+ return makeAsync ( `engine.methods["${ func } "]${ asyncDetected ? '.asyncMethod' : '.method' } (` + buildString ( method [ func ] , buildState ) + ', context, above, engine)' )
196
205
} else {
197
206
asyncDetected = Boolean ( async && engine . methods [ func ] && engine . methods [ func ] . asyncMethod )
198
-
199
- functions [ func ] = 1
200
207
notTraversed . push ( method [ func ] )
201
-
202
- return makeAsync ( `gen["${ func } "](` + `notTraversed[${ notTraversed . length - 1 } ]` + ')' )
208
+ return makeAsync ( `engine.methods["${ func } "]${ asyncDetected ? '.asyncMethod' : '.method' } (` + `notTraversed[${ notTraversed . length - 1 } ]` + ', context, above, engine)' )
203
209
}
204
210
}
205
211
}
@@ -218,14 +224,13 @@ function build (method, buildState = {}) {
218
224
Object . assign (
219
225
{
220
226
notTraversed : [ ] ,
221
- functions : { } ,
222
227
methods : [ ] ,
223
228
state : { } ,
224
229
processing : [ ] ,
225
230
async : buildState . engine . async ,
226
- above : [ ] ,
227
231
asyncDetected : false ,
228
- values : [ ]
232
+ values : [ ] ,
233
+ compile : compileTemplate
229
234
} ,
230
235
buildState
231
236
)
@@ -246,20 +251,19 @@ async function buildAsync (method, buildState = {}) {
246
251
Object . assign (
247
252
{
248
253
notTraversed : [ ] ,
249
- functions : { } ,
250
254
methods : [ ] ,
251
255
state : { } ,
252
256
processing : [ ] ,
253
257
async : buildState . engine . async ,
254
- above : [ ] ,
255
258
asyncDetected : false ,
256
- values : [ ]
259
+ values : [ ] ,
260
+ compile : compileTemplate
257
261
} ,
258
262
buildState
259
263
)
260
264
)
261
265
const str = buildString ( method , buildState )
262
- buildState . processing = await Promise . all ( buildState . processing )
266
+ buildState . processing = await Promise . all ( buildState . processing || [ ] )
263
267
return processBuiltString ( method , str , buildState )
264
268
}
265
269
@@ -271,58 +275,26 @@ async function buildAsync (method, buildState = {}) {
271
275
* @returns
272
276
*/
273
277
function processBuiltString ( method , str , buildState ) {
274
- const gen = { }
275
278
const {
276
- functions,
277
- state,
278
- async,
279
279
engine,
280
- above,
281
280
methods,
282
281
notTraversed,
283
- processing,
282
+ processing = [ ] ,
284
283
values
285
284
} = buildState
286
- processing . forEach ( ( item , x ) => {
287
- str = str . replace ( `__%%%${ x } %%%__` , item )
288
- } )
289
- Object . keys ( functions ) . forEach ( ( key ) => {
290
- if ( functions [ key ] === 2 ) return
291
285
292
- if ( ! engine . methods [ key ] ) throw new Error ( `Method ' ${ key } ' was not found in the Logic Engine.` )
286
+ const above = [ ]
293
287
294
- if ( typeof engine . methods [ key ] === 'function' ) {
295
- const method = engine . methods [ key ]
296
- gen [ key ] = ( input ) => method ( input , state , above , engine )
297
- } else {
298
- if ( async && engine . methods [ key ] . asyncMethod ) {
299
- buildState . asyncDetected = true
300
- const method = engine . methods [ key ] . asyncMethod
301
- gen [ key ] = ( input ) => method ( input , state , above , engine )
302
- } else {
303
- const method = engine . methods [ key ] . method
304
- gen [ key ] = ( input ) => method ( input , state , above , engine )
305
- }
306
- }
288
+ processing . forEach ( ( item , x ) => {
289
+ str = str . replace ( `__%%%${ x } %%%__` , item )
307
290
} )
308
291
309
- if ( ! Object . keys ( functions ) . length ) return method
310
-
311
- let copyStateCall = 'state[Override] = context;'
312
- // console.log(buildState.useContext)
313
-
314
- if ( ! buildState . useContext ) {
315
- copyStateCall = ''
316
- str = str . replace ( / s t a t e \[ O v e r r i d e \] / g, 'context' )
317
- }
318
-
319
- methods . truthy = engine . truthy
320
- const final = `(state, values, methods, gen, notTraversed, Override, asyncIterators) => ${ buildState . asyncDetected ? 'async' : '' } (context ${ buildState . extraArguments ? ',' + buildState . extraArguments : '' } ) => { ${ copyStateCall } const result = ${ str } ; return result }`
292
+ const final = `(values, methods, notTraversed, asyncIterators, engine, above) => ${ buildState . asyncDetected ? 'async' : '' } (context ${ buildState . extraArguments ? ',' + buildState . extraArguments : '' } ) => { const result = ${ str } ; return result }`
321
293
322
294
// console.log(str)
323
295
// console.log(final)
324
296
// eslint-disable-next-line no-eval
325
- return declareSync ( ( typeof globalThis !== 'undefined' ? globalThis : global ) . eval ( final ) ( state , values , methods , gen , notTraversed , Override , asyncIterators ) , ! buildState . asyncDetected )
297
+ return declareSync ( ( typeof globalThis !== 'undefined' ? globalThis : global ) . eval ( final ) ( values , methods , notTraversed , asyncIterators , engine , above ) , ! buildState . asyncDetected )
326
298
}
327
299
328
300
export { build }
0 commit comments