Skip to content

Commit 29404d4

Browse files
committed
Function builder tracer
1 parent dfaeaca commit 29404d4

5 files changed

Lines changed: 151 additions & 7 deletions

File tree

src/backend/functionBuilder.js

Lines changed: 78 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,81 @@
88
/// Properties:
99
/// nodeMap - {Object} Object map, where nodeMap[function] = functionNode;
1010
///
11-
function functionBuilder() {
12-
this.nodeMap = {};
13-
}
11+
var functionBuilder = (function() {
12+
13+
///
14+
/// Function: functionBuilder
15+
///
16+
/// [Constructor] Blank constructor, which initializes the properties
17+
///
18+
function functionBuilder() {
19+
this.nodeMap = {};
20+
}
21+
22+
///
23+
/// Function: addFunction
24+
///
25+
/// Creates the functionNode, and add it to the nodeMap
26+
///
27+
/// Parameters:
28+
/// 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
30+
/// paramTypeArray - {[String,...]} Parameter type array, assumes all parameters are "float" if null
31+
/// returnType - {String} The return type, assumes "float" if null
32+
///
33+
function addFunction( functionName, jsFunction, paramTypeArray, returnType ) {
34+
this.addFunctionNode( new functionNode( functionName, jsFunction, paramTypeArray, returnType ) );
35+
}
36+
functionBuilder.prototype.addFunction = addFunction;
37+
38+
///
39+
/// Function: addFunctionNode
40+
///
41+
/// Add the funciton node directly
42+
///
43+
/// Parameters:
44+
/// inNode - {functionNode} functionNode to add
45+
///
46+
function addFunctionNode( inNode ) {
47+
this.nodeMap[ inNode.functionName ] = inNode;
48+
}
49+
functionBuilder.prototype.addFunctionNode = addFunctionNode;
50+
51+
///
52+
/// Function: traceFunctionCalls
53+
///
54+
/// Trace all the depending functions being called, from a single function
55+
///
56+
/// This allow for "uneeded" functions to be automatically optimized out.
57+
///
58+
/// Parameters:
59+
/// functionName - {String} Function name to trace from, default to "kernel"
60+
/// retList - {[String,...]} Returning list of function names that is traced. Including itself.
61+
///
62+
/// Returns:
63+
/// {[String,...]} Returning list of function names that is traced. Including itself.
64+
function traceFunctionCalls( functionName, retList ) {
65+
functionName = functionName || "kernel";
66+
retList = retList || [];
67+
68+
var fNode = this.nodeMap[functionName];
69+
if( fNode ) {
70+
// Check if function already exists
71+
if( retList.indexOf(functionName) >= 0 ) {
72+
// Does nothing if already traced
73+
} else {
74+
retList.push(functionName);
75+
76+
fNode.getWebglFunctionString(); //ensure JS trace is done
77+
for(var i=0; i<fNode.calledFunctions.length; ++i) {
78+
this.traceFunctionCalls( fNode.calledFunctions[i], retList );
79+
}
80+
}
81+
}
82+
83+
return retList;
84+
}
85+
functionBuilder.prototype.traceFunctionCalls = traceFunctionCalls;
86+
87+
return functionBuilder;
88+
})();

