Skip to content

Commit 5f59354

Browse files
fix: this.thread, and this.output type handling, and block statements
1 parent f78b032 commit 5f59354

File tree

15 files changed

+993
-359
lines changed

15 files changed

+993
-359
lines changed

bin/gpu-browser-core.js

Lines changed: 162 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
*
55
* GPU Accelerated JavaScript
66
*
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)
99
*
1010
* @license MIT
1111
* The MIT License
@@ -273,7 +273,7 @@ class CPUFunctionNode extends FunctionNode {
273273
if (initArr.length > 0) {
274274
retArr.push(initArr.join(''), ';\n');
275275
}
276-
retArr.push(`for (int ${iVariableName}=0;${iVariableName}<LOOP_MAX;${iVariableName}++){\n`);
276+
retArr.push(`for (let ${iVariableName}=0;${iVariableName}<LOOP_MAX;${iVariableName}++){\n`);
277277
if (testArr.length > 0) {
278278
retArr.push(`if (!${testArr.join('')}) break;\n`);
279279
}
@@ -334,13 +334,17 @@ class CPUFunctionNode extends FunctionNode {
334334
}
335335

336336
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 {
338344
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+
}
344348
retArr.push('}\n');
345349
}
346350
return retArr;
@@ -355,7 +359,7 @@ class CPUFunctionNode extends FunctionNode {
355359
const type = this.getType(firstDeclaration.init);
356360
for (let i = 0; i < varDecNode.declarations.length; i++) {
357361
this.declarations[varDecNode.declarations[i].id.name] = {
358-
type,
362+
type: type === 'LiteralInteger' ? 'Number' : type,
359363
dependencies: {
360364
constants: [],
361365
arguments: []
@@ -865,13 +869,7 @@ class CPUKernel extends Kernel {
865869
return function (${ this.argumentNames.map(argumentName => 'user_' + argumentName).join(', ') }) {
866870
${ this._processConstants() }
867871
${ 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) }
875873
${ prototypes.length > 0 ? prototypes.join('\n') : '' }
876874
}.bind(this);`;
877875
return kernelString;
@@ -964,20 +962,40 @@ class CPUKernel extends Kernel {
964962
return imagesArray;
965963
}
966964

967-
_kernelLoop(kernelString) {
965+
_resultKernelLoop(kernelString) {
968966
switch (this.output.length) {
969967
case 1:
970-
return this._kernel1DLoop(kernelString);
968+
return this._resultKernel1DLoop(kernelString) + this._kernelOutput();
971969
case 2:
972-
return this._kernel2DLoop(kernelString);
970+
return this._resultKernel2DLoop(kernelString) + this._kernelOutput();
973971
case 3:
974-
return this._kernel3DLoop(kernelString);
972+
return this._resultKernel3DLoop(kernelString) + this._kernelOutput();
975973
default:
976974
throw new Error('unsupported size kernel');
977975
}
978976
}
979977

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) {
981999
const {
9821000
output
9831001
} = this;
@@ -995,12 +1013,29 @@ class CPUKernel extends Kernel {
9951013
}`;
9961014
}
9971015

998-
_kernel2DLoop(kernelString) {
1016+
_graphicalKernel1DLoop(kernelString) {
9991017
const {
10001018
output
10011019
} = 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') }
10041039
${ this._mapSubKernels(subKernel => `const result_${ subKernel.name } = new Array(${ output[1] });\n`).join('') }
10051040
for (let y = 0; y < ${ output[1] }; y++) {
10061041
this.thread.z = 0;
@@ -1017,7 +1052,25 @@ class CPUKernel extends Kernel {
10171052
}`;
10181053
}
10191054

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) {
10211074
const {
10221075
output
10231076
} = this;
@@ -1043,6 +1096,27 @@ class CPUKernel extends Kernel {
10431096
}`;
10441097
}
10451098

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+
10461120
_kernelOutput() {
10471121
if (!this.subKernels) {
10481122
return 'return result;';
@@ -1612,7 +1686,7 @@ class FunctionNode {
16121686
}
16131687
}
16141688
if (ast.name === 'Infinity') {
1615-
return 'Integer';
1689+
return 'Number';
16161690
}
16171691
return null;
16181692
case 'ReturnStatement':
@@ -1641,7 +1715,7 @@ class FunctionNode {
16411715
case 'this.thread.value':
16421716
return 'Integer';
16431717
case 'this.output.value':
1644-
return 'Integer';
1718+
return 'LiteralInteger';
16451719
case 'this.constants.value':
16461720
return this.getConstantType(ast.property.name);
16471721
case 'this.constants.value[]':
@@ -1793,6 +1867,7 @@ class FunctionNode {
17931867
this.getDependencies(ast.left, dependencies, isNotSafe);
17941868
this.getDependencies(ast.right, dependencies, isNotSafe);
17951869
return dependencies;
1870+
case 'UnaryExpression':
17961871
case 'UpdateExpression':
17971872
return this.getDependencies(ast.argument, dependencies, isNotSafe);
17981873
case 'VariableDeclaration':
@@ -3206,6 +3281,7 @@ class WebGLFunctionNode extends FunctionNode {
32063281
this.popState('casting-to-float');
32073282
break;
32083283

3284+
case 'Integer & Float':
32093285
case 'Integer & Number':
32103286
this.astGeneric(ast.left, retArr);
32113287
retArr.push(operatorMap[ast.operator] || ast.operator);
@@ -3234,7 +3310,7 @@ class WebGLFunctionNode extends FunctionNode {
32343310
break;
32353311
case 'Float & LiteralInteger':
32363312
case 'Number & LiteralInteger':
3237-
if (this.isState('force-integer')) {
3313+
if (this.isState('in-for-loop-test')) {
32383314
retArr.push('int(');
32393315
this.astGeneric(ast.left, retArr);
32403316
retArr.push(')');
@@ -3252,7 +3328,7 @@ class WebGLFunctionNode extends FunctionNode {
32523328
break;
32533329
case 'LiteralInteger & Float':
32543330
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')) {
32563332
this.pushState('casting-to-integer');
32573333
this.astGeneric(ast.left, retArr);
32583334
retArr.push(operatorMap[ast.operator] || ast.operator);
@@ -3286,10 +3362,7 @@ class WebGLFunctionNode extends FunctionNode {
32863362

32873363
astIdentifierExpression(idtNode, retArr) {
32883364
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);
32933366
}
32943367

32953368
if (idtNode.name === 'Infinity') {
@@ -3331,9 +3404,9 @@ class WebGLFunctionNode extends FunctionNode {
33313404
}
33323405

33333406
if (forNode.test) {
3334-
this.pushState('force-integer');
3407+
this.pushState('in-for-loop-test');
33353408
this.astGeneric(forNode.test, testArr);
3336-
this.popState('force-integer');
3409+
this.popState('in-for-loop-test');
33373410
} else {
33383411
isSafe = false;
33393412
}
@@ -3433,13 +3506,17 @@ class WebGLFunctionNode extends FunctionNode {
34333506
}
34343507

34353508
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 {
34373516
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+
}
34433520
retArr.push('}\n');
34443521
}
34453522
return retArr;
@@ -3463,20 +3540,34 @@ class WebGLFunctionNode extends FunctionNode {
34633540
throw this.astErrorOutput(`Markup type ${ markupType } not handled`, varDecNode);
34643541
}
34653542
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+
34713544
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(');
34763554
this.astGeneric(init, initResult);
34773555
initResult.push(')');
34783556
} 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+
}
34803571
}
34813572
result.push(initResult.join(''));
34823573

@@ -3541,18 +3632,33 @@ class WebGLFunctionNode extends FunctionNode {
35413632
} = this.getMemberExpressionDetails(mNode);
35423633
switch (signature) {
35433634
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}`);
35453639
return retArr;
35463640
case 'this.output.value':
35473641
switch (name) {
35483642
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+
}
35503648
break;
35513649
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+
}
35533655
break;
35543656
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+
}
35563662
break;
35573663
default:
35583664
throw this.astErrorOutput('Unexpected expression', mNode);

0 commit comments

Comments
 (0)