Roman Liutikov
front-end web dev
Slides link
https://slides.com/roman01la/code-transformation-for-fun-and-profit/live
your
native
language
your
native
language
AST
AST
CODE
CODE
(Abstract Syntax Tree)
const c = a + b;
const a = 1; const b = 2; const c = a + b;
(evaluating constant expressions at compile time)
Input
const c = 3;
Output
const add = (a, b) => a + b; const c = add(1, 2);
(replaces a function call site with the body of that function)
Input
const c = 1 + 2;
Output
for (let i = 0; i < 3; i++) { console.log(i); }
(replaces a loop with a sequence of expressions)
Input
console.log(0);
console.log(1);
console.log(2);
Output
class Button extends Component { render() { const { label, onClick } = this.props; return ( <button onClick={onClick}> {label} </button> ); } }
const Button = (props) => {
const { label, onClick } = props; return ( <button onClick={onClick}> {label} </button> );
}
[0 1 2] |> map(inc) |> filter(odd) // [1, 3]
#[1, 2, 3] > Immutable.List([1, 2, 3]) #{1, 2, 3} > Immutable.Set([1, 2, 3])
const getFileNames = (dir) => { if (__prepack) { return getFileNamesFrom(dir); } } const files = getFileNames('./');
const files = [ "img1.png", "data.json" ];
via domain specific optimization
(macros)
(runs code in Node.js at compile-time)
const files = preval` module.exports = getFilesFrom("./");
`;
const files = [ "img1.png", "data.json" ];
import css from "css.macro";
const styles = css` color: black; font-size: ${base * 2} `;
(input)
const styles = css("css-63457", { fontSize: base * 2 });
(output)
const Counter = ({ text }, { theme }, { val } = { val: 0 }, setState) => (
<div className={theme}>
<h1>{text}</h1>
<div>
<button onClick={() => setState({ val: val - 1 })}>-</button>
<span>{val}</span>
<button onClick={() => setState({ val: val + 1 })}>+</button>
</div>
</div>
);
By Roman Liutikov