Skip to content

Commit c2cbe2a

Browse files
committed
Automatic inner functions
1 parent 0f4de2c commit c2cbe2a

6 files changed

Lines changed: 66 additions & 20 deletions

File tree

src/backend/functionBuilder.js

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,25 @@ var functionBuilder = (function() {
1515
///
1616
/// [Constructor] Blank constructor, which initializes the properties
1717
///
18-
function functionBuilder() {
18+
function functionBuilder(gpu) {
1919
this.nodeMap = {};
20+
this.gpu = gpu;
2021
}
2122

2223
///
2324
/// Function: addFunction
2425
///
2526
/// Creates the functionNode, and add it to the nodeMap
2627
///
27-
/// Parameters:
28+
/// Parameters:
29+
/// gpu - {GPU} The GPU instance
2830
/// functionName - {String} Function name to assume, if its null, it attempts to extract from the function
29-
/// jsFunction - {JS Function} JS Function to do conversion
31+
/// jsFunction - {JS Function} JS Function to do conversion
3032
/// paramTypeArray - {[String,...]} Parameter type array, assumes all parameters are "float" if null
3133
/// returnType - {String} The return type, assumes "float" if null
3234
///
3335
function addFunction( functionName, jsFunction, paramTypeArray, returnType ) {
34-
this.addFunctionNode( new functionNode( functionName, jsFunction, paramTypeArray, returnType ) );
36+
this.addFunctionNode( new functionNode( this.gpu, functionName, jsFunction, paramTypeArray, returnType ) );
3537
}
3638
functionBuilder.prototype.addFunction = addFunction;
3739

@@ -40,7 +42,7 @@ var functionBuilder = (function() {
4042
///
4143
/// Add the funciton node directly
4244
///
43-
/// Parameters:
45+
/// Parameters:
4446
/// inNode - {functionNode} functionNode to add
4547
///
4648
function addFunctionNode( inNode ) {
@@ -56,7 +58,7 @@ var functionBuilder = (function() {
5658
/// This allow for "uneeded" functions to be automatically optimized out.
5759
/// Note that the 0-index, is the starting function trace.
5860
///
59-
/// Parameters:
61+
/// Parameters:
6062
/// functionName - {String} Function name to trace from, default to "kernel"
6163
/// retList - {[String,...]} Returning list of function names that is traced. Including itself.
6264
///
@@ -88,7 +90,7 @@ var functionBuilder = (function() {
8890
///
8991
/// Function: webglString_fromFunctionNames
9092
///
91-
/// Parameters:
93+
/// Parameters:
9294
/// functionList - {[String,...]} List of function to build the webgl string.
9395
///
9496
/// Returns:
@@ -109,7 +111,7 @@ var functionBuilder = (function() {
109111
///
110112
/// Function: webglString
111113
///
112-
/// Parameters:
114+
/// Parameters:
113115
/// functionName - {String} Function name to trace from. If null, it returns the WHOLE builder stack
114116
///
115117
/// Returns:
@@ -118,7 +120,7 @@ var functionBuilder = (function() {
118120
function webglString(functionName) {
119121
if(functionName) {
120122
return this.webglString_fromFunctionNames( this.traceFunctionCalls(functionName, []).reverse() );
121-
}
123+
}
122124
return this.webglString_fromFunctionNames(Object.keys(this.nodeMap));
123125
}
124126
functionBuilder.prototype.webglString = webglString;

src/backend/functionNode.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,15 @@ var functionNode = (function() {
3131
/// [Constructor] Builds the function with the given JS function, and argument type array.
3232
///
3333
/// Parameters:
34+
/// gpu - {GPU} The GPU instance
3435
/// functionName - {String} Function name to assume, if its null, it attempts to extract from the function
3536
/// jsFunction - {JS Function} JS Function to do conversion
3637
/// paramTypeArray - {[String,...]} Parameter type array, assumes all parameters are "float" if null
3738
/// returnType - {String} The return type, assumes "float" if null
3839
///
39-
function functionNode( functionName, jsFunction, paramTypeArray, returnType ) {
40+
function functionNode( gpu, functionName, jsFunction, paramTypeArray, returnType ) {
41+
42+
this.gpu = gpu;
4043

4144
//
4245
// Internal vars setup

src/backend/functionNode_webgl.js

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Closure capture for the ast function, prevent collision with existing AST functions
22
var functionNode_webgl = (function() {
33

4+
var gpu, jsFunctionString;
5+
46
///
57
/// Function: functionNode_webgl
68
///
@@ -13,6 +15,8 @@ var functionNode_webgl = (function() {
1315
/// the converted webGL function string
1416
///
1517
function functionNode_webgl( inNode ) {
18+
gpu = inNode.gpu;
19+
jsFunctionString = inNode.jsFunctionString;
1620
inNode.webglFunctionString_array = ast_generic( inNode.getJS_AST(), [], inNode );
1721
inNode.webglFunctionString = inNode.webglFunctionString_array.join("").trim();
1822
return inNode.webglFunctionString;
@@ -49,6 +53,8 @@ var functionNode_webgl = (function() {
4953
}
5054

5155
switch(ast.type) {
56+
case "FunctionDeclaration":
57+
return ast_FunctionDeclaration(ast, retArr, funcParam);
5258
case "FunctionExpression":
5359
return ast_FunctionExpression(ast, retArr, funcParam);
5460
case "ReturnStatement":
@@ -99,6 +105,38 @@ var functionNode_webgl = (function() {
99105
}
100106
}
101107

108+
/// Prases the abstract syntax tree, to its named function declartion
109+
///
110+
/// @param ast the AST object to parse
111+
/// @param retArr return array string
112+
/// @param funcParam FunctionNode, that tracks compilation state
113+
///
114+
/// @returns the appened retArr
115+
function ast_FunctionDeclaration(ast, retArr, funcParam) {
116+
// TODO: make this less hacky?
117+
var lines = jsFunctionString.split(/\r?\n/);
118+
119+
var start = ast.loc.start;
120+
var end = ast.loc.end;
121+
122+
var funcArr = [];
123+
124+
funcArr.push(lines[start.line-1].slice(start.column));
125+
for (var i=start.line; i<end.line-1; i++) {
126+
funcArr.push(lines[i]);
127+
}
128+
funcArr.push(lines[end.line-1].slice(0,end.column));
129+
130+
var funcStr = funcArr.join('\n');
131+
132+
// TODO: fix this evil!
133+
eval('var funcObj = ' + funcStr);
134+
135+
gpu.addFunction(funcObj);
136+
137+
return retArr;
138+
}
139+
102140
/// Prases the abstract syntax tree, to its named function
103141
///
104142
/// @param ast the AST object to parse
@@ -126,6 +164,7 @@ var functionNode_webgl = (function() {
126164

127165
retArr.push( funcParam.paramType[i] );
128166
retArr.push(" ");
167+
retArr.push("user_");
129168
retArr.push( funcParam.paramNames[i] );
130169
}
131170

@@ -251,10 +290,8 @@ var functionNode_webgl = (function() {
251290
retArr.push('uOutputDim.y');
252291
} else if (idtNode.name == "gpu_dimensionsZ") {
253292
retArr.push('uOutputDim.z');
254-
} else if(funcParam.isRootKernel) {
255-
retArr.push("user_"+idtNode.name);
256293
} else {
257-
retArr.push(idtNode.name);
294+
retArr.push("user_"+idtNode.name);
258295
}
259296

260297
return retArr;

src/backend/glsl.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@
150150
var builder = this.functionBuilder;
151151
var endianness = this.endianness;
152152

153-
var kernelNode = new functionNode("kernel", kernel);
153+
var kernelNode = new functionNode(gpu, "kernel", kernel);
154154
kernelNode.paramNames = [];
155155
kernelNode.paramType = [];
156156
kernelNode.isRootKernel = true;

src/gpu.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ var GPU = (function() {
4343
this.programCache = {};
4444
this.endianness = endianness();
4545

46-
this.functionBuilder = new functionBuilder();
46+
this.functionBuilder = new functionBuilder(this);
4747
this.functionBuilder.polyfillStandardFunctions();
4848
}
4949

test/src/internal/functionNode_test.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ QUnit.test( "hello_world: just return magic 42", function( assert ) {
88

99
// Create a function hello node
1010
var node = new functionNode(
11+
null,
1112
"hello_world",
1213
function() {
1314
return 42;
@@ -17,7 +18,7 @@ QUnit.test( "hello_world: just return magic 42", function( assert ) {
1718
assert.notEqual( node, null, "class creation check" );
1819
assert.notEqual( node.getJS_AST(), null, "AST fetch check" );
1920

20-
assert.equal(
21+
assert.equal(
2122
node.getWebglFunctionString().replace(/\s+/g,' '),
2223
"float hello_world() { return 42.0; }",
2324
"webgl function conversion check"
@@ -34,6 +35,7 @@ QUnit.test( "hello_inner: call a funciton inside a function", function( assert )
3435

3536
// Create a function hello node
3637
var node = new functionNode(
38+
null,
3739
"hello_inner",
3840
function() {
3941
return inner();
@@ -43,7 +45,7 @@ QUnit.test( "hello_inner: call a funciton inside a function", function( assert )
4345
assert.notEqual( node, null, "class creation check" );
4446
assert.notEqual( node.getJS_AST(), null, "AST fetch check" );
4547

46-
assert.equal(
48+
assert.equal(
4749
node.getWebglFunctionString().replace(/\s+/g,' '),
4850
"float hello_inner() { return inner(); }",
4951
"webgl function conversion check"
@@ -56,6 +58,7 @@ QUnit.test( "hello_inner: call a funciton inside a function", function( assert )
5658
QUnit.test( "Math.round implementation: A function with arguments", function( assert ) {
5759
// Math.round node
5860
var node = new functionNode(
61+
null,
5962
"round",
6063
function(a) {
6164
return Math.floor( a + 0.5 );
@@ -65,7 +68,7 @@ QUnit.test( "Math.round implementation: A function with arguments", function( as
6568
assert.notEqual( node, null, "class creation check" );
6669
assert.notEqual( node.getJS_AST(), null, "AST fetch check" );
6770

68-
assert.equal(
71+
assert.equal(
6972
node.getWebglFunctionString().replace(/\s+/g,' '),
7073
"float round(float a) { return floor(a+0.5); }",
7174
"webgl function conversion check"
@@ -78,6 +81,7 @@ QUnit.test( "Math.round implementation: A function with arguments", function( as
7881
QUnit.test( "Two arguments test", function( assert ) {
7982

8083
var node = new functionNode(
84+
null,
8185
"add_together",
8286
function(a,b) {
8387
return a+b;
@@ -87,7 +91,7 @@ QUnit.test( "Two arguments test", function( assert ) {
8791
assert.notEqual( node, null, "class creation check" );
8892
assert.notEqual( node.getJS_AST(), null, "AST fetch check" );
8993

90-
assert.equal(
94+
assert.equal(
9195
node.getWebglFunctionString().replace(/\s+/g,' '),
9296
"float add_together(float a, float b) { return a+b; }",
9397
"webgl function conversion check"
@@ -102,7 +106,7 @@ QUnit.test( "Automatic naming support", function( assert ) {
102106
return 42;
103107
}
104108
// Create a function hello node
105-
var node = new functionNode(null, hello_world);
109+
var node = new functionNode(null, null, hello_world);
106110
assert.notEqual( node, null, "class creation check" );
107111
assert.equal( node.functionName, "hello_world" );
108112
});

0 commit comments

Comments
 (0)