Permalink
Browse files

Public release

  • Loading branch information...
0 parents commit e73c73191f3a6a0f2e22d7aab217e7bfc29d8931 @FGRibreau committed Sep 3, 2011
Showing with 980 additions and 0 deletions.
  1. +4 −0 History.md
  2. +27 −0 LICENSE
  3. +7 −0 Makefile
  4. +105 −0 README.md
  5. +79 −0 bench/bench.coffee
  6. +63 −0 bench/bench.js
  7. +35 −0 example/inline_function.coffee
  8. +35 −0 example/inline_function.js
  9. +1 −0 index.js
  10. +199 −0 lib/ast_inlining.js
  11. +24 −0 package.json
  12. +218 −0 test/ast_inlining.test.coffee
  13. +183 −0 test/ast_inlining.test.js
@@ -0,0 +1,4 @@
+1.0.0 / 2011-09-3
+==================
+
+ * First public release
27 LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2011, Francois-Guillaume Ribreau <node@fgribreau.com>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name of node-ast-inliner nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,7 @@
+build:
+ coffee -c ./*/*.coffee
+
+test:
+ nodeunit ./test/*.js
+
+.PHONY: test
105 README.md
@@ -0,0 +1,105 @@
+# Node Ast Inlining
+
+Node Ast Inlining is a small (~200 LOC) library that [inline and expand](http://en.wikipedia.org/wiki/Inline_expansion) function call
+
+### Work In Progress
+
+Node Ast Inlining currently inling-expand only method calls and inline simple function with return statement.
+
+### Installation
+
+This package can be installed via [npm](http://npmjs.org/) as follows
+
+ % npm install ast-inlining -g
+
+### Usage
+
+ var inliner = require('../index')
+ , f = {
+ testInput: function(data) {
+ // Method calls that will be inlined
+ return a._startWith(data.content, 'ipsum') || f._contains(data.name, 'reau') || a._startWith(data.content, 'Lorem');
+ },
+
+ _substr: function(where, what) {
+ return where.indexOf(what) !== -1;
+ },
+ _contains: function(where, what) {
+ return f._substr(where, ' ' + what + ' ');
+ },
+ _csstartWith: function(where, what) {
+ return where.indexOf(what) === 0;
+ }
+ }
+ , a = {
+ _startWith: function(where, what) {
+ return f._csstartWith(where.toLowerCase(), what.toLowerCase());
+ }
+ }
+
+ // For now we need to explicitly declare the testInput call context
+ var context = {f:f, a:a};
+
+ f.testInputInlined = inliner.inline_function(f.testInput, context);
+
+ console.log(f.testInputInlined.toString());
+ /*
+ * function anon_0(data) {
+ * return data.content.toLowerCase().indexOf("ipsum".toLowerCase()) === 0
+ * || data.name.indexOf(" reau ") !== -1
+ * || data.content.toLowerCase().indexOf("Lorem".toLowerCase()) === 0;
+ * }
+ */
+
+### API
+
+ * `inline_function(fct, context [, option])` Inline-expands method calls inside `fct` given the `context`
+ * `inline_ast(ast, context)` Inline-expands method calls inside `ast` given the `context`
+
+### Benchmark
+
+ % node bench/bench.js
+
+![Benchmark](http://bit.ly/r9wAwI "Benchmark's result")
+
+![Benchmark](http://bit.ly/r6pUZp "Benchmark's result")
+
+### Tests
+ % make test
+ Or
+
+ % nodeunit test/ast_inlining.test.js
+
+### TODO
+ * `extremeInline` option which inline native Number and String's prototype method like toLowerCase()
+ * Inline & expand small function < 5 LOC
+
+### Licence
+
+Copyright (c) 2011, Francois-Guillaume Ribreau <node@fgribreau.com>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ - Neither the name of node-ast-inliner nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,79 @@
+# Dependencies
+jslitmus = require 'jslitmus'
+jsp = require("uglify-js").parser
+pro = require("uglify-js").uglify
+vm = require 'vm'
+sys = require 'sys'
+
+inliner = require '../index'
+
+# Helpers
+eval = (sourceCode, isVerbose, evalContext) ->
+ try
+ vm.runInNewContext("this[\"-eval-\"] = function(code){ eval(code); };", evalContext)
+ evalContext["-eval-"] "this.evaluate = function(){return " + (sourceCode or "") + "};"
+ return evalContext.evaluate()
+ catch error
+ throw error if isVerbose
+ return false
+
+# f.startWith & f.contain are going to be inlined
+fct = """
+ function myFunc(data) {
+ return f.startWith(data.content, 'ipsum') || f.contains(data.name, 'reau') || f.startWith(data.content, 'Lorem')
+ }
+ """;
+
+# Stub
+data =
+ lang:'fr'
+ content:'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod'
+ name:'fgribreau'
+
+f =
+ substr: (where, what) ->
+ where.indexOf(what) != -1
+
+ contains: (where, what) ->
+ f.substr(where, ' '+what+' ')
+
+ startWith: (where, what) ->
+ f.csstartWith(where.toLowerCase(), what.toLowerCase())
+
+ # case sensitive
+ csstartWith: (where, what) ->
+ where.indexOf(what) == 0
+
+context =
+ f:f
+
+
+ast = jsp.parse(fct);
+inliner.inline_ast(ast, context)
+
+
+func1 = eval(fct, true, context)
+func2 = eval(pro.gen_code(ast), true, context)
+
+console.log 'Without inlining:', func1.toString(),"\n"
+console.log 'With inlining:', func2.toString(),"\n\nTesting..."
+
+
+jslitmus.test('Without inlining', () ->
+ func1(data)
+)
+
+jslitmus.test('With inlining', () ->
+ func2(data)
+)
+# Log the test results
+jslitmus.on('complete', (test) ->
+ sys.log(test)
+)
+
+jslitmus.on('all_complete', () ->
+ console.log("\n",jslitmus.getGoogleChart());
+)
+
+# Run it!
+jslitmus.runAll()
@@ -0,0 +1,63 @@
+(function() {
+ var ast, context, data, eval, f, fct, func1, func2, inliner, jslitmus, jsp, pro, sys, vm;
+ jslitmus = require('jslitmus');
+ jsp = require("uglify-js").parser;
+ pro = require("uglify-js").uglify;
+ vm = require('vm');
+ sys = require('sys');
+ inliner = require('../index');
+ eval = function(sourceCode, isVerbose, evalContext) {
+ try {
+ vm.runInNewContext("this[\"-eval-\"] = function(code){ eval(code); };", evalContext);
+ evalContext["-eval-"]("this.evaluate = function(){return " + (sourceCode || "") + "};");
+ return evalContext.evaluate();
+ } catch (error) {
+ if (isVerbose) {
+ throw error;
+ }
+ return false;
+ }
+ };
+ fct = "function myFunc(data) {\n return f.startWith(data.content, 'ipsum') || f.contains(data.name, 'reau') || f.startWith(data.content, 'Lorem')\n}";
+ data = {
+ lang: 'fr',
+ content: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod',
+ name: 'fgribreau'
+ };
+ f = {
+ substr: function(where, what) {
+ return where.indexOf(what) !== -1;
+ },
+ contains: function(where, what) {
+ return f.substr(where, ' ' + what + ' ');
+ },
+ startWith: function(where, what) {
+ return f.csstartWith(where.toLowerCase(), what.toLowerCase());
+ },
+ csstartWith: function(where, what) {
+ return where.indexOf(what) === 0;
+ }
+ };
+ context = {
+ f: f
+ };
+ ast = jsp.parse(fct);
+ inliner.inline_ast(ast, context);
+ func1 = eval(fct, true, context);
+ func2 = eval(pro.gen_code(ast), true, context);
+ console.log('Without inlining:', func1.toString(), "\n");
+ console.log('With inlining:', func2.toString(), "\n\nTesting...");
+ jslitmus.test('Without inlining', function() {
+ return func1(data);
+ });
+ jslitmus.test('With inlining', function() {
+ return func2(data);
+ });
+ jslitmus.on('complete', function(test) {
+ return sys.log(test);
+ });
+ jslitmus.on('all_complete', function() {
+ return console.log("\n", jslitmus.getGoogleChart());
+ });
+ jslitmus.runAll();
+}).call(this);
@@ -0,0 +1,35 @@
+inliner = require '../index'
+# or
+# inliner = require 'ast-inlining'
+
+f =
+ testInput: (data) ->
+ # Method calls that will be inlined
+ a._startWith(data.content, 'ipsum') || f._contains(data.name, 'reau') || a._startWith(data.content, 'Lorem')
+
+ _substr: (where, what) ->
+ where.indexOf(what) != -1
+
+ _contains: (where, what) ->
+ f._substr(where, ' '+what+' ')
+
+ # case sensitive
+ _csstartWith: (where, what) ->
+ where.indexOf(what) == 0
+
+a =
+ _startWith: (where, what) ->
+ f._csstartWith(where.toLowerCase(), what.toLowerCase())
+
+
+# Inline calls
+f.testInputInlined = inliner.inline_function(f.testInput, f:f, a:a)
+
+console.log f.testInputInlined.toString()
+###
+# function anon_0(data) {
+# return data.content.toLowerCase().indexOf("ipsum".toLowerCase()) === 0
+# || data.name.indexOf(" reau ") !== -1
+# || data.content.toLowerCase().indexOf("Lorem".toLowerCase()) === 0;
+# }
+###
@@ -0,0 +1,35 @@
+(function() {
+ var a, f, inliner;
+ inliner = require('../index');
+ f = {
+ testInput: function(data) {
+ return a._startWith(data.content, 'ipsum') || f._contains(data.name, 'reau') || a._startWith(data.content, 'Lorem');
+ },
+ _substr: function(where, what) {
+ return where.indexOf(what) !== -1;
+ },
+ _contains: function(where, what) {
+ return f._substr(where, ' ' + what + ' ');
+ },
+ _csstartWith: function(where, what) {
+ return where.indexOf(what) === 0;
+ }
+ };
+ a = {
+ _startWith: function(where, what) {
+ return f._csstartWith(where.toLowerCase(), what.toLowerCase());
+ }
+ };
+ f.testInputInlined = inliner.inline_function(f.testInput, {
+ f: f,
+ a: a
+ });
+ console.log(f.testInputInlined.toString());
+ /*
+ # function anon_0(data) {
+ # return data.content.toLowerCase().indexOf("ipsum".toLowerCase()) === 0
+ # || data.name.indexOf(" reau ") !== -1
+ # || data.content.toLowerCase().indexOf("Lorem".toLowerCase()) === 0;
+ # }
+ */
+}).call(this);
@@ -0,0 +1 @@
+module.exports = require('./lib/ast_inlining');
Oops, something went wrong.

0 comments on commit e73c731

Please sign in to comment.