Sunday, December 30, 2012

In my last blog post I demonstrated using Gazelle to write a quick Tampermonkey script. That example necessitated an aside about the nature of operators in Gazelle. I'd like to say a bit more about that in this post and introduce a small Gazelle featurette.

Second Class Citizens

Freedom for Operators!


Most languages do something which I consider quite odd: they take a set of operations and, rather than providing them to the user as functions, with all the associated first class benefits thereof, they furnish them as mere operators. In Javascript, these benighted second-class citizens count among themselves:
+ - / * ^ % < > <= >=
And others. These operators support infix syntax, the benefits of which I believe, in accord with Lispers everywhere, are overrated, but this post is not about infix expressions. It is about the peculiar and unnecessary distinction between operators and functions. That is, in Javascript, we are unable to say something as reasonable as:
reduce(+, [1,2,3,4])
Even though nothing about the nature of + dictates that this ought to be verboden. On the contrary, given an array and a + function, this is about the most reasonable thing you could want to do with them. Why this state of affairs persists in modern programming languages I will not presently speculate.

Operators in Gazelle

The unusual status of these functions in Javascript poses a problem for Gazelle, which tries to graft a Lisp-like language onto it. In all Lisps I know of, the operations listed above are exposed to the user as plain functions, so that one can write:
(reduce + (list 1 2 3 4))
For instance. Ultimately, I feel that in day to day programming its indispensable to have basic operations be functions. Parenscript, which is otherwise a great piece of software, lets you write:
(+ 1 2 3 4)
which lulls you into a false sense of security pertaining to the nature of +, but produce code which results in an error if you write:
(apply #'+ (list 1 2 3 4))
Because + is not a function. Gazelle takes a somewhat more conservative approach. Without loading any other code, there is no + operation and you cannot write even (+ 1 2).
What you can do is refer to the underlying Javascript operator using the notation Gazelle uses for Javascript primitives, eg: _+. One can write:
(_+ 1 2)
But cannot write (_+ 1 2 3 4). Why not? Because the idea of the primitive operations is to expose, as closely as possible, the behavior of the underlying Javascript. The Javascript + operator is a binary operator, and so the Gazelle _+ operator is also one.

Getting Operator Functions in Gazelle

Because of the way that Gazelle works, you can write operator functions pretty easily, but it is a bit confusing as to what is going on, so lets go through it. Suppose we want a function denoted by + in Gazelle, which is like a Lisp + function. Here is how we might write it:
(define (+)
     (_if (_=== 0 (.. arguments length))
          ((_throw "Plus requires at least one argument.")))
     (var total [arguments 0])
     (for ((var i 1) (_< i (.. arguments length)) (set! i (_+ i 1)))
          (set! total (_+ total [arguments i])))
     total)
Where this is almost pure Javascript. This renders into the following:

    var plus = function ()  {
      if ((0===(arguments.length)))    {
        throw ("Plus requires at least one argument.");
        };
      var total = arguments[0];
      for (var i = 1;(i<(arguments.length));i = (i+1))    {
        total = (total+(arguments[i]));
        };
      return (total);
      }

Note that at the level of Javascript, the function we just defined is called plus, not +. And note that all the references to _+ in the body have been transcoded to + in Javascript. If we refer to + in Gazelle, we refer to plus in Javascript, and if we refer to _+ in Gazelle, we refer to + in Javascript. Hence, we can go about our business using + in Gazelle and everything works.

A Systematic Solution

In 'idiomatic' Gazelle, which, since I am the world's only Gazelle programmer, means however I program, one is supposed to use modules, and one of the most important modules is the operator-functions module, which defines all the common operators as functions and/or macros. One writes:
(require (("hooves/operator-functions" :all))
  (+ 1 2 3))
To use all of the definitions in the module.
Sometimes, as in the Tampermonkey code, we cannot easily use the module system, because we want to write standalone scripts. In that case you can either get by with simply using the primitive operations or you can now say:
(gazelle:essentials)
at the top of the file, which is a "built-in" macro (defined in proper.el) that expands to definitions of all the common operators. This is a reasonable solution if you need to write a standalone script or otherwise don't like the module system. Feel free to implement your own solutions. That is what Lisp is all about.

Saturday, December 29, 2012

Using Gazelle to write a Simple Greasemonkey/Tampermonkey Script


In this post I will demonstrate using Gazelle to write a Grease/Tampermonkey script to replace certain IP addresses in gmail's login history page with names, if the IP address is known to belong to a particular location.

I'm using Tampermonkey on Chrome, but I understand that the Greasemonkey script should be similar. Your mileage may vary.

Setting Up Gazelle

Gazelle is/aspires to be easy to set up.

You'll need GNU Emacs, which hosts the entire project.

You'll also need the Gazelle repository repository and shadchen-el.

you@home:~$ cd emacs-code # or wherever you put your emacs stuff
you@home:~/emacs-code$ git clone https://github.com/VincentToups/shadchen-el.git
you@home:~/emacs-code$ git clone  https://github.com/VincentToups/gazelle.git

Then, in your emacs configuration, either .emacs.d/init.el or .emacs add lines to the effect of:

(push "~/emacs-code/shadchen-el/" load-path)
(push "~/emacs-code/gazelle/" load-path)

If you want to use Gazelle you then must, at some point, (require 'gazelle).  It is very much worth byte-compiling all the Gazelle emacs lisp files, because they depend on a fair amount of macro magic and byte compiling should improve performance significantly.

What Do We Want to Do?

Gmail provides a handy feature that allows you to see what IP addresses are currently logged into your gmail account. It is the Details link at the very bottom right of one's inbox. It pops up a page that looks like this:



What we'd like to do is look at each of the td elements in the page, and if the element contains a description of an IP address we know, we want to replace the text of that element with a more descriptive name.  Here I have blacked out the IP addresses, but the lines are something to the effect of "* 000.00.00.000 (Geographic Location)".

This is a pretty simple task usinq something like jQuery, so the idea here is to show how it works in Gazelle.

Writing the Script

Create a file called name-ips-in-gmail.gazelle and put it someplace convenient. Tampermonkey scripts begin with a comment header that tells the system a few things about the script. Our script is going to use Jquery, and so the most notable line is the @require form. Comments are introduced in Gazelle via the comment form, which takes strings.

(comment "==UserScript=="
         "@name       Gazelle Example/IP Namer"
         "@namespace  http://use.i.E.your.homepage/"
         "@version    0.1"
         "@description  enter something useful"
         "@match      "
         "@require    https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"
         "@copyright  2012+, You"
         "==/UserScript==")

Now, it will be useful in this script to get the text of an html element but without the text of any sub-elements. The behavior of .text() in Jquery is the latter, rather than the former. So we define a function to do what we want:

(define (just-text element)
  (.. ($ element)
      (clone)
      (children)
      (remove)
      (end)
      (text)))

This function simply clones the element in question, removes all of its children, and then gets the text.
We will want to replace the contents of an element if it contains a particular IP address, so we need a predicate function to test for strings containing some substring.

(define (string-contains? s substring)
  (if (_> (.. s (index-of substring)) 0)
      true
    false))

In this case, we use the prim operation _> because we haven't included a function definition of >. If we want that we could write:

(define (> a b)
    (_> a b))

(See footnote 1)
When using Gazelle with modules, the hooves/operator-functions module contains function or macro definitions for the common operators (where appropriate). But here its not worth the trouble.
Now the meat of the script, a function which will be applied to each td element on the page, and which will test to see whether it should be replaced with a known location.

(define (each-fun index element)
  (var text (just-text element))
  (if (string-contains? text "000.00.000.000")
      (.. ($ element) (text "Location 1")))
  (if (string-contains? text "00.000.00.000")
      (.. ($ element) (text "Location 2")))
  (if (string-contains? text "00.00.000.000")
      (.. ($ element) (text "Location 3"))))

Obviously you will need to replace the IPs above with meaningful ones. You could also make an easier to extend implementation.

And finally we perform the action:

(.. 
 ($ "td") (each 
           each-fun))

Once we have all this in a file, we can say:

M-x gz:transcode-file

And we get this result in name-ips-in-gmail.js:
// ==UserScript==
// @name       Gazelle Example/IP Namer
// @namespace  http://use.i.E.your.homepage/
// @version    0.1
// @description  enter something useful
// @match      
// @require    https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js
// @copyright  2012+, You
// ==/UserScript==
;
var justText = function (element)  {
  return ($(element).clone().children().remove().end().text());
  };
var stringContainsPredicate = function (s, substring)  {
  return (((((s.indexOf(substring))>0))?(true) : (false)));
  };
var eachFun = function (index, element)  {
  var text = justText(element);
  ((stringContainsPredicate(text,
"***.**.***.***"))?($(element).text("Location 1")) : (undefined));
  ((stringContainsPredicate(text,
"**.***.**.***"))?($(element).text("Location 2")) : (undefined));
  return (((stringContainsPredicate(text,
"**.**.***.***"))?($(element).text("Location 3")) : (undefined)));
  };
$("td").each(eachFun);

Now simply create a new User Script in Grease or Tampermonkey and copy the .js file into it and you should be done. Congratulations, you've written your first bits of Gazelle code!

Footnote 1:

Since Gazelle is brand new, it bears discussing exactly what something like this:


(define (> a b)
    (_> a b))


really means.  This form introduces a function called `>` which, in its body, references the Javascript operator of the same name by using the symbol `_>`.   This is expanded to Javascript code like:

var greaterThan = function(a,b){ return a>b }

In Gazelle we can refer to the function `greaterThan` with the symbol `>`.  We could also restrict ourselves to uses of the operator `_>`, but the function is probably preferred, because we can map, reduce, filter, or apply with it.  Frankly, I'll never understand why modern programming languages keep to the idea that one should have these second class citizen "operators" floating around.

Wednesday, December 26, 2012

On Lisps

My recent release of Gazelle, a Javascript Lisp dialect, has, unsurprisingly, produced some commentary about my choice to implement the system in Emacs Lisp. Coincidentally, this also comes on the tail of a long (and mostly civil, I might add) discussion I had in the Lisp sub-reddit about the merits of including in our rhetorical ecosystem discussion about unusual Lisp dialects like Newlisp and Picolisp, in which I argued that its useful to discuss and even program in these dialects. Many people express strong opinions to the contrary, and while some of the objections relate to aspects of Newlisp's implementation, like One Reference Only Memory Management, to which, as a dabbler in language implementation, I cannot speak, a lot of the distaste for these dialects, and for Emacs Lisp, seems to relate to their use of dynamic scope.

Now, in general, I like my Lisps static. A lot of what I fiddle with in Lisp has to do with emulating features I like in Haskell (poorly), and Haskell hews pretty close to orthodoxy on the scope issue. My favorite Lisp is probably Racket, and the only support it provides for dynamic-like bindings is through parameters. In short, I am no fan of dynamic binding, and was delighted as anyone when Emacs Lisp began to support lexical binding natively, and would be happy to program without it in any language.

However, I do not view dynamic scope as the kiss of death like many people seem to, especially when programming in Lisp dialects. Of which more later. I'd like to make the case that perhaps, just maybe, we should think of default dynamic scope in a Lisp as a wart, rather than language nullifying feature.

Why do I feel this way?

 Well, it has something to do with Concatenative Languages.

What?

Consider the following diagram:
------------------------------------------------------
dynamicish                                   lexicish
+--------+  +--------+      +-----------+   +--------+
|factor  |  |picolisp|      |common lisp|   |haskell |
|        |  |        |      |           |   |        |
+--------+  +--------+      +-----------+   +--------+
 +--------+    +---------+        +-------+
 |joy     |    |newlisp  |        |scheme |
 |        |    |         |        |       |
 +--------+    +---------+        +-------+
Where the left hand side of each box indicates the position of the language inside on a sloppily conceived of axis going from "dynamicish" to "lexicish", ideas which we will try to pin down as we go. (If, by the way, any actual computer scientists are reading this, I apologize in advance for the conceptual butchery I am no doubt in the process of committing.)

One thing this diagram reflects is the intuitive degree to which we can depend on the nature of binding in the language - Picolisp and Newlisp here obviously favor dynamic binding, Common Lisp supports both well, Scheme favors lexical bindings somewhat more than Common Lisp, and a language like Haskell is pretty much straight lexical binding. (Exceptions abound of course, given the power of these languages to add features.)

What is interesting is that if we change the above diagram by relabling the axes:
------------------------------------------------------
code is simple data            code is not simple data
+--------+  +--------+      +-----------+   +--------+
|factor  |  |picolisp|      |common lisp|   |haskell |
|        |  |        |      |           |   |        |
+--------+  +--------+      +-----------+   +--------+
 +--------+    +---------+        +-------+
 |joy     |    |newlisp  |        |scheme |
 |        |    |         |        |       |
 +--------+    +---------+        +-------+

We don't really need to move the boxes around very much. This is particularly true if we make ourselves clearer and say that code is data when the "official" result of evaluating a piece of "code data" that represents a piece of code is encodable in that data in a simple form. Examples will clarify that horrible monster of a sentence, hopefully.

Concatenative Languages and Quotations

Put aside for the moment the oddness of concatenative languages, and questions which may be appearing in your mind about why anyone would want to program in one. The point here isn't to convince you of their merits. The point is that concatenative languages (except Forth), as it lacks quotations) provide an example of languages where "code is data" is particularly true, and where that data is particularly simple while still retaining a consistent meaning.
Concatenative languages are based on the composition of functions which map one stack onto another stack (usually). Because all functions in such languages have the same interface, one writes a concatenative program as a list of functions, as in this piece of Factor code:

1 1 +

Which evaluates to "2" and is read from left to right as "take the stack and return it with 1 pushed onto it", do that again, and then "take the stack, return a new stack with the result of the first two items removed and added together". Note the utter absence of variable bindings (functions do have names, of course). This (arguably punishing) simplicity makes evaluation unusually simple: begin at the left with an empty stack, and call each "word" on the stack until you run out of functions. We can represent a program as a flat list of lexemes, each of which denotes a function. So the representation of code can be a list and its meaning is simple.

Here is what is interesting about these languages to me: they lack a notion of variable binding, and so you might think they they lack anonymous functions, which they do, strictly speaking. However, because code is easily represented as a list, lists serve the same role as anonymous functions and in languages like Factor, these fragments of code (called quotations because they are introduced via something like quote in Lisps) are constantly exploited to perform the equivalent of "functional programming" idioms in Factor. For instance, to add one to each number in a list of numbers, one writes in Factor:

{ 1 2 3 } [ 1 + ] map

Or, less succinctly, but more evocatively:

{ 1 2 3 } 1 [ + ] curry map

Where I have just shown that one can curry, really, partially apply, and compose (not illustrated) quotations.

The question one must ask is what do we really need for functional programming? We must be able to apply functions, compose them, and partially apply them. Many, but not all, uses of lexical scope in more lexical languages reduce transparently to these operations. We might write in Scheme:

(map (curry + 1) (list 1 2 3))

For instance, with (a simple) curry being implemented as:

(define (curry f a)
  (lambda (b) (f a b)))

Where we are exploiting the lexical scope introduced by curry to stick two values into the lambda.
In a dynamic Lisp, we might say instead, as I often say in Emacs Lisp when I don't want to engage the machinery of the old lexical-let implementation in cl.el:

(defun curry (f a)
 `(lambda (b) (funcall #',f ,a)))

Code is Sort of Data

Factor uses a special data type called a quotation for its, um, quotations, but this has more to do with type safety and compiltion than with the semantics of what a quotation is. It is still basically a list, so let us imagine that the implementation of the curry word is:

: curry ( item quotation -- quotations ) cons ;

That is, effectively, curry is cons. It adds an element to the front of a list.
Now, the dynamic, Emacs Lisp version

(defun curry (f a)
 `(lambda (b) (funcall #',f ,a))) ; thanks to coroi on reddit 
for pointing out an error 
                                  ; here. 

Has something in common with the Factor version. They both operate on and return a simple representation of code, a list. The extra complexity of Emacs Lisp lies in its evaluator. For instance:

(funcall (curry #'+ 1) 1)

is evaluated in the following way: the call to curry is evaluated, returning a list. 1 evaluates to 1, of course, and then funcall does the following. The evaluator can see that the first argument is a lambda because its head is lambda. That means that it extends the dynamic environment with a binding of 1 to b, and then recursively evaluates the body. That means the evaluator is carrying around an environment which it needs to resolve the meaning of code. Still, its pretty simple: just (conceptually) a list of stacks for each possible variable binding with the latest binding on the tops.

The Scheme code, in contrast:

(define (curry f a)
 (lambda (b) (f a b)))

Doesn't deal with any simple data structure. f is a procedure, and its representation is complex, hidden and has a lot to do with compiling the Scheme code, probably. The return value, as the result of a lambda expression, is also a procedure, and similarly inscrutible. The compiler probably does some efficient fiddling to encode in the lambda itself where the references f and a point to: in all likelihood, the compiled code removes the mention of specific symbols entirely. Even though the lambda represents a piece of code in some sense, as it is executable, its representation is now quite complicated. We can still say "Code is data" of Scheme lambda expressions, but it is not very transparent or interesting data.

What about Quotations?

In Factor, quotations and lambdas are the same thing, because there are no symbols to bind in any scopes. Higher order functions and macros are basically the same!
In Emacs Lisp quotations are pretty close to lambdas too: if they happen to have as their head a lambda, then they are, subject to some constraints, actually lambda expressions. If not, you can still call eval on them and if all of their free symbols are located in the dynamic environment that you call eval from, then you get a "meaningful" result. In picolisp, where this philosophy is entirely embraced, one can write higher order functions that do the same thing as macros because they can inspect code passed in.

In Scheme, a quotation introduces syntax, primarily because you want to use quotation during macro construction and hygienic macros need to know more than just the list-structure of the code they work on to ensure hygiene. So already the representation of code in just a quotation is more complicated. This is the primary reason that Scheme is "more staticy/lexical" than Common Lisp, in which a quotation really does produce just a regular list. Scheme wants to ensure macro hygeine, and for that reason static or lexical concerns must even enter into your primary code represantation. In Common Lisp there is a macro system which is distinct from the function system, but allows you to use regular list operations to build the generated code. In Scheme the macro system is somewhat more cumbersome conceptually, with special operations on "syntax" objects to enforce lexical hygeine. Complexity has crawled deep into the language.

Finally, in a language like Haskell, you don't really have quotations at all. The representation of any kind of code has become fairly complex and generally not worth fiddling with (template metahaskell aside).

What does this mean?

The point of the above discussion is twofold:
  1. Languages lie on a continuum between dynamic and static and that positions on that continuum have complexity and flexibility payoffs and penalties. The very dynamic languages pick up a lot of flexibility (which is good and bad) and the static languages pick up a lot of complexity, but get certain conceptual guarantees and speed in exchange.
  2. Especially in Lisps, which provide facilities for meta-programming, this distinction isn't extremely important. Heck, even Factor has an implementation of lambda with lexically scoped variables that compiles down to stack code. Emacs Lisp has a lexical-let form that gets you 99% of what you want. Specific features of closures that you need at any given moment can easily be built in dynamic lisps. If you want to program functionally, for instance, you can whip up good curry and compose operations in any of these languages and away you go.
I can't find the reference at the moment, but I recall reading from one of the Factor maintainer's that they use lexical variables in less than ten percent of the Factor code base. I suspect if you examine any large Lisp project you will find that for the most part the actual use of the semantics of lexical scope is small.
There is absolutely an argument to be made that dynamic scope introduces certain kinds of hard to find bugs, and I agree with that assessment. I don't think dynamic scope is optimal by any means, but the case against it is somewhat overstated. A dynamically scoped Lisp is still extremely powerful and in some ways more flexible than an efficiently compiled lexical lisp.

Actual Code

I work hard on making my Emacs Lisp code readable and clear, and so I wanted to show a bit of the implementation of Gazelle here, to drive the point home that in a Lisp the exact feature set under the hood doesn't make as big of a difference as it might seem.

(defun-match- prim:transcode ('_false)
  (prim:insert "false"))

(defun-match prim:transcode ('_true)
  (prim:insert "true"))

(defun-match prim:transcode ('_null)
  (prim:insert "null"))

(defun-match prim:transcode ('_undefined)
  (prim:insert "undefined"))

(defun-match prim:transcode ((non-kw-symbol s))
  (prim:insert (prim:mangle s)))

(defun-match prim:transcode ((keyword k))
  (prim:insert "\"")
  (prim:insert (prim:mangle (prim:kw->symbol k)))
  (prim:insert "\""))

(defun-match prim:transcode ((number n))
  (prim:insertf "%s" n))

(defun prim:transcode-string (string)
  (prim:insert "\"")
  (loop for character in (coerce string 'list) do
        (match character
               (?\n (insert "\\n"))
               (?\t (insert "\\t"))
               (?\" (insert "\\\""))
               (?\\ (insert "\\"))
               (else (insert else))))
  (prim:insert "\""))

(defun-match prim:transcode ((string s))
  (prim:transcode-string  s))

(defun-match prim:transcode ((list '_var (non-kw-symbol s) expr))
  (prim:insert "var ")
  (prim:transcode s)
  (prim:insert " = ")
  (prim:transcode expr))

(defun-match prim:transcode 
       ((list '_return 
              (list (and which 
                    (or '_for '_while '_try '_var '_=)) (tail body))))
  (recur `(,which ,@body)))

(defun-match prim:transcode 
       ((list '_return 
              (list 
               (and which (or '_throw '_continue '_break)) expression)))
  (recur `(,which ,expression)))

(defun-match prim:transcode ((list '_return expression))
  (prim:insert "return ")
  (prim:in-parens 
   (prim:transcode expression)))

This is a small excerpt from the prim module, which converts a primitive representation of Javascript in s-expressions to Javascript source code. That transcoder consists of one large function definition, split up into several invocations of defun-match (the initial defun-match- clears previous function bindings to the provided function name), each of which matches its pattern against the input and executes when the match succeeds. Matches are tried in the order in which the defun-match forms are compiled, in most cases from top to bottom. defun-match allows you to tail-recur to the same function without growing the stack, so in many cases (two shown above), prim:transcode calls itself to perform the actual transcoding.

I can only ultimately speak for myself, but I find that this code is clear, readable (once you get used to the pattern matching) and self documenting. If you can write code like this in Emacs Lisp, is it really such a crime to do so?

And given that by really thinking about the different ways to program in different Lisp and Lisp-like languages we can learn a great deal about programming, even in our favorite dialects, is it really useful to stifle conversation and development in alternative Lisps?
I really don't think so.

Monday, December 24, 2012

Introducing Gazelle!

Happy Holidays everyone! I made you all a present:

We all want Mhorr Gazelle.


Gazelle is a rewrite of an aborted project, jsel, which aims to be a sensible Lisp for Javascript. By "sensible" I mean it adheres to the following ideas:
  1. Be yourself: Gazelle doesn't try to be or imitate another Lisp. It is based on an s-expression representation of javascript itself and the base idioms of the language are the base idioms of javascript. Any other idioms are meant to be added via the macro system.
  2. Stay Organized: Despite the above, Gazelle has a few built in extensions to the basic Javascript paradigm. One of them is a module system for both static and dynamic (macros and run-time values) objects, based on require.js
  3. I never metaprogram I didn't like. That is, be a Lisp: Gazelle provides a powerful macroexpansion language (Emacs Lisp + shadchen) which transforms a s-expression representation of javascript before the s-expression to javascript compiler is invoked. The idea behind Lisps is extension of the base language, so Gazelle exposes javascript for extension.
Unsensibly, Gazelle is written in Emacs Lisp. I'll port it to Common Lisp eventually.

Getting Started

You'll need GNU Emacs, which hosts the entire project.
You'll also need this repository and shadchen-el.

you@home:~$ cd emacs-code # or wherever you put your emacs stuff
you@home:~/emacs-code$ git clone https://github.com/VincentToups/shadchen-el.git
you@home:~/emacs-code$ git clone  https://github.com/VincentToups/gazelle.git

Then, in your emacs configuration, either .emacs.d/init.el or .emacs add lines to the effect of:

(push "~/emacs-code/shadchen-el/" load-path)
(push "~/emacs-code/gazelle/" load-path)

If you want to use Gazelle you then must, at some point, (require 'gazelle). (I recommend byte-compiling all the parts of Gazelle - there is some pretty heavy macro magic involved.)
Gazelle can be used in two ways. The first is the simplest, the function gz:transcode-file takes the contents of a .gazelle file and outputs a .js file with the same filename in the same directory. (Optionally, an alternative output file name can be specified.) One could develop their Javascript project in separate files this way and never used Gazelle's module system. However, the module system provides powerful features for code organization.

Quick Syntax Notes

Gazelle is like Javascript but provides some thin wrappers on Javascript ideas.
Dotted symbols are supported, so you can write.
(console.log "Hello World")
You can also write
(.. console (log "Hello World"))
The former expands into the latter.
Arrays are constructed using the following syntax:
[: a b c d]
The ":" is required, because
[an-array 3]
represents the Javascript
anArray[3]
Objects are denoted via:
(var object ({} x 10 y 11})
Object indexing is either
object.x
or
[object "x"]
For loops are written in the expected way, translated to s-expressions:
(for (i :in array-thing)
     (do-something [array-thing i]))
They do not return a value.
if expands to the ternary conditional. Eg:
(if cond e1 e2)
is
(cond ? e1 : e2)
One can write a "flat" if using the primitive if, eg;
(_if cond (true-branch0 true-branch ...)
          (false-branch0 false-branch))
This does not produce a value. The code in prim is quite readable, and proper, for the most part, provides non-underscored versions of many primitive operations.

Using Modules

Gazelle's module system is based on require.js, with extensions and provisions for the fact that Gazelle has both run-time and compile-time entities which it needs to scope to modules. To use the system, you must set up your project directory as in the require.js documentation. Gazelle also needs to know about the location of your project directory. It can find out about this in two ways. The first is to type
M-x gz:set-project-directory
And then enter the scripts directory for your project. The alternative is to do nothing, and the first time Gazelle needs to use the project directory, it will ask for one. Afterward, if need to set the project directory, use the above command.
Your page should look like the require.js example page, eg:
<!DOCTYPE html>
<html>
    <head>
        <title>My Sample Project</title>
        <!-- data-main attribute tells require.js to load
             scripts/main.js after require.js loads. -->
        <script data-main="scripts/main" src="scripts/require.js"></script>
    </head>
    <body>
        <h1>My Sample Project</h1>
    </body>
</html>
And your entry point should be in scripts/main.gazelle. And it should look something like this:
(require 
 (("hooves/operator-functions" :all)
  ("hooves/lisp-idioms" (:with-prefix idioms- :all))
  ("jquery/jquery" (:as $)))
 (_+ 1 1)
 (var x 10)
 (incr x)
 (console.log (_+ "X minus one is " (- x 1)))
 (console.log (+ "7 < 10" (< 7 10)))
 (console.log (+ "7 > 10" (> 7 10)))
 (console.log (+ "using idioms- " (idioms-apply + [: 1 2])))
 (.. ($ "body") (append "Hello World.")) 
 (+ 1 2))
Here we have just a simple example to demonstrate the module syntax. require is a special form which compiles to a call to the require.js function call of the same name (how to do this is explained in the manual).
The syntax is
(require <list-of-module/import-specifiers> body0 body ...)
Each module import specifier is of the form
(<module designator string> import-directives)
An import directive is one of
(:as import-mapping)

:all

(:with-prefix prefix import-directive)
An import mapping is one of
a symbol

a list with one symbol

a list with two symbols
The meaning of a single symbol is to take the external symbol in the imported module and map it onto a local symbol. The list with a single symbol has the same meaning. When two symbols are present, the first designates the name of an entity in the module and the second designates the local name.
An :all import directive imports all external entities from the module to identical names in the current module.
:with-prefix is a kind of import directive modifier. It expands the inner import directive and then prefixes all the local names with the indicated prefix. So in our example, the lisp-idioms module exports symbols funcall and apply. The ("hooves/lisp-idios" (:with-prefix idioms- :all)) creates module local bindings idioms-funcall and idioms-apply.
Local bindings to values in an imported module are not actual variables, but symbol macros, so you can set! them at get the appropriate behavior. That is, if a value is referenced inside a module, and it is imported into another module, expressions in both modules refer to the same Javascript object.
Once you have your main.gazelle and your modules, simple perform a gz:transcode-file on main.gazelle. This will transcode all of the files via the module system. Module transcoding is cached against the md5 hash of the module file, so if you change the module, the next recompile of main.gazelle with force a recompile of the module too, but unnecessary module recompilation is avoided. You can reset the cache by
M-x proper:reset-module-cache
In this way the module system doubles as the build system.
Here is an example of a module file (located at hooves/lisp-idioms.gazelle):
(module 
 ()
 ;; lisp-idioms 
 ;; this module defines funcall and apply
 (define+ (apply f an-array)
   (.. f (apply undefined an-array)))
 (define+ (funcall f (tail args))
   (apply f args)))
Inside a module, define defines local module values or functions, and define-macro defines local macros. define+ defines an external function or value and define-macro+ defines an external macro.
define is like define in Scheme, in the sense that it can define either functions or values, except that any place an argument symbol can be used, you can specify a shadchen-like pattern. To collect any additional arguments into an array, use the pattern (tail tl) in the argument list.  define produces functions which automatically return the value of the last expression in their body, if that makes sense.  You can define plain Javascript functions by using the primitive form _function.

How it Works

Gazelle is made up of several parts. The prim module (for primitive) is a transcoder that takes an s-expression representation of all of Javascript's primitives and transcodes them to Javascript itself. For instance,
(_function (arg-one arg-two) (_return (_+ arg-one arg-two)))
Is a valid prim expression which transcodes to:
(function(argOne, argTwo) { return (argOne+argTwo); })
Generally speaking, prim is simple to understand. Each javascript primitive is assigned a symbol beginning with an underscore, and that is transcoded in a straightforward manner to Javascript.
Prim does not support your familiar Lisp idioms, though they are in Gazelle itself. Prim has just one interface, the emacs lisp function prim:transcode, which inserts the transcoded representation of its input argument into the current buffer. Generally, you won't need to worry about this.
The module proper is where most of the heavy lifting of Gazelle takes place. Despite this fact, Proper is fairly simple, amounting to slightly more than the construction of a macro system on top of prim. That means that almost all special forms in proper and therefore in Gazelle itself are implemented as regular macros. Proper implements a lexically scoped, static macro system, which means that it is possible, but not typical to, to shadow special forms in limited contexts. There is also a symbol macro system, which is partially exposed and used "under the hood" to implement advanced features.
In the course of typical compilation, proper macros can expand to additional macro definitions and the behavior is consistent. Code is passed through multiple compilation passes until it reduces entirely to prim operations.
Proper has several entry points because it needs to know about the one advanced feature in Gazelle which is not in Javascript itself, modules, of which more later.

Gazelle is available at my github.  Along with a lot of other cool/ill conceived stuff