Skip to content

Instantly share code, notes, and snippets.

Created September 15, 2014 22:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/09d7fb45cd510f37b70f to your computer and use it in GitHub Desktop.
Save anonymous/09d7fb45cd510f37b70f to your computer and use it in GitHub Desktop.
/*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 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
@me97esn
Copy link

me97esn commented Nov 5, 2014

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment