May 14 2014, Verona
Massimiliano Mantione
Passionate about languages and compilers
Worked in the V8 team in Google
Overall, worked on JIT compilers for +7 years
Now working on scalable, fault tolerant,
web facing distributed systems
I started as a Javascript hater
When I sow Javascript for the 1st time (in 1995) I vowed that I would never touch such an abomination, even with a 10 feet pole
Eventually, I changed my mind, but...
Let's change subject!
Do you know what metaprogramming is?
Are you sure?
It is not "code that can see your code"...
It is "code that can modify your code"!
Please read "Beating the Average"
by Paul Graham
Structured control flow
(if then else, while...)
Record and arrays (dynamic?)
First class functions
Lexical scoping (closures!)
Automating memory management
Metaprogramming!
Metaprogramming is writing code that modifies code
A piece of code that modifies other code is called a macro
To write a macro, code must be handled as data
Therefore a macro is a function that takes code as input and produces code as output
Let's experiment
Too many to mention
Convertion rules can kick in with WAT? results
Forgetting a variable declaration can be catastrophic
Lack of proper block-scoping (until ES6)
Verbose Java-like syntax
No type system and no metaprogramming
Sticking to "the good parts"
Using jslint or jshint
Or... with a different programming language!
(like Coffeescript)
Coffeescript
(nice, but no metaprogramming)
Typescript
(has a type system, but is still Javascript)
Lispyscript
(semi-unknown, and is a Lisp)
Clojurescript
(not very Javascript-friendly, and is also a Lisp)
Clean syntax (like Coffeescript)
Sane scoping rules (like ES6 let)
A type system (like Typescript)
Real metaprogramming (like Lisp)
Be a Good Javascript Citizen
Designed for
zero runtime overhead
Each core construct cleanly translates into a Javascript primitive
Consuming existing modules is natural
Producing modules of any kind is easy
Full source map support, from day 1
Our all-time favorite first program:
console.log 'Hello, Metascript!'
...Just Work!
(1 + 2 * 3).should.equal 7
('a' + 'b' + 'c').should.equal "abc"
(typeof (1 + 2)).should.equal 'number'
(typeof {}).should.equal 'object'
...Just Expressions!
(if true 1 else 2).should.equal 1
(do
var a = 'a'
a = a + a
a
).should.equal 'aa'
var fact = (x) ->
loop (var r = 1, x)
if (x > 0)
next! (r * x, x - 1)
else
r
fact(1).should.equal(1)
fact(5).should.equal(5 * 4 * 3 * 2 * 1)
Two main conflicting goals:
Also in the wishlist:
Note that expression grouping and nesting can be achieved in different ways
Metascript uses all of them interchangeably!
callFunction(a, b, c)
callFunction
(a, b, c)
callFunction
a
b
c
if condition (f a) else (g b)
if condition
f a
else
g b
if condition f(a)
else g(b)
...if you feel you need them
callFunction (
a
b
c
)
if condition (
f(a)
) else (
g(b)
)
callFunction (a, b, c)
callFunction a b c
callFunction (a) (b) (c)
( (callFunction(a)) (b) ) (c)
var (a, b) =
if true (1, 2) else (3, 4)
a.should.equal 1
b.should.equal 2
(a, b) = (b, a)
a.should.equal 2
b.should.equal 1
var status =
if ok do
console.log 'Starting up'
engine.power = 100
give! 'moving'
else do
console.log 'Stopping'
engine.power = 0
'stopped'
(var status, var message, engine.power) =
if ok
('moving', 'Starting up', 100)
else
('stopped', 'Stopping', 0)
console.log message
var r = []
loop (var i = 1)
if (i > 10) end
var s = 'element' + i
r.push s
; These will not compile...
console.log i
console.log s
Sometimes inside macros you need to create variables that will be added to the program code
You risk to use a variable name already in the scope where the macro is expanded
Multiple expansions of the macro in the same scope risk to overwrite the variable
Metascript allows you to have variable with "virtual" names that will be transformed so they are guaranteed to be uinique
Making the compiler production-ready
Completing the metaprogramming system
Writing "standard" macros
Implementing the type system
It is already pretty solid
Add support for for ... in
(Object.keys() is not always enough)
Running in the browser and implement a REPL shell are not on my radar
(the Lighttable plugin is IMHO even better)
Document the AST API that can be used inside macros.
Polish the module system for macros
Fix a stupid issue with hygienic macros
Fix another stupid issue with quote and unquote
We already have a lot of them
(Destructuring assignments, structure matchers, argument splicing, switch/case, many small operators...)
I should publish a module on github for them
Eventually add proper generator and coroutine support
Take structural subtyping from Typescript
Take convention on type argument names from Haskell
Put real algebraic types into the mix
Allow explicit typing of the this argument
Make everything optional, with type inference
It is damn too slow!
ES7 will likely have async for Promises
Will it ever support rx.js?
Will it ever support async machines with persistent state?
Will it ever support what you need now?
You should never wait for the ECMA committee,
browser vendors or some compiler writer
to extend your programming language
You should add the features you need to your language
It should take only a handful of lines of code
If you cannot do it,
you are using the wrong language!
code, docs and slides are on github
twitter: @M_a_s_s_i, #metascript
group: metascript@googlegroups.com