js2coffee
Version:
JavaScript to CoffeeScript compiler
438 lines (310 loc) • 10.2 kB
Markdown
Abstract Syntax Tree
====================
The CoffeeScript AST format is much pretty much exactly like JavaScript's. Only:
it has a few new node types, a few new properties in existing types, and some
unsupported ones are removed.
- New node types are always prefixed with *Coffee*, eg: `CoffeeLoopStatement`.
- New properties are always prefixed with underscore, eg: `_prefix` in
`ThisExpression`.
- Types supported in JS but not Coffee are removed, eg: `WithStatement`.
Refer to the Mozilla's [Parser API spec] for the JavaScript version.
Inspecting the syntax tree
--------------------------
In the command line, you can use the `--ast` option:
```sh
js2c file.coffee --ast
```
Programatically, just check the result's `ast` property:
```js
result = js2coffee.build(source);
console.log(result.ast);
```
An example of an AST:
```js
/* echo "alert()" | js2c --ast */
{ type: 'Program',
body:
[ { type: 'ExpressionStatement',
expression:
{ type: 'CallExpression',
callee: { type: 'Identifier', name: 'alert' },
arguments: [],
_isStatement: true } } ],
comments: [] }
```
About this document
-------------------
A few pointers on notation:
- Array properties are denoted with `[ ... ]`. (eg: `expressions` in an
[ArrayExpression])
- Optional properties are denoted with `*`, meaning they can be `null` in
some cases. (eg: `argument` of a [ReturnStatement])
Basic node types
----------------
### Statement
A block contains many statements. (eg, [IfStatement], [ExpressionStatement]).
### Expression
Fragments of a statement (eg, [ObjectExpression], [Identifier]).
Node types
----------
These are nodes available in both CoffeeScript and JavaScript.
### Program
The root node.
- `body` : [ [Statement], ... ]
### BlockStatement
A sequence of statements. Usually belongs to a loop like WhileStatement, or an
[IfStatement], or some other.
- `body` : [ [Statement], ... ]
- `_negative` : Boolean (`true` if it's `unless`)
### ExpressionStatement
A statement with one expression in it.
- `expression` : [Expression]
### Identifier
Just an identifier.
- `name` : String
### IfStatement
A conditional. This encompasses both the `if` and `else` parts.
- `test` : [Expression]
- `consequent` : [BlockStatement]
- `alternate` : [BlockStatement] *
### BreakStatement
Just `break`, for breaking out of loops. No properties.
### ContinueStatement
Just `continue`, for breaking out of loops. No properties.
### SwitchStatement
### ReturnStatement
Can have its argument missing (eg: `return`).
- `argument` : [Expression] *
### ThrowStatement
- `argument` : [Expression]
### TryStatement
A try block. Encompasses all `try`, `catch`, and `finally`.
- `block` : [BlockStatement] (the *try*)
- `handler` : [CatchClause] * (the *catch*)
- `finalizer` : [BlockStatement] * (the *finally*)
### CatchClause
A handler in a TryStatement. (eg: `catch err`)
- `param` : [Identifier]
- `body` : [BlockStatement]
### WhileStatement
### DebuggerStatement
Invokes a debugger. No properties.
### ThisExpression
Just `this`.
- `_prefix` : Boolean (true if rendered as `@`)
### ArrayExpression
- `elements` : [ [Expression], ... ] *
### ObjectExpression
- `properties` : [ [Property], ... ] *
- `_braced` : Boolean (true if braced, eg `{ a: 1 }`)
- `_last` : Boolean (true if it's the last expression in the scope)
The `_last` property is set to `true` when the expression is the last in the
scope, such as in this example. In these cases, js2coffee will omit the braces
and won't indent the object.
```js
/* assume there's nothing else in the file */
({a:2, c:3});
```
### Property
Inside [ObjectExpression].
- `kind` : "init" (not sure what this is)
- `key` : [Expression] (usually [Identifier] or [Literal])
- `value` : [Expression]
### FunctionExpression
(note: `id` is removed from function expressions.)
- `params` : [ [Identifier], ... ]
- `defaults` : [ [Identifier], ... ] ]
- `body` : [BlockStatement]
- `_parenthesized` : Boolean (true if parenthesized, eg `(-> ...)`)
### UnaryExpression
A prefix expression. Note that this *operator* also be `not`, which is not
available in JS.
- `operator` : String (eg: "void", "!")
- `argument` : [Expression]
### BinaryExpression
- `left` : [Expression]
- `operator` : String (eg: `+`)
- `right` : [Expression]
### AssignmentExpression
An assignment. Also covers shorthand like `+=`.
- `left` : [Identifier]
- `operator` : String (eg: `+=`)
- `right` : [Expression]
### UpdateExpression
An increment or decrement. (`a++`)
- `prefix` : Boolean
- `operator` : String (eg: `++`)
- `argument` : [Identifier] (eg: `a`)
### ConditionalExpression
The ternary operator. (`if a then b else c`)
- `test` : [Expression] (the *if*)
- `consequent` : [Expression] (the *then*)
- `alternate` : [Expression] (the *else*)
### NewExpression
Instanciation (eg: `new X()`).
- `callee` : [Expression] (usually an Identifier)
- `arguments` : [ [Expression], ... ]
### CallExpression
A function call.
- `callee` : [Expression] (usually an [Identifier])
- `arguments` : [ [Expression], ... ]
- `_isStatement` : Boolean (true if it has no parentheses)
### MemberExpression
Scope resolution (eg: `this.foo`).
- `computed` : Boolean (true if `a[b]`, false if `a.b`)
- `object` : [Expression] (left side)
- `property` : [Expression] (right side)
### SwitchStatement
- `discriminant` : [Expression]
- `cases` : [ [SwitchCase], ... ]
### SwitchCase
A case inside a SwitchStatement. Then `test` is not present, it's the `else`.
- `type` : ??
- `test` : [Expression] *
- `consquent` : [BlockStatement]
### Identifier
- `name` : String
### Literal
- `raw` : raw code as a string (eg: `"\"hello\""`)
- `value` : whatever the value is (eg: `hello`)
CoffeeScript-specific
---------------------
These are CoffeeScript-specific AST types:
### CoffeeListExpression
a comma-separated list (eg: `when a, b`).
- `expressions` : [ [Expression], ... ]
### CoffeePrototypeExpression
Prototype resolution operator. Similar to MemberExpression.
- `object` : [BlockStatement]
- `property` : [Expression] (usually [Identifier])
- `computed` : Boolean (*true* if `a::[b]`)
Examples:
```coffee
a::b
# { type: 'CoffeePrototypeExpression',
# object: { type: 'Identifier', name: 'a' },
# property: { type: 'Identifier', name: 'b' } }
```
### CoffeeLoopStatement
A forever loop. Compiles to `loop`.
- `body` : [BlockStatement]
Examples:
```coffee
loop
a()
# { type: 'CoffeeLoopExpression',
# body: {
# type: 'BlockStatement',
# body: { ... } }
```
### CoffeeEscapedExpression
A backtick-wrapped JS expression.
- `value` : the raw value
Example:
```coffee
`undefined`
# { type: 'CoffeeEscapedExpression',
# value: 'undefined' }
```
### CoffeeDoExpression
Represents `do -> ...`.
- `function` : [FunctionExpression]
Example:
```coffee
do -> ...
# { type: 'CoffeeDoExpression'
# function: {
# type: 'FunctionExpression'
# body: { ... } } }
```
### BlockComment
A `### ... ###` comment.
- `value` : String
### LineComment
A `# ...` comment.
- `value` : String
Only in JavaScript
------------------
These node types are not present in CoffeeScript ASTs, but are present in
JavaScript ASTs.
### SequenceExpression
turned into a sequence of [ExpressionStatement]s.
### EmptyStatement
removed from the tree.
### FunctionDeclaration
converted into `a = ->` ([AssignmentExpression]).
### VariableDeclaration
converted into `a = ->` ([AssignmentExpression]).
### VariableDeclarator
converted into `a = ->` ([AssignmentExpression]).
### WithStatement
throws an error; unsupported in CoffeeScript.
### LabeledStatement
throws an error; unsupported in CoffeeScript.
### ForStatement
Converted to [WhileStatement] loops.
### ForInStatement
Converted to [WhileStatement] loops.
### DoWhileStatement
Converted to [CoffeeLoopStatement] loops.
ES6/Harmony
-----------
### ArrowFunctionExpression
### ArrayPattern
For destructuring
### ObjectPattern
For destructuring
[Parser API spec]: https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Parser_API
[Expression]: #expression
[Statement]: #statement
[Program]: #program
[BlockStatement]: #blockstatement
[ExpressionStatement]: #expressionstatement
[Identifier]: #identifier
[IfStatement]: #ifstatement
[BreakStatement]: #breakstatement
[ContinueStatement]: #continuestatement
[SwitchStatement]: #switchstatement
[ReturnStatement]: #returnstatement
[ThrowStatement]: #throwstatement
[TryStatement]: #trystatement
[CatchClause]: #catchclause
[WhileStatement]: #whilestatement
[DebuggerStatement]: #debuggerstatement
[ThisExpression]: #thisexpression
[ArrayExpression]: #arrayexpression
[ObjectExpression]: #objectexpression
[Property]: #property
[FunctionExpression]: #functionexpression
[UnaryExpression]: #unaryexpression
[BinaryExpression]: #binaryexpression
[AssignmentExpression]: #assignmentexpression
[UpdateExpression]: #updateexpression
[ConditionalExpression]: #conditionalexpression
[NewExpression]: #newexpression
[CallExpression]: #callexpression
[MemberExpression]: #memberexpression
[SwitchStatement]: #switchstatement
[SwitchCase]: #switchcase
[Identifier]: #identifier
[Literal]: #literal
[CoffeeListExpression]: #coffeelistexpression
[CoffeePrototypeExpression]: #coffeeprototypeexpression
[CoffeeLoopStatement]: #coffeeloopstatement
[CoffeeEscapedExpression]: #coffeeescapedexpression
[CoffeeDoExpression]: #coffeedoexpression
[BlockComment]: #blockcomment
[LineComment]: #linecomment
[SequenceExpression]: #sequenceexpression
[EmptyStatement]: #emptystatement
[FunctionDeclaration]: #functiondeclaration
[VariableDeclaration]: #variabledeclaration
[VariableDeclarator]: #variabledeclarator
[WithStatement]: #withstatement
[LabeledStatement]: #labeledstatement
[ForStatement]: #forstatement
[ForInStatement]: #forinstatement
[DoWhileStatement]: #dowhilestatement
[ArrowFunctionExpression]: #arrowfunctionexpression
[ArrayPattern]: #arraypattern
[ObjectPattern]: #objectpattern