src/backend/functionNode.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
/// This handles all the raw state, converted state, etc. Of a single function.
77
///
88
/// Properties:
9+
/// functionName - {String} Name of the function
910
/// jsFunction - {JS Function} The JS Function the node represents
1011
/// jsFunctionString - {String} jsFunction.toString()
1112
/// paramNames - {[String,...]} Parameter names of the function
@@ -30,10 +31,10 @@ var functionNode = (function() {
3031
/// [Constructor] Builds the function with the given JS function, and argument type array.
3132
///
3233
/// Parameters:
33-
/// functionName - {String} -Function name to assume, if its null, it attempts to extract from the function
34+
/// functionName - {String} Function name to assume, if its null, it attempts to extract from the function
3435
/// jsFunction - {JS Function} JS Function to do conversion
35-
/// paramTypeArray - {[String,...]} Parameter type array, assumes all parameters are "float" if not given
36-
/// returnType - {String} The return type, assumes "float" if not given
36+
/// paramTypeArray - {[String,...]} Parameter type array, assumes all parameters are "float" if null
37+
/// returnType - {String} The return type, assumes "float" if null
3738
///
3839
function functionNode( functionName, jsFunction, paramTypeArray, returnType ) {
3940

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>GPU.JS : FunctionBuilder unit testing</title>
6+
<link rel="stylesheet" href="../../lib/qunit-1.20.0.css">
7+
8+
<!-- gpu.js scripts -->
9+
<script src="../../../src/parser.js"></script>
10+
<script src="../../../src/backend/functionNode_webgl.js"></script>
11+
<script src="../../../src/backend/functionNode.js"></script>
12+
<script src="../../../src/backend/functionBuilder.js"></script>
13+
</head>
14+
<body>
15+
<div id="qunit"></div>
16+
<div id="qunit-fixture"></div>
17+
<script src="../../lib/qunit-1.20.0.js"></script>
18+
<script src="../../src/internal/functionBuilder_test.js"></script>
19+
</body>
20+
</html>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
///
2+
/// Test the various basic functionality of functionBuilder
3+
///
4+
5+
/// Test the function tracing of 3 layers
6+
QUnit.test( "traceFunctionCalls: 3 layer test", function( assert ) {
7+
assert.notEqual( functionBuilder, null, "script include check" );
8+
9+
function layerOne() {
10+
return 42;
11+
}
12+
13+
function layerTwo() {
14+
return layerOne() * 2;
15+
}
16+
17+
function layerThree() {
18+
return layerTwo() * 2;
19+
}
20+
21+
// Create a function hello node
22+
var builder = new functionBuilder();
23+
assert.notEqual( builder, null, "class creation check" );
24+
25+
builder.addFunction(null, layerOne);
26+
builder.addFunction(null, layerTwo);
27+
builder.addFunction(null, layerThree);
28+
29+
assert.deepEqual( builder.traceFunctionCalls("layerOne"), ["layerOne"] );
30+
assert.deepEqual( builder.traceFunctionCalls("layerTwo"), ["layerTwo","layerOne"] );
31+
assert.deepEqual( builder.traceFunctionCalls("layerThree"), ["layerThree","layerTwo","layerOne"] );
32+
});

test/src/internal/functionNode_test.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
/// @file functionNode_test.js
21
///
32
/// Test the various basic functionality of functionNode
43
///
@@ -49,6 +48,8 @@ QUnit.test( "hello_inner: call a funciton inside a function", function( assert )
4948
"float hello_inner() { return inner(); }",
5049
"webgl function conversion check"
5150
);
51+
52+
assert.deepEqual( node.calledFunctions, ["inner"] );
5253
});
5354

5455
/// Test creation of function, that calls another function, with ARGS
@@ -69,6 +70,8 @@ QUnit.test( "Math.round implementation: A function with arguments", function( as
6970
"float round(float a) { return floor(a+0.5); }",
7071
"webgl function conversion check"
7172
);
73+
74+
assert.deepEqual( node.calledFunctions, ["floor"] );
7275
});
7376

7477
/// Test creation of function, that calls another function, with ARGS
@@ -90,3 +93,16 @@ QUnit.test( "Two arguments test", function( assert ) {
9093
"webgl function conversion check"
9194
);
9295
});
96+
97+
/// Test the creation of a hello_world function
98+
QUnit.test( "Automatic naming support", function( assert ) {
99+
assert.notEqual( functionNode, null, "script include check" );
100+
101+
function hello_world() {
102+
return 42;
103+
}
104+
// Create a function hello node
105+
var node = new functionNode(null, hello_world);
106+
assert.notEqual( node, null, "class creation check" );
107+
assert.equal( node.functionName, "hello_world" );
108+
});

0 commit comments

Comments
 (0)