5
5
* GPU Accelerated JavaScript
6
6
*
7
7
* @version 2.0.0
8
- * @date Sun Feb 10 2019 12:13:28 GMT-0500 (Eastern Standard Time)
8
+ * @date Sun Feb 10 2019 22:55:24 GMT-0500 (Eastern Standard Time)
9
9
*
10
10
* @license MIT
11
11
* The MIT License
@@ -220,87 +220,68 @@ class CPUFunctionNode extends FunctionNode {
220
220
221
221
astForStatement ( forNode , retArr ) {
222
222
if ( forNode . type !== 'ForStatement' ) {
223
- throw this . astErrorOutput (
224
- 'Invalid for statement' ,
225
- forNode
226
- ) ;
223
+ throw this . astErrorOutput ( 'Invalid for statement' , forNode ) ;
227
224
}
228
225
229
- if ( forNode . test && forNode . test . type === 'BinaryExpression' ) {
230
- if ( ( forNode . test . right . type === 'Identifier' ) &&
231
- forNode . test . operator === '<' &&
232
- this . isIdentifierConstant ( forNode . test . right . name ) === false ) {
226
+ const initArr = [ ] ;
227
+ const testArr = [ ] ;
228
+ const updateArr = [ ] ;
229
+ const bodyArr = [ ] ;
230
+ let isSafe = null ;
233
231
234
- if ( ! this . loopMaxIterations ) {
235
- console . warn ( 'Warning: loopMaxIterations is not set! Using default of 1000 which may result in unintended behavior.' ) ;
236
- console . warn ( 'Set loopMaxIterations or use a for loop of fixed length to silence this message.' ) ;
232
+ if ( forNode . init ) {
233
+ this . pushState ( 'in-for-loop-init' ) ;
234
+ this . astGeneric ( forNode . init , initArr ) ;
235
+ for ( let i = 0 ; i < initArr . length ; i ++ ) {
236
+ if ( initArr [ i ] . includes && initArr [ i ] . includes ( ',' ) ) {
237
+ isSafe = false ;
237
238
}
239
+ }
240
+ this . popState ( 'in-for-loop-init' ) ;
241
+ } else {
242
+ isSafe = false ;
243
+ }
238
244
239
- retArr . push ( 'for (' ) ;
240
- this . astGeneric ( forNode . init , retArr ) ;
241
- if ( retArr [ retArr . length - 1 ] !== ';' ) {
242
- retArr . push ( ';' ) ;
243
- }
244
- this . astGeneric ( forNode . test . left , retArr ) ;
245
- retArr . push ( forNode . test . operator ) ;
246
- retArr . push ( 'LOOP_MAX' ) ;
247
- retArr . push ( ';' ) ;
248
- this . astGeneric ( forNode . update , retArr ) ;
249
- retArr . push ( ')' ) ;
245
+ if ( forNode . test ) {
246
+ this . astGeneric ( forNode . test , testArr ) ;
247
+ } else {
248
+ isSafe = false ;
249
+ }
250
250
251
- retArr . push ( '{\n' ) ;
252
- retArr . push ( 'if (' ) ;
253
- this . astGeneric ( forNode . test . left , retArr ) ;
254
- retArr . push ( forNode . test . operator ) ;
255
- this . astGeneric ( forNode . test . right , retArr ) ;
256
- retArr . push ( ') {\n' ) ;
257
- if ( forNode . body . type === 'BlockStatement' ) {
258
- for ( let i = 0 ; i < forNode . body . body . length ; i ++ ) {
259
- this . astGeneric ( forNode . body . body [ i ] , retArr ) ;
260
- }
261
- } else {
262
- this . astGeneric ( forNode . body , retArr ) ;
263
- }
264
- retArr . push ( '} else {\n' ) ;
265
- retArr . push ( 'break;\n' ) ;
266
- retArr . push ( '}\n' ) ;
267
- retArr . push ( '}\n' ) ;
251
+ if ( forNode . update ) {
252
+ this . astGeneric ( forNode . update , updateArr ) ;
253
+ } else {
254
+ isSafe = false ;
255
+ }
268
256
269
- return retArr ;
270
- } else if ( forNode . init && forNode . init . declarations ) {
271
- const declarations = forNode . init . declarations ;
272
- if ( ! Array . isArray ( declarations ) || declarations . length < 1 ) {
273
- throw new Error ( 'Error: Incompatible for loop declaration' ) ;
274
- }
257
+ if ( forNode . body ) {
258
+ this . pushState ( 'loop-body' ) ;
259
+ this . astGeneric ( forNode . body , bodyArr ) ;
260
+ this . popState ( 'loop-body' ) ;
261
+ }
275
262
276
- if ( declarations . length > 1 ) {
277
- retArr . push ( 'for (' ) ;
278
- retArr . push ( `${ forNode . init . kind } ` ) ;
279
- for ( let i = 0 ; i < declarations . length ; i ++ ) {
280
- if ( i > 0 ) {
281
- retArr . push ( ',' ) ;
282
- }
283
- this . astGeneric ( declarations [ i ] , retArr ) ;
284
- }
285
- retArr . push ( ';' ) ;
286
- } else {
287
- retArr . push ( 'for (' ) ;
288
- this . astGeneric ( forNode . init , retArr ) ;
289
- }
263
+ if ( isSafe === null ) {
264
+ isSafe = this . isSafe ( forNode . init ) && this . isSafe ( forNode . test ) ;
265
+ }
290
266
291
- this . astGeneric ( forNode . test , retArr ) ;
292
- retArr . push ( ';' ) ;
293
- this . astGeneric ( forNode . update , retArr ) ;
294
- retArr . push ( ')' ) ;
295
- this . astGeneric ( forNode . body , retArr ) ;
296
- return retArr ;
267
+ if ( isSafe ) {
268
+ retArr . push ( `for (${ initArr . join ( '' ) } ;${ testArr . join ( '' ) } ;${ updateArr . join ( '' ) } ){\n` ) ;
269
+ retArr . push ( bodyArr . join ( '' ) ) ;
270
+ retArr . push ( '}\n' ) ;
271
+ } else {
272
+ const iVariableName = this . getInternalVariableName ( 'safeI' ) ;
273
+ if ( initArr . length > 0 ) {
274
+ retArr . push ( initArr . join ( '' ) , ';\n' ) ;
275
+ }
276
+ retArr . push ( `for (int ${ iVariableName } =0;${ iVariableName } <LOOP_MAX;${ iVariableName } ++){\n` ) ;
277
+ if ( testArr . length > 0 ) {
278
+ retArr . push ( `if (!${ testArr . join ( '' ) } ) break;\n` ) ;
297
279
}
280
+ retArr . push ( bodyArr . join ( '' ) ) ;
281
+ retArr . push ( `\n${ updateArr . join ( '' ) } ;` ) ;
282
+ retArr . push ( '}\n' ) ;
298
283
}
299
-
300
- throw this . astErrorOutput (
301
- 'Invalid for statement' ,
302
- forNode
303
- ) ;
284
+ return retArr ;
304
285
}
305
286
306
287
astWhileStatement ( whileNode , retArr ) {
@@ -353,11 +334,15 @@ class CPUFunctionNode extends FunctionNode {
353
334
}
354
335
355
336
astBlockStatement ( bNode , retArr ) {
356
- retArr . push ( '{\n' ) ;
337
+ if ( ! this . isState ( 'loop-body' ) ) {
338
+ retArr . push ( '{\n' ) ;
339
+ }
357
340
for ( let i = 0 ; i < bNode . body . length ; i ++ ) {
358
341
this . astGeneric ( bNode . body [ i ] , retArr ) ;
359
342
}
360
- retArr . push ( '}\n' ) ;
343
+ if ( ! this . isState ( 'loop-body' ) ) {
344
+ retArr . push ( '}\n' ) ;
345
+ }
361
346
return retArr ;
362
347
}
363
348
@@ -382,7 +367,9 @@ class CPUFunctionNode extends FunctionNode {
382
367
}
383
368
this . astGeneric ( varDecNode . declarations [ i ] , retArr ) ;
384
369
}
385
- retArr . push ( ';' ) ;
370
+ if ( ! this . isState ( 'in-for-loop-init' ) ) {
371
+ retArr . push ( ';' ) ;
372
+ }
386
373
return retArr ;
387
374
}
388
375
@@ -819,16 +806,16 @@ class CPUKernel extends Kernel {
819
806
const kernelString = this . getKernelString ( ) ;
820
807
this . kernelString = kernelString ;
821
808
809
+ if ( this . debug ) {
810
+ console . log ( 'Function output:' ) ;
811
+ console . log ( kernelString ) ;
812
+ }
813
+
822
814
try {
823
815
this . run = new Function ( [ ] , kernelString ) . bind ( this ) ( ) ;
824
816
} catch ( e ) {
825
817
console . error ( 'An error occurred compiling the javascript: ' , e ) ;
826
818
}
827
-
828
- if ( this . debug ) {
829
- console . log ( 'Function output:' ) ;
830
- console . log ( kernelString ) ;
831
- }
832
819
}
833
820
834
821
color ( r , g , b , a ) {
@@ -1601,8 +1588,8 @@ class FunctionNode {
1601
1588
if ( ast . operator === '%' ) {
1602
1589
return 'Number' ;
1603
1590
} else if ( ast . operator === '>' || ast . operator === '<' ) {
1604
- return 'Boolean' ;
1605
- }
1591
+ return 'Boolean' ;
1592
+ }
1606
1593
const type = this . getType ( ast . left ) ;
1607
1594
return typeLookupMap [ type ] || type ;
1608
1595
case 'UpdateExpression' :
@@ -2331,10 +2318,10 @@ class FunctionNode {
2331
2318
if ( ! this . _internalVariableNames . hasOwnProperty ( name ) ) {
2332
2319
this . _internalVariableNames [ name ] = 0 ;
2333
2320
}
2334
- this . _internalVariableNames [ name ] ++ ;
2321
+ this . _internalVariableNames [ name ] ++ ;
2335
2322
if ( this . _internalVariableNames [ name ] === 1 ) {
2336
- return name ;
2337
- }
2323
+ return name ;
2324
+ }
2338
2325
return name + this . _internalVariableNames [ name ] ;
2339
2326
}
2340
2327
}
@@ -2355,7 +2342,6 @@ const typeLookupMap = {
2355
2342
module . exports = {
2356
2343
FunctionNode
2357
2344
} ;
2358
-
2359
2345
} , { "../utils" :28 , "acorn" :1 } ] , 9 :[ function ( require , module , exports ) {
2360
2346
const {
2361
2347
Kernel
@@ -3335,7 +3321,7 @@ class WebGLFunctionNode extends FunctionNode {
3335
3321
this . pushState ( 'in-for-loop-init' ) ;
3336
3322
this . astGeneric ( forNode . init , initArr ) ;
3337
3323
for ( let i = 0 ; i < initArr . length ; i ++ ) {
3338
- if ( initArr [ i ] . includes ( ',' ) ) {
3324
+ if ( initArr [ i ] . includes && initArr [ i ] . includes ( ',' ) ) {
3339
3325
isSafe = false ;
3340
3326
}
3341
3327
}
@@ -3393,7 +3379,8 @@ class WebGLFunctionNode extends FunctionNode {
3393
3379
throw this . astErrorOutput ( 'Invalid while statement' , whileNode ) ;
3394
3380
}
3395
3381
3396
- retArr . push ( 'for (int safeI=0;safeI<LOOP_MAX;safeI++){\n' ) ;
3382
+ const iVariableName = this . getInternalVariableName ( 'safeI' ) ;
3383
+ retArr . push ( `for (int ${ iVariableName } =0;${ iVariableName } <LOOP_MAX;${ iVariableName } ++){\n` ) ;
3397
3384
retArr . push ( 'if (!' ) ;
3398
3385
this . astGeneric ( whileNode . test , retArr ) ;
3399
3386
retArr . push ( ') break;\n' ) ;
@@ -3408,7 +3395,8 @@ class WebGLFunctionNode extends FunctionNode {
3408
3395
throw this . astErrorOutput ( 'Invalid while statement' , doWhileNode ) ;
3409
3396
}
3410
3397
3411
- retArr . push ( 'for (int safeI=0;safeI<LOOP_MAX;safeI++){\n' ) ;
3398
+ const iVariableName = this . getInternalVariableName ( 'safeI' ) ;
3399
+ retArr . push ( `for (int ${ iVariableName } =0;${ iVariableName } <LOOP_MAX;${ iVariableName } ++){\n` ) ;
3412
3400
this . astGeneric ( doWhileNode . body , retArr ) ;
3413
3401
retArr . push ( 'if (!' ) ;
3414
3402
this . astGeneric ( doWhileNode . test , retArr ) ;
@@ -3797,7 +3785,6 @@ const operatorMap = {
3797
3785
module . exports = {
3798
3786
WebGLFunctionNode
3799
3787
} ;
3800
-
3801
3788
} , { "../function-node" :8 } ] , 14 :[ function ( require , module , exports ) {
3802
3789
const {
3803
3790
utils
0 commit comments