Created
September 15, 2014 22:30
-
-
Save anonymous/09d7fb45cd510f37b70f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*jshint strict:false */ | |
'use strict'; | |
function allItems() { | |
return []; | |
} | |
function print () { | |
} | |
iterate (let x, var i over allItems()) { | |
print(i, x) | |
} | |
iterate (var x, i over allItems()) { | |
print(i, x) | |
} | |
iterate (x over [1,2,3,4]) { | |
var a = x + 10; | |
print(x); | |
} | |
var d = Dict({a:1, b:2}); | |
iterate (let key: var value from d) { | |
print(key + ':' + value); | |
} | |
var Translator = {}; | |
each ( item from Translator.nextItem() ) { | |
print(item.value); | |
} | |
var typeMap = { | |
BibTeX2Zotero: Dict(), | |
Zotero2BibTeX: Dict() | |
}; | |
var items = []; | |
var x = collect ( item.id for item of items ) | |
x = collect ( item.id for item of items where item.id > 0 ) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This macro specifies the variable declaration options | |
macro $varlet { | |
rule { var } | |
rule { let } | |
} | |
// if a param is provided, remember its name and how it was declared | |
macroclass $param { | |
pattern { | |
rule { $decl:$varlet $name:ident } | |
} | |
pattern { | |
rule { $name:ident } | |
with $decl = #{} | |
} | |
} | |
/*** Object/array iterators *** | |
* if you do not declare your params, they're assumed to exist in the calling context. | |
* a 'var' declaration will hoist your var to the top of the calling context (function or global). | |
* a 'let' declaration will be contained on the block scope | |
*/ | |
macro iterate { | |
// ** iterate over an object ** | |
// iterate ([var|let]? key : [var|let]? value from object) { ... } | |
rule { ($key:$param $[:] $val:$param from $dict:expr) { $body ... } } => { | |
do { // this will contain any let statements to the block scope | |
$key$decl $key$name = null; | |
$val$decl $val$name = null; | |
let dict = $dict; | |
let keys = Object.keys(dict); | |
let length = keys.length; | |
let index = 0; | |
// a while loop is faster than a for (;;) | |
while (index < length) { | |
$key$name = keys[index]; | |
if (!dict.hasOwnProperty($key$name)) { continue; } | |
$val$name = dict[$key$name]; | |
$body... | |
index++; | |
} | |
dict = undefined; | |
keys = undefined; | |
} while (false) | |
} | |
// ** iterate over an array, with index ** | |
// iterate ([var|let]? val, [var|let]? index over array) { ... } | |
rule { ($val:$param, $idx:$param over $items:expr) { $body... } } => { | |
do { // this will contain any let statements to the block scope | |
let items = $items; | |
let length = items.length; | |
$val$decl $val$name = null; | |
$idx$decl $idx$name = 0; | |
// a while loop is faster than a for (;;) | |
while ($idx$name < length) { | |
$val$name = items[$idx$name]; | |
$body... | |
$idx$name++; | |
} | |
items = undefined; | |
} while (false) | |
} | |
// ** iterate over an array, without index ** | |
// iterate ([var|let]? val over array) { ... } | |
rule { ($val:$param over $items:expr) { $body... } } => { | |
iterate ($val$decl $val$name, var i over $items) { $body... } | |
} | |
} | |
// very specific to the Zotero generaror | |
macro each { | |
rule { ($item:ident from $generator:expr) { $body... } } => { | |
do { | |
let $item = $generator; | |
while ($item) { | |
$body... | |
$item = $generator; | |
} | |
} while (false) | |
} | |
} | |
// Dictionary 'type' that doesn't inherit all of Object's properties. | |
macro Dict { | |
// Dict initialized from an object (or another Dict) | |
rule { ($init:expr) } => { | |
// Wrapped in a function so it can be called as a simple expression | |
(function() { | |
var init = $init; | |
var dict = Object.create(null); | |
iterate (let key: let value from init) { | |
dict[key] = value | |
} | |
return dict; | |
})() | |
} | |
// Empty Dict | |
rule {()} => { Object.create(null) } | |
} | |
// Helper macro for collect | |
macro $collect { | |
rule { ($result:expr, $item:ident, $items:expr, $cond:expr) } => { | |
(function() { | |
var result = []; | |
iterate (let $item over $items) { | |
if ($cond) { | |
result.push($result); | |
} | |
} | |
return result; | |
})() | |
} | |
} | |
// array comprehensions | |
macro collect { | |
// collect (expr for item of items) | |
rule { ($($result:expr for $item:ident of $items:expr)) } => { | |
$collect($result, $item, $items, true) | |
} | |
// collect (expr for item of items where condition-for-item) | |
rule { ($($result:expr for $item:ident of $items:expr where $cond:expr)) } => { | |
$collect($result, $item, $items, $cond) | |
} | |
} | |
export iterate | |
export each | |
export Dict | |
export collect |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Yes, this is exactly what I was looking for! Been in mourning ever since array comprehension was removed from ES6.
By the way, is this macro published in npm? That would make using it so much easier!