SlideShare une entreprise Scribd logo
1  sur  99
Don’t Be Afraid of 
ASTs 
Jamund Ferguson
Our Basic Plan 
1. High-level overview 
2. Static Analysis with ASTs 
3. Transforming and refactoring 
4. A quick look at the Mozilla Parser API 
(de-facto standard AST format)
An abstract syntax tree 
is basically a DOM for 
your code.
An AST makes it easier to 
inspect and manipulate 
your code with confidence.
{ 
"type": "Program", 
"body": [ 
{ 
"type": “VariableDeclaration", 
"kind": "var" 
"declarations": [ 
{ 
"type": "VariableDeclarator", 
"id": { 
"type": "Identifier", 
"name": "fullstack" 
}, 
"init": { 
"type": "BinaryExpression", 
"left": { 
"type": "Identifier", 
"name": "node" 
}, 
"operator": "+", 
"right": { 
"type": "Identifier", 
"name": "ui" 
} 
} 
} 
], 
} 
] 
}
var fullstack = node + ui;
{ 
"type": "Program", 
"body": [ 
{ 
"type": “VariableDeclaration", 
"kind": "var" 
"declarations": [ 
{ 
"type": "VariableDeclarator", 
"id": { 
"type": "Identifier", 
"name": "fullstack" 
}, 
"init": { 
"type": "BinaryExpression", 
"left": { 
"type": "Identifier", 
"name": "node" 
}, 
"operator": "+", 
"right": { 
"type": "Identifier", 
"name": "ui" 
} 
} 
} 
], 
} 
] 
}
Things Built On ASTs 
• Syntax Highlighting 
• Code Completion 
• Static Analysis (aka 
JSLint, etc.) 
• Code Coverage 
• Minification 
• JIT Compilation 
• Source Maps 
• Compile to JS 
Languages 
So much more…
Static Analysis
It’s not just about 
formatting.
Fix a bug. Add a unit test. 
Fix a similar bug…
Write some really 
solid static analysis. 
Never write that same 
type of bug again.
function loadUser(req, res, next) { 
User.loadUser(function(err, user) { 
req.session.user = user; 
next(); 
}); 
} 
Bad Example 
We forgot to handle the error!
handle-callback-err 
1. Each time a function is declared check 
if there is an error* parameter 
If so set a count to 0; 
Increment count when error is used 
At the end of the function warn when 
count is empty 
* the parameter name can be defined by the user
Static Analysis 
• Complexity Analysis 
• Catching Mistakes 
• Consistent Style
History Lesson 
• 1995: JavaScript 
• 2002: JSLint started by Douglas Crockford 
• 2011: JSHint comes out as a fork of JSLint. 
Esprima AST parser released. 
• 2012: plato, escomplex, complexity-report 
• 2013: Nicholoas Zakas releases ESLint. Marat 
Dulin releases JSCS.
My static analysis tool 
of choice is ESLint.
JSHint 
Mixes the rule engine with the parser
Examples
no-console 
return { 
"MemberExpression": function(node) { 
if (node.object.name === "console") { 
context.report(node, "Unexpected console statement.”); 
} 
} 
}; 
https://github.com/eslint/eslint/blob/master/lib/rules/no-console.js
no-loop-func 
function checkForLoops(node) { 
var ancestors = context.getAncestors(); 
if (ancestors.some(function(ancestor) { 
return ancestor.type === "ForStatement" || 
ancestor.type === "WhileStatement" || 
ancestor.type === "DoWhileStatement"; 
})) { 
context.report(node, "Don't make functions within a loop"); 
} 
} 
return { 
"FunctionExpression": checkForLoops, 
"FunctionDeclaration": checkForLoops 
};
max-params 
var numParams = context.options[0] || 3; 
function checkParams(node) { 
if (node.params.length > numParams) { 
context.report(node, "This function has too many parameters 
({{count}}). Maximum allowed is {{max}}.", { 
count: node.params.length, 
max: numParams 
}); 
} 
} 
return { 
“FunctionDeclaration”: checkParams, 
“FunctionExpression”: checkParams 
}
no-jquery 
function isjQuery(name) { 
return name === '$' || name === 'jquery' || name === 'jQuery'; 
} 
return { 
“CallExpression”: function(node) { 
var name = node.callee && node.callee.name; 
if (isjQuery(name)) { 
context.report(node, 'Please avoid using jQuery here.’); 
} 
} 
}
More Complex Rules 
• indent 
• no-extend-native 
• no-next-next 
• security 
• internationalization
Other Areas for Static 
Analysis 
Code complexity and visualization is another 
area where static analysis is really useful. Plato is 
an exciting start, but I believe there are tons of 
more interesting things that can be done in this 
area.
Recap 
• Static Analysis can help you catch real bugs and keep 
your code maintainable 
• ESLint and JSCS both use ASTs for inspecting your 
code to make it easy to cleanly to add new rules 
• Static analysis can also help you manage your code 
complexity as well 
• What exactly does a for loop sound like?
Transforms
Sometimes you want to step 
into the future, but something 
is keeping you in the past.
Maybe it’s Internet 
Explorer
Maybe it’s the size of 
your code base
ASTs to the rescue!
Tools like falafel and recast give 
you an API to manipulate an AST 
and then convert that back into 
source code.
Two Types of AST 
Transformations 
Regenerative 
Regenerate the full file from the AST. Often losing 
comments and non-essential formatting. Fine for code 
not read by humans (i.e. browserify transforms). 
Partial-source transformation 
Regenerate only the parts of the source that have 
changed based on the AST modifications. Nicer for 
one-time changes in source.
Build a Simple 
Browserify Transform
var vfaurl lfsutlalcskt a=c kn o=d en o+d ber o+w sueir;ify;
4 Steps 
1. Buffer up the stream of source code 
2. Convert the source into an AST 
3. Transform the AST 
4. Re-generate and output the source
Step 1 
Use through to grab the source code 
var through = require(‘through'); 
var buffer = []; 
return through(function write(data) { 
buffer.push(data); 
}, function end () { 
var source = buffer.join(‘’); 
});
Step 2 
Use falafel to transform create an AST 
var falafel = require(‘falafel’); 
function end () { 
var source = buffer.join(‘’); 
var out = falafel(source, parse).toString(); 
}
Step 3 
function parse(node) { 
if (node.type === 'Identifier' && 
node.value === ‘ui’) { 
node.update('browserify'); 
} 
} 
Use falafel to transform the AST
Step 4 
Stream the source with through and close the stream 
function end () { 
var source = buffer.join(‘’); 
var out = falafel(source, parse).toString(); 
this.queue(out); 
this.queue(null); // end the stream 
}
var through = require('through'); 
var falafel = require('falafel'); 
module.exports = function() { 
var buffer = []; 
return through(function write(data) { 
buffer.push(data); 
}, function end() { 
var source = buffer.join('n'); 
var out = falafel(source, parse).toString(); 
this.queue(out); 
this.queue(null); // close the stream 
}); 
}; 
function parse(node) { 
if (node.type === 'Identifier' && 
node.name === 'ui') { 
node.update('browserify'); 
} 
}
It Works! 
browserify -t ./ui-to-browserify.js code.js 
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="var fullstack = node + browserify; 
},{}]},{},[1]);
Lots of code to do 
something simple?
Probably, but… 
It will do exactly what is 
expected 100% of the time.
And it’s a building block 
for building a bunch of 
cooler things.
What sort of cooler 
things?
How about 
performance?
V8 doesn’t do it, but 
there’s nothing stopping 
you*.
*Except it’s hard.
A Basic Map/Filter 
var a = [1, 2, 3]; 
var b = a.filter(function(n) { 
return n > 1; 
}).map(function(k) { 
return k * 2; 
});
Faster Like This 
var a = [1, 2, 3]; 
var b = []; 
for (var i = 0; i < a.length; i++) { 
if (a[i] > 1) { 
b.push(a[i] * 2); 
} 
}
A Basic Recast Script 
var recast = require(‘recast’); 
var code = fs.readFileSync(‘code.js', 'utf-8'); 
var ast = recast.parse(code); 
var faster = transform(ast); 
var output = recast.print(faster).code;
function transform(ast) { 
var transformedAST = new MapFilterEater({ 
body: ast.program.body 
}).visit(ast); 
return transformedAST; 
} 
var Visitor = recast.Visitor; 
var MapFilterEater = Visitor.extend({ 
init: function(options) {}, 
visitForStatement: function(ast) {}, 
visitIfStatement: function(ast) {}, 
visitCallExpression: function(ast) {}, 
visitVariableDeclarator: function(ast) {} 
});
How Does it Work? 
1. Move the right side of the b declaration into a for loop 
2. Set b = [] 
3. Place the .filter() contents inside of an if statement 
4. Unwrap the .map contents and .push() them into b 
5. Replace all of the local counters with a[_i]
And Voila…. 
var a = [1, 2, 3]; 
var b = []; 
for (var i = 0; i < a.length; i++) { 
if (a[i] > 1) { 
b.push(a[i] * 2); 
} 
}
Worth the effort? 
YES!
The most well-read documentation 
for how to engineer your app is the 
current codebase.
If you change your code, 
you can change the 
future.
Knowledge 
What is an AST and what does it look like?
Parser 
1. Read your raw JavaScript source. 
2. Parse out every single thing that’s happening. 
3. Return an AST that represents your code
Esprima is a very popular* 
parser that converts your code 
into an abstract syntax tree. 
*FB recently forked it to add support for ES6 and JSX
Parsers 
narcissus 
ZeParser 
Treehugger 
Uglify-JS 
Esprima 
Acorn
Esprima follows the Mozilla Parser 
API which is a well documented AST 
format used internally by Mozilla (and 
now by basically everyone else*)
var fullstack = node + ui;
{ 
"type": "Program", 
"body": [ 
{ 
"type": “VariableDeclaration", 
"kind": "var" 
"declarations": [ 
{ 
"type": "VariableDeclarator", 
"id": { 
"type": "Identifier", 
"name": "fullstack" 
}, 
"init": { 
"type": "BinaryExpression", 
"left": { 
"type": "Identifier", 
"name": "node" 
}, 
"operator": "+", 
"right": { 
"type": "Identifier", 
"name": "ui" 
} 
} 
} 
], 
} 
] 
}
{ 
"type": "Program", 
"body": [ 
{ 
"type": “VariableDeclaration", 
"kind": "var" 
"declarations": [ 
{ 
"type": "VariableDeclarator", 
"id": { 
"type": "Identifier", 
"name": "fullstack" 
}, 
"init": { 
"type": "BinaryExpression", 
"left": { 
"type": "Identifier", 
"name": "node" 
}, 
"operator": "+", 
"right": { 
"type": "Identifier", 
"name": "ui" 
} 
} 
} 
], 
} 
] 
}
Node Types 
SwitchCase (1) 
Property (1) 
Literal (1) 
Identifier (1) 
Declaration (3) 
Expression (14) 
Statement (18)
Expression Types 
• FunctionExpression 
• MemberExpression 
• CallExpression 
• NewExpression 
• ConditionalExpression 
• LogicalExpression 
• UpdateExpression 
• AssignmentExpression 
• BinaryExpression 
• UnaryExpression 
• SequenceExpression 
• ObjectExpression 
• ArrayExpression 
• ThisExpression
Statement Types 
• DebuggerStatement 
• ForInStatement 
• ForStatement 
• DoWhileStatement 
• WhileStatement 
• CatchClause 
• TryStatement 
• ThrowStatement 
• ReturnStatement 
• SwitchStatement 
• WithStatement 
• ContinueStatement 
• BreakStatement 
• LabeledStatement 
• IfStatement 
• ExpressionStatement 
• BlockStatement 
• EmptyStatement
Debugging ASTs
• When debugging console.log(ast) will not print a 
large nested AST properly. Instead you can use 
util.inspect: 
var util = require('util'); 
var tree = util.inspect(ast, { depth: null }); 
console.log(tree); 
• When transforming code start with the AST you 
want and then work backward. 
• Often this means pasting code using the Esprima 
online visualization tool or just outputting the trees 
into JS files and manually diffing them.
Oftentimes it helps to print out the code 
representation of a single node. 
In recast you can do: 
var source = recast.prettyPrint(ast, { 
tabWidth: 2 }).code; 
In ESLint you can get the current node with: 
var source = context.getSource(node)
ASTs can turn your 
code into play-dough
Totally worth the effort!
the end 
@xjamundx
Related 
- http://pegjs.majda.cz/ 
- https://www.kickstarter.com/projects/michaelficarra/make-a-better-coffeescript-compiler 
- http://coffeescript.org/documentation/docs/grammar.html 
- https://github.com/padolsey/parsers-built-with-js 
- https://github.com/zaach/jison 
- https://github.com/substack/node-falafel - eprima-based code modifier 
- https://github.com/substack/node-burrito - uglify-based AST walking code-modifier 
- https://github.com/jscs-dev/node-jscs/blob/e745ceb23c5f1587c3e43c0a9cfb05f5ad86b5ac/lib/js-file.js - JSCS’s way of walking the AST 
- https://www.npmjs.org/package/escodegen - converts an AST into real code again 
- https://www.npmjs.org/package/ast-types - esprima-ish parser 
- http://esprima.org/demo/parse.html - the most helpful tool 
https://github.com/RReverser/estemplate - AST-based search and replace 
https://www.npmjs.org/package/aster - build system thing 
Technical Papers 
http://aosd.net/2013/escodegen.html 
Videos / Slides 
http://slidedeck.io/benjamn/fluent2014-talk 
http://vimeo.com/93749422 
https://speakerdeck.com/michaelficarra/spidermonkey-parser-api-a-standard-for-structured-js-representations 
https://www.youtube.com/watch?v=fF_jZ7ErwUY 
https://speakerdeck.com/ariya/bringing-javascript-code-analysis-to-the-next-level 
Just in Time Compilers 
http://blogs.msdn.com/b/ie/archive/2012/06/13/advances-in-javascript-performance-in-ie10-and-windows-8.aspx 
https://blog.mozilla.org/luke/2014/01/14/asm-js-aot-compilation-and-startup-performance/ 
https://blog.indutny.com/4.how-to-start-jitting 
Podcasts 
http://javascriptjabber.com/082-jsj-jshint-with-anton-kovalyov/ 
http://javascriptjabber.com/054-jsj-javascript-parsing-asts-and-language-grammar-w-david-herman-and-ariya-hidayat/
RANDOM EXTRA 
SLIDES
Static analysis tools like ESLint 
and JSCS provide an API to let you 
inspect an AST to make sure it’s 
following certain patterns.
function isEmptyObject( obj ) { 
for ( var name in obj ) { 
return false; 
} 
return true; 
}
static analysis > unit testing > functional testing
function loadUser(req, res, next) { 
User.loadUser(function(err, user) { 
if (err) { 
next(err); 
} 
req.session.user = user; 
next(); 
}); 
} 
Another Example
Program 
VariableDeclarator 
VariableDeclaration 
FunctionExpression 
ExpressionStatement 
Identifier 
Identifier 
Abstract Christmas Trees
Tools like falafel and recast give 
you an API to manipulate an AST 
and then convert that back into 
source code.

Contenu connexe

Tendances

PLCとクラウドを接続!AWSにCODESYSを繋げてみた
PLCとクラウドを接続!AWSにCODESYSを繋げてみたPLCとクラウドを接続!AWSにCODESYSを繋げてみた
PLCとクラウドを接続!AWSにCODESYSを繋げてみたミソジ
 
[DLHacks LT] PytorchのDataLoader -torchtextのソースコードを読んでみた-
[DLHacks LT] PytorchのDataLoader -torchtextのソースコードを読んでみた-[DLHacks LT] PytorchのDataLoader -torchtextのソースコードを読んでみた-
[DLHacks LT] PytorchのDataLoader -torchtextのソースコードを読んでみた-Deep Learning JP
 
[PyConJP2019]Pythonで切り開く新しい農業
[PyConJP2019]Pythonで切り開く新しい農業[PyConJP2019]Pythonで切り開く新しい農業
[PyConJP2019]Pythonで切り開く新しい農業Makoto Koike
 
Deep Learning through Pytorch Exercises
Deep Learning through Pytorch ExercisesDeep Learning through Pytorch Exercises
Deep Learning through Pytorch Exercisesaiaioo
 
東大大学院 電子情報学特論講義資料「深層学習概論と理論解析の課題」大野健太
東大大学院 電子情報学特論講義資料「深層学習概論と理論解析の課題」大野健太東大大学院 電子情報学特論講義資料「深層学習概論と理論解析の課題」大野健太
東大大学院 電子情報学特論講義資料「深層学習概論と理論解析の課題」大野健太Preferred Networks
 
TCP/IPプロトコルスタック自作入門
TCP/IPプロトコルスタック自作入門TCP/IPプロトコルスタック自作入門
TCP/IPプロトコルスタック自作入門雅也 山本
 
Foss4G Japan 2021 シェープファイルの真の後継規格 FlatGeobufの普及啓蒙活動
Foss4G Japan 2021 シェープファイルの真の後継規格 FlatGeobufの普及啓蒙活動Foss4G Japan 2021 シェープファイルの真の後継規格 FlatGeobufの普及啓蒙活動
Foss4G Japan 2021 シェープファイルの真の後継規格 FlatGeobufの普及啓蒙活動Kanahiro Iguchi
 
ドライブレコーダの画像認識による道路情報の自動差分抽出
ドライブレコーダの画像認識による道路情報の自動差分抽出ドライブレコーダの画像認識による道路情報の自動差分抽出
ドライブレコーダの画像認識による道路情報の自動差分抽出Tetsutaro Watanabe
 
オープンデータを入手してQGISで開いてみよう!
オープンデータを入手してQGISで開いてみよう!オープンデータを入手してQGISで開いてみよう!
オープンデータを入手してQGISで開いてみよう!Masaharu Ohashi
 
立花氏とのスライドメモ.pptx
立花氏とのスライドメモ.pptx立花氏とのスライドメモ.pptx
立花氏とのスライドメモ.pptxrehacq
 
Obsのプラグイン作ってみた
Obsのプラグイン作ってみたObsのプラグイン作ってみた
Obsのプラグイン作ってみたYoshimura Soichiro
 
ゲームボーイ向けOSの作り方
ゲームボーイ向けOSの作り方ゲームボーイ向けOSの作り方
ゲームボーイ向けOSの作り方Yuma Ohgami
 
SSII2019TS: Shall We GANs?​ ~GANの基礎から最近の研究まで~
SSII2019TS: Shall We GANs?​ ~GANの基礎から最近の研究まで~SSII2019TS: Shall We GANs?​ ~GANの基礎から最近の研究まで~
SSII2019TS: Shall We GANs?​ ~GANの基礎から最近の研究まで~SSII
 
AWS社員による怒涛のLTチャレンジ! AWS IoT EduKitで遊ぼうぜ!
AWS社員による怒涛のLTチャレンジ! AWS IoT EduKitで遊ぼうぜ!AWS社員による怒涛のLTチャレンジ! AWS IoT EduKitで遊ぼうぜ!
AWS社員による怒涛のLTチャレンジ! AWS IoT EduKitで遊ぼうぜ!Amazon Web Services Japan
 
Pythonではじめるロケーションデータ解析
Pythonではじめるロケーションデータ解析Pythonではじめるロケーションデータ解析
Pythonではじめるロケーションデータ解析Hiroaki Sengoku
 
バグハンターの哀しみ
バグハンターの哀しみバグハンターの哀しみ
バグハンターの哀しみMasato Kinugawa
 
Sampling-Importance-Sampling을 이용한 선수 경기능력 측정
Sampling-Importance-Sampling을 이용한 선수 경기능력 측정Sampling-Importance-Sampling을 이용한 선수 경기능력 측정
Sampling-Importance-Sampling을 이용한 선수 경기능력 측정Mad Scientists
 
高次アンビソニックスのための マイクロホンアレイ設計の研究
高次アンビソニックスのための マイクロホンアレイ設計の研究高次アンビソニックスのための マイクロホンアレイ設計の研究
高次アンビソニックスのための マイクロホンアレイ設計の研究horieyuto
 
DRIVE CHARTを支えるAI技術
DRIVE CHARTを支えるAI技術DRIVE CHARTを支えるAI技術
DRIVE CHARTを支えるAI技術Yusuke Uchida
 
3D描画基礎知識
3D描画基礎知識3D描画基礎知識
3D描画基礎知識AimingStudy
 

Tendances (20)

PLCとクラウドを接続!AWSにCODESYSを繋げてみた
PLCとクラウドを接続!AWSにCODESYSを繋げてみたPLCとクラウドを接続!AWSにCODESYSを繋げてみた
PLCとクラウドを接続!AWSにCODESYSを繋げてみた
 
[DLHacks LT] PytorchのDataLoader -torchtextのソースコードを読んでみた-
[DLHacks LT] PytorchのDataLoader -torchtextのソースコードを読んでみた-[DLHacks LT] PytorchのDataLoader -torchtextのソースコードを読んでみた-
[DLHacks LT] PytorchのDataLoader -torchtextのソースコードを読んでみた-
 
[PyConJP2019]Pythonで切り開く新しい農業
[PyConJP2019]Pythonで切り開く新しい農業[PyConJP2019]Pythonで切り開く新しい農業
[PyConJP2019]Pythonで切り開く新しい農業
 
Deep Learning through Pytorch Exercises
Deep Learning through Pytorch ExercisesDeep Learning through Pytorch Exercises
Deep Learning through Pytorch Exercises
 
東大大学院 電子情報学特論講義資料「深層学習概論と理論解析の課題」大野健太
東大大学院 電子情報学特論講義資料「深層学習概論と理論解析の課題」大野健太東大大学院 電子情報学特論講義資料「深層学習概論と理論解析の課題」大野健太
東大大学院 電子情報学特論講義資料「深層学習概論と理論解析の課題」大野健太
 
TCP/IPプロトコルスタック自作入門
TCP/IPプロトコルスタック自作入門TCP/IPプロトコルスタック自作入門
TCP/IPプロトコルスタック自作入門
 
Foss4G Japan 2021 シェープファイルの真の後継規格 FlatGeobufの普及啓蒙活動
Foss4G Japan 2021 シェープファイルの真の後継規格 FlatGeobufの普及啓蒙活動Foss4G Japan 2021 シェープファイルの真の後継規格 FlatGeobufの普及啓蒙活動
Foss4G Japan 2021 シェープファイルの真の後継規格 FlatGeobufの普及啓蒙活動
 
ドライブレコーダの画像認識による道路情報の自動差分抽出
ドライブレコーダの画像認識による道路情報の自動差分抽出ドライブレコーダの画像認識による道路情報の自動差分抽出
ドライブレコーダの画像認識による道路情報の自動差分抽出
 
オープンデータを入手してQGISで開いてみよう!
オープンデータを入手してQGISで開いてみよう!オープンデータを入手してQGISで開いてみよう!
オープンデータを入手してQGISで開いてみよう!
 
立花氏とのスライドメモ.pptx
立花氏とのスライドメモ.pptx立花氏とのスライドメモ.pptx
立花氏とのスライドメモ.pptx
 
Obsのプラグイン作ってみた
Obsのプラグイン作ってみたObsのプラグイン作ってみた
Obsのプラグイン作ってみた
 
ゲームボーイ向けOSの作り方
ゲームボーイ向けOSの作り方ゲームボーイ向けOSの作り方
ゲームボーイ向けOSの作り方
 
SSII2019TS: Shall We GANs?​ ~GANの基礎から最近の研究まで~
SSII2019TS: Shall We GANs?​ ~GANの基礎から最近の研究まで~SSII2019TS: Shall We GANs?​ ~GANの基礎から最近の研究まで~
SSII2019TS: Shall We GANs?​ ~GANの基礎から最近の研究まで~
 
AWS社員による怒涛のLTチャレンジ! AWS IoT EduKitで遊ぼうぜ!
AWS社員による怒涛のLTチャレンジ! AWS IoT EduKitで遊ぼうぜ!AWS社員による怒涛のLTチャレンジ! AWS IoT EduKitで遊ぼうぜ!
AWS社員による怒涛のLTチャレンジ! AWS IoT EduKitで遊ぼうぜ!
 
Pythonではじめるロケーションデータ解析
Pythonではじめるロケーションデータ解析Pythonではじめるロケーションデータ解析
Pythonではじめるロケーションデータ解析
 
バグハンターの哀しみ
バグハンターの哀しみバグハンターの哀しみ
バグハンターの哀しみ
 
Sampling-Importance-Sampling을 이용한 선수 경기능력 측정
Sampling-Importance-Sampling을 이용한 선수 경기능력 측정Sampling-Importance-Sampling을 이용한 선수 경기능력 측정
Sampling-Importance-Sampling을 이용한 선수 경기능력 측정
 
高次アンビソニックスのための マイクロホンアレイ設計の研究
高次アンビソニックスのための マイクロホンアレイ設計の研究高次アンビソニックスのための マイクロホンアレイ設計の研究
高次アンビソニックスのための マイクロホンアレイ設計の研究
 
DRIVE CHARTを支えるAI技術
DRIVE CHARTを支えるAI技術DRIVE CHARTを支えるAI技術
DRIVE CHARTを支えるAI技術
 
3D描画基礎知識
3D描画基礎知識3D描画基礎知識
3D描画基礎知識
 

Similaire à Don't Be Afraid of Abstract Syntax Trees

WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...Fabio Franzini
 
Null Bachaav - May 07 Attack Monitoring workshop.
Null Bachaav - May 07 Attack Monitoring workshop.Null Bachaav - May 07 Attack Monitoring workshop.
Null Bachaav - May 07 Attack Monitoring workshop.Prajal Kulkarni
 
Event-driven IO server-side JavaScript environment based on V8 Engine
Event-driven IO server-side JavaScript environment based on V8 EngineEvent-driven IO server-side JavaScript environment based on V8 Engine
Event-driven IO server-side JavaScript environment based on V8 EngineRicardo Silva
 
JSLT: JSON querying and transformation
JSLT: JSON querying and transformationJSLT: JSON querying and transformation
JSLT: JSON querying and transformationLars Marius Garshol
 
Java Intro
Java IntroJava Intro
Java Introbackdoor
 
Attack monitoring using ElasticSearch Logstash and Kibana
Attack monitoring using ElasticSearch Logstash and KibanaAttack monitoring using ElasticSearch Logstash and Kibana
Attack monitoring using ElasticSearch Logstash and KibanaPrajal Kulkarni
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing UpDavid Padbury
 
Serializing EMF models with Xtext
Serializing EMF models with XtextSerializing EMF models with Xtext
Serializing EMF models with Xtextmeysholdt
 
Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Guillaume Laforge
 
Jsonsaga 100605143125-phpapp02
Jsonsaga 100605143125-phpapp02Jsonsaga 100605143125-phpapp02
Jsonsaga 100605143125-phpapp02Ramamohan Chokkam
 
Introduction to Javascript
Introduction to JavascriptIntroduction to Javascript
Introduction to JavascriptAmit Tyagi
 
React Native Evening
React Native EveningReact Native Evening
React Native EveningTroy Miles
 
Presto anatomy
Presto anatomyPresto anatomy
Presto anatomyDongmin Yu
 
Server side JavaScript: going all the way
Server side JavaScript: going all the wayServer side JavaScript: going all the way
Server side JavaScript: going all the wayOleg Podsechin
 
Ajax and JavaScript Bootcamp
Ajax and JavaScript BootcampAjax and JavaScript Bootcamp
Ajax and JavaScript BootcampAndreCharland
 

Similaire à Don't Be Afraid of Abstract Syntax Trees (20)

JS everywhere 2011
JS everywhere 2011JS everywhere 2011
JS everywhere 2011
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
 
Null Bachaav - May 07 Attack Monitoring workshop.
Null Bachaav - May 07 Attack Monitoring workshop.Null Bachaav - May 07 Attack Monitoring workshop.
Null Bachaav - May 07 Attack Monitoring workshop.
 
Coding Ajax
Coding AjaxCoding Ajax
Coding Ajax
 
Event-driven IO server-side JavaScript environment based on V8 Engine
Event-driven IO server-side JavaScript environment based on V8 EngineEvent-driven IO server-side JavaScript environment based on V8 Engine
Event-driven IO server-side JavaScript environment based on V8 Engine
 
JSLT: JSON querying and transformation
JSLT: JSON querying and transformationJSLT: JSON querying and transformation
JSLT: JSON querying and transformation
 
Java Intro
Java IntroJava Intro
Java Intro
 
Attack monitoring using ElasticSearch Logstash and Kibana
Attack monitoring using ElasticSearch Logstash and KibanaAttack monitoring using ElasticSearch Logstash and Kibana
Attack monitoring using ElasticSearch Logstash and Kibana
 
Coding Ajax
Coding AjaxCoding Ajax
Coding Ajax
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
 
Serializing EMF models with Xtext
Serializing EMF models with XtextSerializing EMF models with Xtext
Serializing EMF models with Xtext
 
Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008
 
Jsonsaga 100605143125-phpapp02
Jsonsaga 100605143125-phpapp02Jsonsaga 100605143125-phpapp02
Jsonsaga 100605143125-phpapp02
 
Java
JavaJava
Java
 
Introduction to Javascript
Introduction to JavascriptIntroduction to Javascript
Introduction to Javascript
 
"Javascript" por Tiago Rodrigues
"Javascript" por Tiago Rodrigues"Javascript" por Tiago Rodrigues
"Javascript" por Tiago Rodrigues
 
React Native Evening
React Native EveningReact Native Evening
React Native Evening
 
Presto anatomy
Presto anatomyPresto anatomy
Presto anatomy
 
Server side JavaScript: going all the way
Server side JavaScript: going all the wayServer side JavaScript: going all the way
Server side JavaScript: going all the way
 
Ajax and JavaScript Bootcamp
Ajax and JavaScript BootcampAjax and JavaScript Bootcamp
Ajax and JavaScript Bootcamp
 

Dernier

Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGSujit Pal
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
The Evolution of Money: Digital Transformation and CBDCs in Central Banking
The Evolution of Money: Digital Transformation and CBDCs in Central BankingThe Evolution of Money: Digital Transformation and CBDCs in Central Banking
The Evolution of Money: Digital Transformation and CBDCs in Central BankingSelcen Ozturkcan
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 

Dernier (20)

Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAG
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
The Evolution of Money: Digital Transformation and CBDCs in Central Banking
The Evolution of Money: Digital Transformation and CBDCs in Central BankingThe Evolution of Money: Digital Transformation and CBDCs in Central Banking
The Evolution of Money: Digital Transformation and CBDCs in Central Banking
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 

Don't Be Afraid of Abstract Syntax Trees

  • 1. Don’t Be Afraid of ASTs Jamund Ferguson
  • 2. Our Basic Plan 1. High-level overview 2. Static Analysis with ASTs 3. Transforming and refactoring 4. A quick look at the Mozilla Parser API (de-facto standard AST format)
  • 3. An abstract syntax tree is basically a DOM for your code.
  • 4. An AST makes it easier to inspect and manipulate your code with confidence.
  • 5. { "type": "Program", "body": [ { "type": “VariableDeclaration", "kind": "var" "declarations": [ { "type": "VariableDeclarator", "id": { "type": "Identifier", "name": "fullstack" }, "init": { "type": "BinaryExpression", "left": { "type": "Identifier", "name": "node" }, "operator": "+", "right": { "type": "Identifier", "name": "ui" } } } ], } ] }
  • 6. var fullstack = node + ui;
  • 7. { "type": "Program", "body": [ { "type": “VariableDeclaration", "kind": "var" "declarations": [ { "type": "VariableDeclarator", "id": { "type": "Identifier", "name": "fullstack" }, "init": { "type": "BinaryExpression", "left": { "type": "Identifier", "name": "node" }, "operator": "+", "right": { "type": "Identifier", "name": "ui" } } } ], } ] }
  • 8. Things Built On ASTs • Syntax Highlighting • Code Completion • Static Analysis (aka JSLint, etc.) • Code Coverage • Minification • JIT Compilation • Source Maps • Compile to JS Languages So much more…
  • 10. It’s not just about formatting.
  • 11. Fix a bug. Add a unit test. Fix a similar bug…
  • 12. Write some really solid static analysis. Never write that same type of bug again.
  • 13. function loadUser(req, res, next) { User.loadUser(function(err, user) { req.session.user = user; next(); }); } Bad Example We forgot to handle the error!
  • 14.
  • 15. handle-callback-err 1. Each time a function is declared check if there is an error* parameter If so set a count to 0; Increment count when error is used At the end of the function warn when count is empty * the parameter name can be defined by the user
  • 16. Static Analysis • Complexity Analysis • Catching Mistakes • Consistent Style
  • 17. History Lesson • 1995: JavaScript • 2002: JSLint started by Douglas Crockford • 2011: JSHint comes out as a fork of JSLint. Esprima AST parser released. • 2012: plato, escomplex, complexity-report • 2013: Nicholoas Zakas releases ESLint. Marat Dulin releases JSCS.
  • 18. My static analysis tool of choice is ESLint.
  • 19.
  • 20. JSHint Mixes the rule engine with the parser
  • 22. no-console return { "MemberExpression": function(node) { if (node.object.name === "console") { context.report(node, "Unexpected console statement.”); } } }; https://github.com/eslint/eslint/blob/master/lib/rules/no-console.js
  • 23. no-loop-func function checkForLoops(node) { var ancestors = context.getAncestors(); if (ancestors.some(function(ancestor) { return ancestor.type === "ForStatement" || ancestor.type === "WhileStatement" || ancestor.type === "DoWhileStatement"; })) { context.report(node, "Don't make functions within a loop"); } } return { "FunctionExpression": checkForLoops, "FunctionDeclaration": checkForLoops };
  • 24. max-params var numParams = context.options[0] || 3; function checkParams(node) { if (node.params.length > numParams) { context.report(node, "This function has too many parameters ({{count}}). Maximum allowed is {{max}}.", { count: node.params.length, max: numParams }); } } return { “FunctionDeclaration”: checkParams, “FunctionExpression”: checkParams }
  • 25. no-jquery function isjQuery(name) { return name === '$' || name === 'jquery' || name === 'jQuery'; } return { “CallExpression”: function(node) { var name = node.callee && node.callee.name; if (isjQuery(name)) { context.report(node, 'Please avoid using jQuery here.’); } } }
  • 26. More Complex Rules • indent • no-extend-native • no-next-next • security • internationalization
  • 27. Other Areas for Static Analysis Code complexity and visualization is another area where static analysis is really useful. Plato is an exciting start, but I believe there are tons of more interesting things that can be done in this area.
  • 28. Recap • Static Analysis can help you catch real bugs and keep your code maintainable • ESLint and JSCS both use ASTs for inspecting your code to make it easy to cleanly to add new rules • Static analysis can also help you manage your code complexity as well • What exactly does a for loop sound like?
  • 30. Sometimes you want to step into the future, but something is keeping you in the past.
  • 32. Maybe it’s the size of your code base
  • 33. ASTs to the rescue!
  • 34. Tools like falafel and recast give you an API to manipulate an AST and then convert that back into source code.
  • 35. Two Types of AST Transformations Regenerative Regenerate the full file from the AST. Often losing comments and non-essential formatting. Fine for code not read by humans (i.e. browserify transforms). Partial-source transformation Regenerate only the parts of the source that have changed based on the AST modifications. Nicer for one-time changes in source.
  • 36. Build a Simple Browserify Transform
  • 37. var vfaurl lfsutlalcskt a=c kn o=d en o+d ber o+w sueir;ify;
  • 38. 4 Steps 1. Buffer up the stream of source code 2. Convert the source into an AST 3. Transform the AST 4. Re-generate and output the source
  • 39. Step 1 Use through to grab the source code var through = require(‘through'); var buffer = []; return through(function write(data) { buffer.push(data); }, function end () { var source = buffer.join(‘’); });
  • 40. Step 2 Use falafel to transform create an AST var falafel = require(‘falafel’); function end () { var source = buffer.join(‘’); var out = falafel(source, parse).toString(); }
  • 41. Step 3 function parse(node) { if (node.type === 'Identifier' && node.value === ‘ui’) { node.update('browserify'); } } Use falafel to transform the AST
  • 42. Step 4 Stream the source with through and close the stream function end () { var source = buffer.join(‘’); var out = falafel(source, parse).toString(); this.queue(out); this.queue(null); // end the stream }
  • 43. var through = require('through'); var falafel = require('falafel'); module.exports = function() { var buffer = []; return through(function write(data) { buffer.push(data); }, function end() { var source = buffer.join('n'); var out = falafel(source, parse).toString(); this.queue(out); this.queue(null); // close the stream }); }; function parse(node) { if (node.type === 'Identifier' && node.name === 'ui') { node.update('browserify'); } }
  • 44. It Works! browserify -t ./ui-to-browserify.js code.js (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="var fullstack = node + browserify; },{}]},{},[1]);
  • 45. Lots of code to do something simple?
  • 46. Probably, but… It will do exactly what is expected 100% of the time.
  • 47. And it’s a building block for building a bunch of cooler things.
  • 48. What sort of cooler things?
  • 50.
  • 51. V8 doesn’t do it, but there’s nothing stopping you*.
  • 53. A Basic Map/Filter var a = [1, 2, 3]; var b = a.filter(function(n) { return n > 1; }).map(function(k) { return k * 2; });
  • 54. Faster Like This var a = [1, 2, 3]; var b = []; for (var i = 0; i < a.length; i++) { if (a[i] > 1) { b.push(a[i] * 2); } }
  • 55.
  • 56. A Basic Recast Script var recast = require(‘recast’); var code = fs.readFileSync(‘code.js', 'utf-8'); var ast = recast.parse(code); var faster = transform(ast); var output = recast.print(faster).code;
  • 57. function transform(ast) { var transformedAST = new MapFilterEater({ body: ast.program.body }).visit(ast); return transformedAST; } var Visitor = recast.Visitor; var MapFilterEater = Visitor.extend({ init: function(options) {}, visitForStatement: function(ast) {}, visitIfStatement: function(ast) {}, visitCallExpression: function(ast) {}, visitVariableDeclarator: function(ast) {} });
  • 58. How Does it Work? 1. Move the right side of the b declaration into a for loop 2. Set b = [] 3. Place the .filter() contents inside of an if statement 4. Unwrap the .map contents and .push() them into b 5. Replace all of the local counters with a[_i]
  • 59.
  • 60.
  • 61.
  • 62.
  • 63. And Voila…. var a = [1, 2, 3]; var b = []; for (var i = 0; i < a.length; i++) { if (a[i] > 1) { b.push(a[i] * 2); } }
  • 65. The most well-read documentation for how to engineer your app is the current codebase.
  • 66. If you change your code, you can change the future.
  • 67. Knowledge What is an AST and what does it look like?
  • 68. Parser 1. Read your raw JavaScript source. 2. Parse out every single thing that’s happening. 3. Return an AST that represents your code
  • 69. Esprima is a very popular* parser that converts your code into an abstract syntax tree. *FB recently forked it to add support for ES6 and JSX
  • 70. Parsers narcissus ZeParser Treehugger Uglify-JS Esprima Acorn
  • 71.
  • 72. Esprima follows the Mozilla Parser API which is a well documented AST format used internally by Mozilla (and now by basically everyone else*)
  • 73. var fullstack = node + ui;
  • 74. { "type": "Program", "body": [ { "type": “VariableDeclaration", "kind": "var" "declarations": [ { "type": "VariableDeclarator", "id": { "type": "Identifier", "name": "fullstack" }, "init": { "type": "BinaryExpression", "left": { "type": "Identifier", "name": "node" }, "operator": "+", "right": { "type": "Identifier", "name": "ui" } } } ], } ] }
  • 75. { "type": "Program", "body": [ { "type": “VariableDeclaration", "kind": "var" "declarations": [ { "type": "VariableDeclarator", "id": { "type": "Identifier", "name": "fullstack" }, "init": { "type": "BinaryExpression", "left": { "type": "Identifier", "name": "node" }, "operator": "+", "right": { "type": "Identifier", "name": "ui" } } } ], } ] }
  • 76. Node Types SwitchCase (1) Property (1) Literal (1) Identifier (1) Declaration (3) Expression (14) Statement (18)
  • 77. Expression Types • FunctionExpression • MemberExpression • CallExpression • NewExpression • ConditionalExpression • LogicalExpression • UpdateExpression • AssignmentExpression • BinaryExpression • UnaryExpression • SequenceExpression • ObjectExpression • ArrayExpression • ThisExpression
  • 78. Statement Types • DebuggerStatement • ForInStatement • ForStatement • DoWhileStatement • WhileStatement • CatchClause • TryStatement • ThrowStatement • ReturnStatement • SwitchStatement • WithStatement • ContinueStatement • BreakStatement • LabeledStatement • IfStatement • ExpressionStatement • BlockStatement • EmptyStatement
  • 80. • When debugging console.log(ast) will not print a large nested AST properly. Instead you can use util.inspect: var util = require('util'); var tree = util.inspect(ast, { depth: null }); console.log(tree); • When transforming code start with the AST you want and then work backward. • Often this means pasting code using the Esprima online visualization tool or just outputting the trees into JS files and manually diffing them.
  • 81. Oftentimes it helps to print out the code representation of a single node. In recast you can do: var source = recast.prettyPrint(ast, { tabWidth: 2 }).code; In ESLint you can get the current node with: var source = context.getSource(node)
  • 82. ASTs can turn your code into play-dough
  • 83. Totally worth the effort!
  • 85. Related - http://pegjs.majda.cz/ - https://www.kickstarter.com/projects/michaelficarra/make-a-better-coffeescript-compiler - http://coffeescript.org/documentation/docs/grammar.html - https://github.com/padolsey/parsers-built-with-js - https://github.com/zaach/jison - https://github.com/substack/node-falafel - eprima-based code modifier - https://github.com/substack/node-burrito - uglify-based AST walking code-modifier - https://github.com/jscs-dev/node-jscs/blob/e745ceb23c5f1587c3e43c0a9cfb05f5ad86b5ac/lib/js-file.js - JSCS’s way of walking the AST - https://www.npmjs.org/package/escodegen - converts an AST into real code again - https://www.npmjs.org/package/ast-types - esprima-ish parser - http://esprima.org/demo/parse.html - the most helpful tool https://github.com/RReverser/estemplate - AST-based search and replace https://www.npmjs.org/package/aster - build system thing Technical Papers http://aosd.net/2013/escodegen.html Videos / Slides http://slidedeck.io/benjamn/fluent2014-talk http://vimeo.com/93749422 https://speakerdeck.com/michaelficarra/spidermonkey-parser-api-a-standard-for-structured-js-representations https://www.youtube.com/watch?v=fF_jZ7ErwUY https://speakerdeck.com/ariya/bringing-javascript-code-analysis-to-the-next-level Just in Time Compilers http://blogs.msdn.com/b/ie/archive/2012/06/13/advances-in-javascript-performance-in-ie10-and-windows-8.aspx https://blog.mozilla.org/luke/2014/01/14/asm-js-aot-compilation-and-startup-performance/ https://blog.indutny.com/4.how-to-start-jitting Podcasts http://javascriptjabber.com/082-jsj-jshint-with-anton-kovalyov/ http://javascriptjabber.com/054-jsj-javascript-parsing-asts-and-language-grammar-w-david-herman-and-ariya-hidayat/
  • 87.
  • 88. Static analysis tools like ESLint and JSCS provide an API to let you inspect an AST to make sure it’s following certain patterns.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93. function isEmptyObject( obj ) { for ( var name in obj ) { return false; } return true; }
  • 94. static analysis > unit testing > functional testing
  • 95.
  • 96. function loadUser(req, res, next) { User.loadUser(function(err, user) { if (err) { next(err); } req.session.user = user; next(); }); } Another Example
  • 97. Program VariableDeclarator VariableDeclaration FunctionExpression ExpressionStatement Identifier Identifier Abstract Christmas Trees
  • 98.
  • 99. Tools like falafel and recast give you an API to manipulate an AST and then convert that back into source code.

Notes de l'éditeur

  1. Hi I’m Jamund. I work at PayPal doing node stuff and I have an environmental planning degree from the university of washington. Which hopefully qualifies me to talk you about trees today.
  2. Before I get started, how many of you have used these tools before and know what i’m talking about? Cool, so the rest of you. please stick around. It’s to ally worth it and I’m sure these people can attest to that.
  3. Instead of having to worry about string parsing and regexes and all that nonsense.
  4. Here’s an example. This is using the mozilla parser API format used by esprima and respresents the following code.
  5. This single statement creates a tree with 7 different nodes!!!
  6. Each item in this tree is a node of one of several types. We’ll discuss these types in more depth later.
  7. My goals is to help my team not introduce bugs in their code.
  8. Anyone know what’w wrong with this with?
  9. So we just built an ESLint rule that would ensure we never made that same mistake again! And it worked! We haven’t seen that type of bug crop up in our codebase.
  10. I love static analysis and that example proves that it can do a lot more than complain about your formatting.
  11. Essentially since 2011 ever new major static analysis tool has been based on esprima.
  12. Mostly because of this…If I want to add a rule. I can put it in its own file/function. Adding that handle-callback-err thing was no problem at all. Even if ESLint didn’t take it at this point I can just NPM install rules and use them! It rocks.
  13. Mixes the parser with the linter. It’s a great tool. But it’s not as easy to extend.
  14. Everytime there’s a member expression, which is thing.thing you just check to see if the name is the console, in which case it complains…..super simple.. But who cares. You can do this with “grep” or something. Let’s do something more fun.
  15. Pretty awesome. So every time you have a function expression or function declaration we check to see if has an ancestor that’s a loop. Pretty dang slick.
  16. https://github.com/eslint/eslint/blob/master/lib/rules/max-params.js
  17. Here’s a custom one we have that we only apply to certain parts of the code-base. For example in our backbone models, to prevent people from using Backbone.sync.
  18. Currently working with our globalization team on rules to help us avoid mistakes in handling dates, and phone numbers worldwide. and much more.
  19. For example: what if you could turn your AST into a series of beats and you could listen to your code to help determine how complicated it is. Short song good. Consistent tones good. Too many high notes bad? I don’t know. Think about that.
  20. We’ll use both of these in the following examples:
  21. How many of you have used browserify?
  22. Say we want to change this to this. Dynamically. Easy.
  23. Through takes 2 callbacks. The first lets you buffer the stream data the 2nd is when you get everything.
  24. This is our parse() function. We use falafel’s node.update to transform the node.
  25. altogether it looks like this
  26. And it works. And you can add them with npm and they just work.
  27. Marihn haverbeke, author of Acorn.js parser and a genius. Asks this question. The answer is no, but don’t let that stop you from writing .forEach() and .map() and .filter(). CODE IS FOR HUMANS
  28. https://github.com/xjamundx/perfify-recast/
  29. But we can do hard things.
  30. But we write code for humans, so we’ll let the transform take care of this.
  31. https://github.com/benjamn/recast uses “partial source transformation” to safely With browserify when you apply the transforms it rewrites the whole thing. You generally lose comments and stuff that isn’t really needed to form the AST. Recast (and some other tools like falafel) are nice for one-time refactoring because the employ techniques to limit the amount of code that is touched during the re-generation phase.
  32. I can show you the full source it’s online…. https://github.com/xjamundx/perfify-recast/blob/master/index.js
  33. There’s also a Facebook fork of Esprima that supports ES6, so it’s getting some support as well. I assume it will eventually bubble back up to the main branch…hopefully?
  34. You probably just need esprima.
  35. http://esprima.org/demo/parse.html#
  36. It’s also called the SpiderMonkey API. Are th
  37. This single statement creates a tree with 7 different nodes!!!
  38. The key to being successful in working with the JavaScript AST is to study the node types. Memorize them. Get used to them. Think about your JavaScript in this way. Here are the basics.
  39. esprima.org/demo/parse.html#
  40. https://github.com/benjamn/ast-types
  41. https://github.com/benjamn/ast-types/blob/master/def/core.js
  42. Essentially acorn came out around the time Uglify2 was coming out and Esprima was still new, so he spent a lot of time improving Uglify and didn’t want to rewrite it again, so he wrote a compatability layer.
  43. https://medium.com/@valueof/why-i-forked-jslint-to-jshint-73a72fd3612
  44. Anyone know what’w wrong with this with?
  45. https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Parser_API
  46. There are tons of other tools out there as well. I’m just most familiar with thes.e