33
44import {
55 isSync ,
6- // Override is required for the compiler to operate as intended.
7- Override ,
8- Sync
6+ Sync ,
7+ Compiled
98} from './constants.js'
109import declareSync from './utilities/declareSync.js'
1110
1211// asyncIterators is required for the compiler to operate as intended.
1312import asyncIterators from './async_iterators.js'
1413
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+
1535/**
1636 * @typedef BuildState
1737 * Used to keep track of the compilation.
1838 * @property {* } [engine]
1939 * @property {Object } [notTraversed]
20- * @property {Object } [functions]
2140 * @property {Object } [methods]
2241 * @property {Object } [state]
2342 * @property {Array } [processing]
2443 * @property {* } [async]
2544 * @property {Array } [above]
2645 * @property {Boolean } [asyncDetected]
2746 * @property {* } [values]
28- * @property {Boolean } [useContext]
2947 * @property {Boolean } [avoidInlineAsync]
3048 * @property {string } [extraArguments]
31- *
49+ * @property { (strings: string[], ...items: any[]) => { compiled: string } } [compile] A function that can be used to compile a template.
3250 */
3351
3452/**
@@ -117,11 +135,7 @@ function isDeepSync (method, engine) {
117135function buildString ( method , buildState = { } ) {
118136 const {
119137 notTraversed = [ ] ,
120- functions = { } ,
121- // methods = [],
122- // state,
123138 async,
124- // above = [],
125139 processing = [ ] ,
126140 values = [ ] ,
127141 engine
@@ -150,7 +164,6 @@ function buildString (method, buildState = {}) {
150164 }
151165
152166 const func = method && Object . keys ( method ) [ 0 ]
153- buildState . useContext = buildState . useContext || ( engine . methods [ func ] || { } ) . useContext
154167
155168 if ( method && typeof method === 'object' ) {
156169 if ( ! func ) return pushValue ( method )
@@ -159,7 +172,6 @@ function buildString (method, buildState = {}) {
159172 if ( engine . isData ( method , func ) ) return pushValue ( method , true )
160173 throw new Error ( `Method '${ func } ' was not found in the Logic Engine.` )
161174 }
162- functions [ func ] = functions [ func ] || 2
163175
164176 if (
165177 ! buildState . engine . disableInline &&
@@ -175,31 +187,25 @@ function buildString (method, buildState = {}) {
175187 }
176188
177189 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 ]
179192
180193 if ( ( str || '' ) . startsWith ( 'await' ) ) buildState . asyncDetected = true
181194
182195 if ( str !== false ) return str
183196 }
184197
185198 if ( typeof engine . methods [ func ] === 'function' ) {
186- functions [ func ] = 1
187199 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)' )
190201 } else {
191202 if ( engine . methods [ func ] && ( typeof engine . methods [ func ] . traverse === 'undefined' ? true : engine . methods [ func ] . traverse ) ) {
192- functions [ func ] = 1
193203 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)' )
196205 } else {
197206 asyncDetected = Boolean ( async && engine . methods [ func ] && engine . methods [ func ] . asyncMethod )
198-
199- functions [ func ] = 1
200207 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)' )
203209 }
204210 }
205211 }
@@ -218,14 +224,13 @@ function build (method, buildState = {}) {
218224 Object . assign (
219225 {
220226 notTraversed : [ ] ,
221- functions : { } ,
222227 methods : [ ] ,
223228 state : { } ,
224229 processing : [ ] ,
225230 async : buildState . engine . async ,
226- above : [ ] ,
227231 asyncDetected : false ,
228- values : [ ]
232+ values : [ ] ,
233+ compile : compileTemplate
229234 } ,
230235 buildState
231236 )
@@ -246,20 +251,19 @@ async function buildAsync (method, buildState = {}) {
246251 Object . assign (
247252 {
248253 notTraversed : [ ] ,
249- functions : { } ,
250254 methods : [ ] ,
251255 state : { } ,
252256 processing : [ ] ,
253257 async : buildState . engine . async ,
254- above : [ ] ,
255258 asyncDetected : false ,
256- values : [ ]
259+ values : [ ] ,
260+ compile : compileTemplate
257261 } ,
258262 buildState
259263 )
260264 )
261265 const str = buildString ( method , buildState )
262- buildState . processing = await Promise . all ( buildState . processing )
266+ buildState . processing = await Promise . all ( buildState . processing || [ ] )
263267 return processBuiltString ( method , str , buildState )
264268}
265269
@@ -271,58 +275,26 @@ async function buildAsync (method, buildState = {}) {
271275 * @returns
272276 */
273277function processBuiltString ( method , str , buildState ) {
274- const gen = { }
275278 const {
276- functions,
277- state,
278- async,
279279 engine,
280- above,
281280 methods,
282281 notTraversed,
283- processing,
282+ processing = [ ] ,
284283 values
285284 } = 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
291285
292- if ( ! engine . methods [ key ] ) throw new Error ( `Method ' ${ key } ' was not found in the Logic Engine.` )
286+ const above = [ ]
293287
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 )
307290 } )
308291
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 }`
321293
322294 // console.log(str)
323295 // console.log(final)
324296 // 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 )
326298}
327299
328300export { build }
0 commit comments