4
4
*
5
5
* GPU Accelerated JavaScript
6
6
*
7
- * @version 2.0.0-rc.1
8
- * @date Sun Feb 10 2019 23:00:44 GMT-0500 (Eastern Standard Time)
7
+ * @version 2.0.0-rc.2
8
+ * @date Mon Feb 18 2019 10:52:36 GMT-0500 (Eastern Standard Time)
9
9
*
10
10
* @license MIT
11
11
* The MIT License
@@ -273,7 +273,7 @@ class CPUFunctionNode extends FunctionNode {
273
273
if ( initArr . length > 0 ) {
274
274
retArr . push ( initArr . join ( '' ) , ';\n' ) ;
275
275
}
276
- retArr . push ( `for (int ${ iVariableName } =0;${ iVariableName } <LOOP_MAX;${ iVariableName } ++){\n` ) ;
276
+ retArr . push ( `for (let ${ iVariableName } =0;${ iVariableName } <LOOP_MAX;${ iVariableName } ++){\n` ) ;
277
277
if ( testArr . length > 0 ) {
278
278
retArr . push ( `if (!${ testArr . join ( '' ) } ) break;\n` ) ;
279
279
}
@@ -334,13 +334,17 @@ class CPUFunctionNode extends FunctionNode {
334
334
}
335
335
336
336
astBlockStatement ( bNode , retArr ) {
337
- if ( ! this . isState ( 'loop-body' ) ) {
337
+ if ( this . isState ( 'loop-body' ) ) {
338
+ this . pushState ( 'block-body' ) ;
339
+ for ( let i = 0 ; i < bNode . body . length ; i ++ ) {
340
+ this . astGeneric ( bNode . body [ i ] , retArr ) ;
341
+ }
342
+ this . popState ( 'block-body' ) ;
343
+ } else {
338
344
retArr . push ( '{\n' ) ;
339
- }
340
- for ( let i = 0 ; i < bNode . body . length ; i ++ ) {
341
- this . astGeneric ( bNode . body [ i ] , retArr ) ;
342
- }
343
- if ( ! this . isState ( 'loop-body' ) ) {
345
+ for ( let i = 0 ; i < bNode . body . length ; i ++ ) {
346
+ this . astGeneric ( bNode . body [ i ] , retArr ) ;
347
+ }
344
348
retArr . push ( '}\n' ) ;
345
349
}
346
350
return retArr ;
@@ -355,7 +359,7 @@ class CPUFunctionNode extends FunctionNode {
355
359
const type = this . getType ( firstDeclaration . init ) ;
356
360
for ( let i = 0 ; i < varDecNode . declarations . length ; i ++ ) {
357
361
this . declarations [ varDecNode . declarations [ i ] . id . name ] = {
358
- type,
362
+ type : type === 'LiteralInteger' ? 'Number' : type ,
359
363
dependencies : {
360
364
constants : [ ] ,
361
365
arguments : [ ]
@@ -865,13 +869,7 @@ class CPUKernel extends Kernel {
865
869
return function (${ this . argumentNames . map ( argumentName => 'user_' + argumentName ) . join ( ', ' ) } ) {
866
870
${ this . _processConstants ( ) }
867
871
${ this . _processArguments ( ) }
868
- ${ this . _kernelLoop ( kernel ) }
869
- if (this.graphical) {
870
- this._imageData.data.set(this._colorData);
871
- this.context.putImageData(this._imageData, 0, 0);
872
- return;
873
- }
874
- ${ this . _kernelOutput ( ) }
872
+ ${ this . graphical ? this . _graphicalKernelLoop ( kernel ) : this . _resultKernelLoop ( kernel ) }
875
873
${ prototypes . length > 0 ? prototypes . join ( '\n' ) : '' }
876
874
}.bind(this);` ;
877
875
return kernelString ;
@@ -964,20 +962,40 @@ class CPUKernel extends Kernel {
964
962
return imagesArray ;
965
963
}
966
964
967
- _kernelLoop ( kernelString ) {
965
+ _resultKernelLoop ( kernelString ) {
968
966
switch ( this . output . length ) {
969
967
case 1 :
970
- return this . _kernel1DLoop ( kernelString ) ;
968
+ return this . _resultKernel1DLoop ( kernelString ) + this . _kernelOutput ( ) ;
971
969
case 2 :
972
- return this . _kernel2DLoop ( kernelString ) ;
970
+ return this . _resultKernel2DLoop ( kernelString ) + this . _kernelOutput ( ) ;
973
971
case 3 :
974
- return this . _kernel3DLoop ( kernelString ) ;
972
+ return this . _resultKernel3DLoop ( kernelString ) + this . _kernelOutput ( ) ;
975
973
default :
976
974
throw new Error ( 'unsupported size kernel' ) ;
977
975
}
978
976
}
979
977
980
- _kernel1DLoop ( kernelString ) {
978
+ _graphicalKernelLoop ( kernelString ) {
979
+ switch ( this . output . length ) {
980
+ case 1 :
981
+ return this . _graphicalKernel1DLoop ( kernelString ) + this . _graphicalOutput ( ) ;
982
+ case 2 :
983
+ return this . _graphicalKernel2DLoop ( kernelString ) + this . _graphicalOutput ( ) ;
984
+ case 3 :
985
+ return this . _graphicalKernel3DLoop ( kernelString ) + this . _graphicalOutput ( ) ;
986
+ default :
987
+ throw new Error ( 'unsupported size kernel' ) ;
988
+ }
989
+ }
990
+
991
+ _graphicalOutput ( ) {
992
+ return `
993
+ this._imageData.data.set(this._colorData);
994
+ this.context.putImageData(this._imageData, 0, 0);
995
+ return;`
996
+ }
997
+
998
+ _resultKernel1DLoop ( kernelString ) {
981
999
const {
982
1000
output
983
1001
} = this ;
@@ -995,12 +1013,29 @@ class CPUKernel extends Kernel {
995
1013
}` ;
996
1014
}
997
1015
998
- _kernel2DLoop ( kernelString ) {
1016
+ _graphicalKernel1DLoop ( kernelString ) {
999
1017
const {
1000
1018
output
1001
1019
} = this ;
1002
- return `const result = new Array(${ output [ 1 ] } );
1003
- ${ this . _mapSubKernels ( subKernel => `let subKernelResult_${ subKernel . name } ;` ) . join ( '\n' ) }
1020
+ return `${ this . _mapSubKernels ( subKernel => `let subKernelResult_${ subKernel . name } ;` ) . join ( '\n' ) }
1021
+ ${ this . _mapSubKernels ( subKernel => `const result_${ subKernel . name } = new Float32Array(${ output [ 0 ] } );\n` ) . join ( '' ) }
1022
+ for (let x = 0; x < ${ output [ 0 ] } ; x++) {
1023
+ this.thread.x = x;
1024
+ this.thread.y = 0;
1025
+ this.thread.z = 0;
1026
+ let kernelResult;
1027
+ ${ kernelString }
1028
+ result[x] = kernelResult;
1029
+ ${ this . _mapSubKernels ( subKernel => `result_${ subKernel . name } [x] = subKernelResult_${ subKernel . name } ;\n` ) . join ( '' ) }
1030
+ }` ;
1031
+ }
1032
+
1033
+ _resultKernel2DLoop ( kernelString ) {
1034
+ const {
1035
+ output
1036
+ } = this ;
1037
+ return `const result = new Array(${ output [ 2 ] } );
1038
+ ${ this . _mapSubKernels ( subKernel => `let subKernelResult_${ subKernel . name } ;` ) . join ( '\n' ) }
1004
1039
${ this . _mapSubKernels ( subKernel => `const result_${ subKernel . name } = new Array(${ output [ 1 ] } );\n` ) . join ( '' ) }
1005
1040
for (let y = 0; y < ${ output [ 1 ] } ; y++) {
1006
1041
this.thread.z = 0;
@@ -1017,7 +1052,25 @@ class CPUKernel extends Kernel {
1017
1052
}` ;
1018
1053
}
1019
1054
1020
- _kernel3DLoop ( kernelString ) {
1055
+ _graphicalKernel2DLoop ( kernelString ) {
1056
+ const {
1057
+ output
1058
+ } = this ;
1059
+ return `${ this . _mapSubKernels ( subKernel => `let subKernelResult_${ subKernel . name } ;` ) . join ( '\n' ) }
1060
+ ${ this . _mapSubKernels ( subKernel => `const result_${ subKernel . name } = new Array(${ output [ 1 ] } );\n` ) . join ( '' ) }
1061
+ for (let y = 0; y < ${ output [ 1 ] } ; y++) {
1062
+ this.thread.z = 0;
1063
+ this.thread.y = y;
1064
+ ${ this . _mapSubKernels ( subKernel => `const result_${ subKernel . name } X = result_${ subKernel . name } [y] = new Float32Array(${ output [ 0 ] } );\n` ) . join ( '' ) }
1065
+ for (let x = 0; x < ${ output [ 0 ] } ; x++) {
1066
+ this.thread.x = x;
1067
+ ${ kernelString }
1068
+ ${ this . _mapSubKernels ( subKernel => `result_${ subKernel . name } X[x] = subKernelResult_${ subKernel . name } ;\n` ) . join ( '' ) }
1069
+ }
1070
+ }` ;
1071
+ }
1072
+
1073
+ _resultKernel3DLoop ( kernelString ) {
1021
1074
const {
1022
1075
output
1023
1076
} = this ;
@@ -1043,6 +1096,27 @@ class CPUKernel extends Kernel {
1043
1096
}` ;
1044
1097
}
1045
1098
1099
+ _graphicalKernel3DLoop ( kernelString ) {
1100
+ const {
1101
+ output
1102
+ } = this ;
1103
+ return `${ this . _mapSubKernels ( subKernel => `let subKernelResult_${ subKernel . name } ;` ) . join ( '\n' ) }
1104
+ ${ this . _mapSubKernels ( subKernel => `const result_${ subKernel . name } = new Array(${ output [ 2 ] } );\n` ) . join ( '' ) }
1105
+ for (let z = 0; z < ${ output [ 2 ] } ; z++) {
1106
+ this.thread.z = z;
1107
+ ${ this . _mapSubKernels ( subKernel => `const result_${ subKernel . name } Y = result_${ subKernel . name } [z] = new Array(${ output [ 1 ] } );\n` ) . join ( '' ) }
1108
+ for (let y = 0; y < ${ output [ 1 ] } ; y++) {
1109
+ this.thread.y = y;
1110
+ ${ this . _mapSubKernels ( subKernel => `const result_${ subKernel . name } X = result_${ subKernel . name } Y[y] = new Float32Array(${ output [ 0 ] } );\n` ) . join ( '' ) }
1111
+ for (let x = 0; x < ${ output [ 0 ] } ; x++) {
1112
+ this.thread.x = x;
1113
+ ${ kernelString }
1114
+ ${ this . _mapSubKernels ( subKernel => `result_${ subKernel . name } X[x] = subKernelResult_${ subKernel . name } ;\n` ) . join ( '' ) }
1115
+ }
1116
+ }
1117
+ }` ;
1118
+ }
1119
+
1046
1120
_kernelOutput ( ) {
1047
1121
if ( ! this . subKernels ) {
1048
1122
return 'return result;' ;
@@ -1612,7 +1686,7 @@ class FunctionNode {
1612
1686
}
1613
1687
}
1614
1688
if ( ast . name === 'Infinity' ) {
1615
- return 'Integer ' ;
1689
+ return 'Number ' ;
1616
1690
}
1617
1691
return null ;
1618
1692
case 'ReturnStatement' :
@@ -1641,7 +1715,7 @@ class FunctionNode {
1641
1715
case 'this.thread.value' :
1642
1716
return 'Integer' ;
1643
1717
case 'this.output.value' :
1644
- return 'Integer ' ;
1718
+ return 'LiteralInteger ' ;
1645
1719
case 'this.constants.value' :
1646
1720
return this . getConstantType ( ast . property . name ) ;
1647
1721
case 'this.constants.value[]' :
@@ -1793,6 +1867,7 @@ class FunctionNode {
1793
1867
this . getDependencies ( ast . left , dependencies , isNotSafe ) ;
1794
1868
this . getDependencies ( ast . right , dependencies , isNotSafe ) ;
1795
1869
return dependencies ;
1870
+ case 'UnaryExpression' :
1796
1871
case 'UpdateExpression' :
1797
1872
return this . getDependencies ( ast . argument , dependencies , isNotSafe ) ;
1798
1873
case 'VariableDeclaration' :
@@ -3206,6 +3281,7 @@ class WebGLFunctionNode extends FunctionNode {
3206
3281
this . popState ( 'casting-to-float' ) ;
3207
3282
break ;
3208
3283
3284
+ case 'Integer & Float' :
3209
3285
case 'Integer & Number' :
3210
3286
this . astGeneric ( ast . left , retArr ) ;
3211
3287
retArr . push ( operatorMap [ ast . operator ] || ast . operator ) ;
@@ -3234,7 +3310,7 @@ class WebGLFunctionNode extends FunctionNode {
3234
3310
break ;
3235
3311
case 'Float & LiteralInteger' :
3236
3312
case 'Number & LiteralInteger' :
3237
- if ( this . isState ( 'force-integer ' ) ) {
3313
+ if ( this . isState ( 'in-for-loop-test ' ) ) {
3238
3314
retArr . push ( 'int(' ) ;
3239
3315
this . astGeneric ( ast . left , retArr ) ;
3240
3316
retArr . push ( ')' ) ;
@@ -3252,7 +3328,7 @@ class WebGLFunctionNode extends FunctionNode {
3252
3328
break ;
3253
3329
case 'LiteralInteger & Float' :
3254
3330
case 'LiteralInteger & Number' :
3255
- if ( this . isState ( 'force-integer ' ) || this . isState ( 'in-for-loop-init' ) ) {
3331
+ if ( this . isState ( 'in-for-loop-test ' ) || this . isState ( 'in-for-loop-init' ) ) {
3256
3332
this . pushState ( 'casting-to-integer' ) ;
3257
3333
this . astGeneric ( ast . left , retArr ) ;
3258
3334
retArr . push ( operatorMap [ ast . operator ] || ast . operator ) ;
@@ -3286,10 +3362,7 @@ class WebGLFunctionNode extends FunctionNode {
3286
3362
3287
3363
astIdentifierExpression ( idtNode , retArr ) {
3288
3364
if ( idtNode . type !== 'Identifier' ) {
3289
- throw this . astErrorOutput (
3290
- 'IdentifierExpression - not an Identifier' ,
3291
- idtNode
3292
- ) ;
3365
+ throw this . astErrorOutput ( 'IdentifierExpression - not an Identifier' , idtNode ) ;
3293
3366
}
3294
3367
3295
3368
if ( idtNode . name === 'Infinity' ) {
@@ -3331,9 +3404,9 @@ class WebGLFunctionNode extends FunctionNode {
3331
3404
}
3332
3405
3333
3406
if ( forNode . test ) {
3334
- this . pushState ( 'force-integer ' ) ;
3407
+ this . pushState ( 'in-for-loop-test ' ) ;
3335
3408
this . astGeneric ( forNode . test , testArr ) ;
3336
- this . popState ( 'force-integer ' ) ;
3409
+ this . popState ( 'in-for-loop-test ' ) ;
3337
3410
} else {
3338
3411
isSafe = false ;
3339
3412
}
@@ -3433,13 +3506,17 @@ class WebGLFunctionNode extends FunctionNode {
3433
3506
}
3434
3507
3435
3508
astBlockStatement ( bNode , retArr ) {
3436
- if ( ! this . isState ( 'loop-body' ) ) {
3509
+ if ( this . isState ( 'loop-body' ) ) {
3510
+ this . pushState ( 'block-body' ) ;
3511
+ for ( let i = 0 ; i < bNode . body . length ; i ++ ) {
3512
+ this . astGeneric ( bNode . body [ i ] , retArr ) ;
3513
+ }
3514
+ this . popState ( 'block-body' ) ;
3515
+ } else {
3437
3516
retArr . push ( '{\n' ) ;
3438
- }
3439
- for ( let i = 0 ; i < bNode . body . length ; i ++ ) {
3440
- this . astGeneric ( bNode . body [ i ] , retArr ) ;
3441
- }
3442
- if ( ! this . isState ( 'loop-body' ) ) {
3517
+ for ( let i = 0 ; i < bNode . body . length ; i ++ ) {
3518
+ this . astGeneric ( bNode . body [ i ] , retArr ) ;
3519
+ }
3443
3520
retArr . push ( '}\n' ) ;
3444
3521
}
3445
3522
return retArr ;
@@ -3463,20 +3540,34 @@ class WebGLFunctionNode extends FunctionNode {
3463
3540
throw this . astErrorOutput ( `Markup type ${ markupType } not handled` , varDecNode ) ;
3464
3541
}
3465
3542
let dependencies = this . getDependencies ( firstDeclaration . init ) ;
3466
- this . declarations [ firstDeclaration . id . name ] = Object . freeze ( {
3467
- type,
3468
- dependencies,
3469
- isSafe : this . isSafeDependencies ( dependencies ) ,
3470
- } ) ;
3543
+
3471
3544
const initResult = [ ] ;
3472
- initResult . push ( [ `${ markupType } ` ] ) ;
3473
- initResult . push ( `user_${ firstDeclaration . id . name } =` ) ;
3474
- if ( actualType === 'Number' && type === 'Integer' ) {
3475
- initResult . push ( 'int(' ) ;
3545
+ if ( actualType === 'Integer' && type === 'Integer' && ! this . isState ( 'in-for-loop-init' ) ) {
3546
+ this . declarations [ firstDeclaration . id . name ] = Object . freeze ( {
3547
+ type : 'Number' ,
3548
+ dependencies,
3549
+ isSafe : this . isSafeDependencies ( dependencies ) ,
3550
+ } ) ;
3551
+ initResult . push ( 'float ' ) ;
3552
+ initResult . push ( `user_${ firstDeclaration . id . name } =` ) ;
3553
+ initResult . push ( 'float(' ) ;
3476
3554
this . astGeneric ( init , initResult ) ;
3477
3555
initResult . push ( ')' ) ;
3478
3556
} else {
3479
- this . astGeneric ( init , initResult ) ;
3557
+ this . declarations [ firstDeclaration . id . name ] = Object . freeze ( {
3558
+ type,
3559
+ dependencies,
3560
+ isSafe : this . isSafeDependencies ( dependencies ) ,
3561
+ } ) ;
3562
+ initResult . push ( `${ markupType } ` ) ;
3563
+ initResult . push ( `user_${ firstDeclaration . id . name } =` ) ;
3564
+ if ( actualType === 'Number' && type === 'Integer' ) {
3565
+ initResult . push ( 'int(' ) ;
3566
+ this . astGeneric ( init , initResult ) ;
3567
+ initResult . push ( ')' ) ;
3568
+ } else {
3569
+ this . astGeneric ( init , initResult ) ;
3570
+ }
3480
3571
}
3481
3572
result . push ( initResult . join ( '' ) ) ;
3482
3573
@@ -3541,18 +3632,33 @@ class WebGLFunctionNode extends FunctionNode {
3541
3632
} = this . getMemberExpressionDetails ( mNode ) ;
3542
3633
switch ( signature ) {
3543
3634
case 'this.thread.value' :
3544
- retArr . push ( `threadId.${ name } ` ) ;
3635
+ if ( name !== 'x' && name !== 'y' && name !== 'z' ) {
3636
+ throw this . astErrorOutput ( 'Unexpected expression, expected `this.thread.x`, `this.thread.y`, or `this.thread.z`' , mNode ) ;
3637
+ }
3638
+ retArr . push ( `threadId.${ name } ` ) ;
3545
3639
return retArr ;
3546
3640
case 'this.output.value' :
3547
3641
switch ( name ) {
3548
3642
case 'x' :
3549
- retArr . push ( this . output [ 0 ] ) ;
3643
+ if ( this . isState ( 'casting-to-integer' ) ) {
3644
+ retArr . push ( this . output [ 0 ] ) ;
3645
+ } else {
3646
+ retArr . push ( this . output [ 0 ] , '.0' ) ;
3647
+ }
3550
3648
break ;
3551
3649
case 'y' :
3552
- retArr . push ( this . output [ 1 ] ) ;
3650
+ if ( this . isState ( 'casting-to-integer' ) ) {
3651
+ retArr . push ( this . output [ 1 ] ) ;
3652
+ } else {
3653
+ retArr . push ( this . output [ 1 ] , '.0' ) ;
3654
+ }
3553
3655
break ;
3554
3656
case 'z' :
3555
- retArr . push ( this . output [ 2 ] ) ;
3657
+ if ( this . isState ( 'casting-to-integer' ) ) {
3658
+ retArr . push ( this . output [ 2 ] ) ;
3659
+ } else {
3660
+ retArr . push ( this . output [ 2 ] , '.0' ) ;
3661
+ }
3556
3662
break ;
3557
3663
default :
3558
3664
throw this . astErrorOutput ( 'Unexpected expression' , mNode ) ;
0 commit comments