mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
added the ability to print the parse tree
This commit is contained in:
parent
950d1199c2
commit
7c01bba4f4
6 changed files with 92 additions and 10 deletions
|
@ -33,6 +33,10 @@
|
|||
exports.tokenize = function tokenize(code) {
|
||||
return lexer.tokenize(code);
|
||||
};
|
||||
// Just the nodes.
|
||||
exports.tree = function tree(code) {
|
||||
return parser.parse(lexer.tokenize(code));
|
||||
};
|
||||
//---------- Below this line is obsolete, for the Ruby compiler. ----------------
|
||||
// Executes the `coffee` Ruby program to convert from CoffeeScript to JavaScript.
|
||||
path = require('path');
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
posix = require('posix');
|
||||
coffee = require('coffee-script');
|
||||
BANNER = "coffee compiles CoffeeScript source files into JavaScript.\n\nUsage:\n coffee path/to/script.coffee";
|
||||
SWITCHES = [['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-r', '--run', 'compile and run a CoffeeScript'], ['-o', '--output [DIR]', 'set the directory for compiled JavaScript'], ['-w', '--watch', 'watch scripts for changes, and recompile'], ['-p', '--print', 'print the compiled JavaScript to stdout'], ['-l', '--lint', 'pipe the compiled JavaScript through JSLint'], ['-e', '--eval', 'compile a cli scriptlet or read from stdin'], ['-t', '--tokens', 'print the tokens that the lexer produces'], ['-n', '--no-wrap', 'raw output, no function safety wrapper'], ['-g', '--globals', 'attach all top-level variables as globals'], ['-v', '--version', 'display CoffeeScript version'], ['-h', '--help', 'display this help message']];
|
||||
SWITCHES = [['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-r', '--run', 'compile and run a CoffeeScript'], ['-o', '--output [DIR]', 'set the directory for compiled JavaScript'], ['-w', '--watch', 'watch scripts for changes, and recompile'], ['-p', '--print', 'print the compiled JavaScript to stdout'], ['-l', '--lint', 'pipe the compiled JavaScript through JSLint'], ['-e', '--eval', 'compile a cli scriptlet or read from stdin'], ['-t', '--tokens', 'print the tokens that the lexer produces'], ['--tree', 'print the parse tree that Jison produces'], ['-n', '--no-wrap', 'raw output, no function safety wrapper'], ['-g', '--globals', 'attach all top-level variables as globals'], ['-v', '--version', 'display CoffeeScript version'], ['-h', '--help', 'display this help message']];
|
||||
WATCH_INTERVAL = 0.5;
|
||||
// The CommandLine handles all of the functionality of the `coffee` utility.
|
||||
exports.run = function run() {
|
||||
|
@ -53,16 +53,17 @@
|
|||
}
|
||||
opts = this.options;
|
||||
return posix.cat(source).addCallback(function(code) {
|
||||
var js;
|
||||
if (opts.tokens) {
|
||||
return puts(coffee.tokenize(code).join(' '));
|
||||
}
|
||||
js = coffee.compile(code);
|
||||
if (opts.tree) {
|
||||
return puts(coffee.tree(code).toString());
|
||||
}
|
||||
if (opts.run) {
|
||||
return eval(js);
|
||||
return eval(coffee.compile(code));
|
||||
}
|
||||
if (opts.print) {
|
||||
return puts(js);
|
||||
return puts(coffee.compile(code));
|
||||
}
|
||||
return exports.compile_scripts();
|
||||
});
|
||||
|
@ -98,6 +99,9 @@
|
|||
oparser.add('tokens', function() {
|
||||
return opts.tokens = true;
|
||||
});
|
||||
oparser.add('tree', function() {
|
||||
return opts.tree = true;
|
||||
});
|
||||
oparser.add('help', (function(__this) {
|
||||
var __func = function() {
|
||||
return this.usage();
|
||||
|
|
|
@ -185,6 +185,19 @@
|
|||
}
|
||||
return false;
|
||||
};
|
||||
// toString representation of the node, for inspecting the parse tree.
|
||||
Node.prototype.toString = function toString(idt) {
|
||||
var __a, __b, __c, child;
|
||||
idt = idt || '';
|
||||
return (this.type || 'anon') + "\n" + ((function() {
|
||||
__a = []; __b = this.children;
|
||||
for (__c = 0; __c < __b.length; __c++) {
|
||||
child = __b[__c];
|
||||
__a.push(idt + TAB + child.toString(idt + TAB));
|
||||
}
|
||||
return __a;
|
||||
}).call(this));
|
||||
};
|
||||
// Default implementations of the common node methods.
|
||||
Node.prototype.unwrap = function unwrap() {
|
||||
return this;
|
||||
|
@ -201,6 +214,7 @@
|
|||
};
|
||||
// A collection of nodes, each one representing an expression.
|
||||
Expressions = (exports.Expressions = inherit(Node, {
|
||||
type: 'Expressions',
|
||||
constructor: function constructor(nodes) {
|
||||
this.children = (this.expressions = compact(flatten(nodes)));
|
||||
return this;
|
||||
|
@ -310,6 +324,7 @@
|
|||
// Literals are static values that can be passed through directly into
|
||||
// JavaScript without translation, eg.: strings, numbers, true, false, null...
|
||||
LiteralNode = (exports.LiteralNode = inherit(Node, {
|
||||
type: 'Literal',
|
||||
constructor: function constructor(value) {
|
||||
this.value = value;
|
||||
return this;
|
||||
|
@ -329,6 +344,7 @@
|
|||
LiteralNode.prototype.is_statement_only = LiteralNode.prototype.is_statement;
|
||||
// Return an expression, or wrap it in a closure and return it.
|
||||
ReturnNode = (exports.ReturnNode = inherit(Node, {
|
||||
type: 'Return',
|
||||
constructor: function constructor(expression) {
|
||||
this.children = [(this.expression = expression)];
|
||||
return this;
|
||||
|
@ -345,6 +361,7 @@
|
|||
statement(ReturnNode, true);
|
||||
// A value, indexed or dotted into, or vanilla.
|
||||
ValueNode = (exports.ValueNode = inherit(Node, {
|
||||
type: 'Value',
|
||||
SOAK: " == undefined ? undefined : ",
|
||||
constructor: function constructor(base, properties) {
|
||||
this.children = flatten((this.base = base), (this.properties = (properties || [])));
|
||||
|
@ -413,6 +430,7 @@
|
|||
// Pass through CoffeeScript comments into JavaScript comments at the
|
||||
// same position.
|
||||
CommentNode = (exports.CommentNode = inherit(Node, {
|
||||
type: 'Comment',
|
||||
constructor: function constructor(lines) {
|
||||
this.lines = lines;
|
||||
return this;
|
||||
|
@ -427,6 +445,7 @@
|
|||
// Node for a function invocation. Takes care of converting super() calls into
|
||||
// calls against the prototype's function of the same name.
|
||||
CallNode = (exports.CallNode = inherit(Node, {
|
||||
type: 'Call',
|
||||
constructor: function constructor(variable, args) {
|
||||
this.children = flatten([(this.variable = variable), (this.args = (args || []))]);
|
||||
this.prefix = '';
|
||||
|
@ -501,6 +520,7 @@
|
|||
// Node to extend an object's prototype with an ancestor object.
|
||||
// After goog.inherits from the Closure Library.
|
||||
ExtendsNode = (exports.ExtendsNode = inherit(Node, {
|
||||
type: 'Extends',
|
||||
constructor: function constructor(child, parent) {
|
||||
this.children = [(this.child = child), (this.parent = parent)];
|
||||
return this;
|
||||
|
@ -518,6 +538,7 @@
|
|||
// A dotted accessor into a part of a value, or the :: shorthand for
|
||||
// an accessor into the object's prototype.
|
||||
AccessorNode = (exports.AccessorNode = inherit(Node, {
|
||||
type: 'Accessor',
|
||||
constructor: function constructor(name, tag) {
|
||||
this.children = [(this.name = name)];
|
||||
this.prototype = tag === 'prototype';
|
||||
|
@ -530,6 +551,7 @@
|
|||
}));
|
||||
// An indexed accessor into a part of an array or object.
|
||||
IndexNode = (exports.IndexNode = inherit(Node, {
|
||||
type: 'Index',
|
||||
constructor: function constructor(index) {
|
||||
this.children = [(this.index = index)];
|
||||
return this;
|
||||
|
@ -540,6 +562,7 @@
|
|||
}));
|
||||
// A this-reference, using '@'.
|
||||
ThisNode = (exports.ThisNode = inherit(Node, {
|
||||
type: 'This',
|
||||
constructor: function constructor(property) {
|
||||
this.property = property || null;
|
||||
return this;
|
||||
|
@ -551,6 +574,7 @@
|
|||
// A range literal. Ranges can be used to extract portions (slices) of arrays,
|
||||
// or to specify a range for list comprehensions.
|
||||
RangeNode = (exports.RangeNode = inherit(Node, {
|
||||
type: 'Range',
|
||||
constructor: function constructor(from, to, exclusive) {
|
||||
this.children = [(this.from = from), (this.to = to)];
|
||||
this.exclusive = !!exclusive;
|
||||
|
@ -594,6 +618,7 @@
|
|||
// specifies the index of the end of the slice (just like the first parameter)
|
||||
// is the index of the beginning.
|
||||
SliceNode = (exports.SliceNode = inherit(Node, {
|
||||
type: 'Slice',
|
||||
constructor: function constructor(range) {
|
||||
this.children = [(this.range = range)];
|
||||
return this;
|
||||
|
@ -608,6 +633,7 @@
|
|||
}));
|
||||
// An object literal.
|
||||
ObjectNode = (exports.ObjectNode = inherit(Node, {
|
||||
type: 'Object',
|
||||
constructor: function constructor(props) {
|
||||
this.objects = (this.properties = props || []);
|
||||
return this;
|
||||
|
@ -652,6 +678,7 @@
|
|||
}));
|
||||
// An array literal.
|
||||
ArrayNode = (exports.ArrayNode = inherit(Node, {
|
||||
type: 'Array',
|
||||
constructor: function constructor(objects) {
|
||||
this.children = (this.objects = objects || []);
|
||||
return this;
|
||||
|
@ -706,6 +733,7 @@
|
|||
});
|
||||
// Setting the value of a local variable, or the value of an object property.
|
||||
AssignNode = (exports.AssignNode = inherit(Node, {
|
||||
type: 'Assign',
|
||||
PROTO_ASSIGN: /^(\S+)\.prototype/,
|
||||
LEADING_DOT: /^\.(prototype\.)?/,
|
||||
constructor: function constructor(variable, value, context) {
|
||||
|
@ -809,6 +837,7 @@
|
|||
// A function definition. The only node that creates a new Scope.
|
||||
// A CodeNode does not have any children -- they're within the new scope.
|
||||
CodeNode = (exports.CodeNode = inherit(Node, {
|
||||
type: 'Code',
|
||||
constructor: function constructor(params, body, tag) {
|
||||
this.params = params;
|
||||
this.body = body;
|
||||
|
@ -854,6 +883,7 @@
|
|||
// A splat, either as a parameter to a function, an argument to a call,
|
||||
// or in a destructuring assignment.
|
||||
SplatNode = (exports.SplatNode = inherit(Node, {
|
||||
type: 'Splat',
|
||||
constructor: function constructor(name) {
|
||||
this.children = [(this.name = name)];
|
||||
return this;
|
||||
|
@ -874,6 +904,7 @@
|
|||
// A while loop, the only sort of low-level loop exposed by CoffeeScript. From
|
||||
// it, all other loops can be manufactured.
|
||||
WhileNode = (exports.WhileNode = inherit(Node, {
|
||||
type: 'While',
|
||||
constructor: function constructor(condition, body) {
|
||||
this.children = [(this.condition = condition), (this.body = body)];
|
||||
return this;
|
||||
|
@ -906,6 +937,7 @@
|
|||
// Simple Arithmetic and logical operations. Performs some conversion from
|
||||
// CoffeeScript operations into their JavaScript equivalents.
|
||||
OpNode = (exports.OpNode = inherit(Node, {
|
||||
type: 'Op',
|
||||
CONVERSIONS: {
|
||||
'==': '===',
|
||||
'!=': '!==',
|
||||
|
@ -989,6 +1021,7 @@
|
|||
}));
|
||||
// A try/catch/finally block.
|
||||
TryNode = (exports.TryNode = inherit(Node, {
|
||||
type: 'Try',
|
||||
constructor: function constructor(attempt, error, recovery, ensure) {
|
||||
this.children = [(this.attempt = attempt), (this.recovery = recovery), (this.ensure = ensure)];
|
||||
this.error = error;
|
||||
|
@ -1009,6 +1042,7 @@
|
|||
statement(TryNode);
|
||||
// Throw an exception.
|
||||
ThrowNode = (exports.ThrowNode = inherit(Node, {
|
||||
type: 'Throw',
|
||||
constructor: function constructor(expression) {
|
||||
this.children = [(this.expression = expression)];
|
||||
return this;
|
||||
|
@ -1020,6 +1054,7 @@
|
|||
statement(ThrowNode, true);
|
||||
// Check an expression for existence (meaning not null or undefined).
|
||||
ExistenceNode = (exports.ExistenceNode = inherit(Node, {
|
||||
type: 'Existence',
|
||||
constructor: function constructor(expression) {
|
||||
this.children = [(this.expression = expression)];
|
||||
return this;
|
||||
|
@ -1042,6 +1077,7 @@
|
|||
};
|
||||
// An extra set of parentheses, specified explicitly in the source.
|
||||
ParentheticalNode = (exports.ParentheticalNode = inherit(Node, {
|
||||
type: 'Paren',
|
||||
constructor: function constructor(expressions) {
|
||||
this.children = [(this.expressions = expressions)];
|
||||
return this;
|
||||
|
@ -1061,6 +1097,7 @@
|
|||
// of the comprehenion. Unlike Python array comprehensions, it's able to pass
|
||||
// the current index of the loop as a second parameter.
|
||||
ForNode = (exports.ForNode = inherit(Node, {
|
||||
type: 'For',
|
||||
constructor: function constructor(body, source, name, index) {
|
||||
var __a;
|
||||
this.body = body;
|
||||
|
@ -1161,6 +1198,7 @@
|
|||
// Single-expression IfNodes are compiled into ternary operators if possible,
|
||||
// because ternaries are first-class returnable assignable expressions.
|
||||
IfNode = (exports.IfNode = inherit(Node, {
|
||||
type: 'If',
|
||||
constructor: function constructor(condition, body, else_body, tags) {
|
||||
this.condition = condition;
|
||||
this.body = body && body.unwrap();
|
||||
|
|
|
@ -27,6 +27,10 @@ exports.compile: (code) ->
|
|||
exports.tokenize: (code) ->
|
||||
lexer.tokenize code
|
||||
|
||||
# Just the nodes.
|
||||
exports.tree: (code) ->
|
||||
parser.parse lexer.tokenize code
|
||||
|
||||
|
||||
#---------- Below this line is obsolete, for the Ruby compiler. ----------------
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ SWITCHES: [
|
|||
['-l', '--lint', 'pipe the compiled JavaScript through JSLint']
|
||||
['-e', '--eval', 'compile a cli scriptlet or read from stdin']
|
||||
['-t', '--tokens', 'print the tokens that the lexer produces']
|
||||
[ '--tree', 'print the parse tree that Jison produces']
|
||||
['-n', '--no-wrap', 'raw output, no function safety wrapper']
|
||||
['-g', '--globals', 'attach all top-level variables as globals']
|
||||
['-v', '--version', 'display CoffeeScript version']
|
||||
|
@ -62,9 +63,9 @@ exports.compile_scripts: ->
|
|||
opts: @options
|
||||
posix.cat(source).addCallback (code) ->
|
||||
return puts coffee.tokenize(code).join(' ') if opts.tokens
|
||||
js: coffee.compile code
|
||||
return eval js if opts.run
|
||||
return puts js if opts.print
|
||||
return puts coffee.tree(code).toString() if opts.tree
|
||||
return eval coffee.compile code if opts.run
|
||||
return puts coffee.compile code if opts.print
|
||||
exports.compile_scripts()
|
||||
|
||||
|
||||
|
@ -82,6 +83,7 @@ exports.parse_options: ->
|
|||
oparser.add 'lint', -> opts.lint: true
|
||||
oparser.add 'eval', -> opts.eval: true
|
||||
oparser.add 'tokens', -> opts.tokens: true
|
||||
oparser.add 'tree', -> opts.tree: true
|
||||
oparser.add 'help', => @usage()
|
||||
oparser.add 'version', => @version()
|
||||
|
||||
|
|
|
@ -58,8 +58,8 @@ inherit: (parent, props) ->
|
|||
|
||||
# Mark a node as a statement, or a statement only.
|
||||
statement: (klass, only) ->
|
||||
klass::is_statement: -> true
|
||||
(klass::is_statement_only: -> true) if only
|
||||
klass::is_statement: -> true
|
||||
(klass::is_statement_only: -> true) if only
|
||||
|
||||
# The abstract base class for all CoffeeScript nodes.
|
||||
# All nodes are implement a "compile_node" method, which performs the
|
||||
|
@ -103,6 +103,11 @@ Node::contains: (block) ->
|
|||
return true if node instanceof Node and node.contains block
|
||||
false
|
||||
|
||||
# toString representation of the node, for inspecting the parse tree.
|
||||
Node::toString: (idt) ->
|
||||
idt ||= ''
|
||||
(@type || 'anon') + "\n" + (idt + TAB + child.toString(idt + TAB) for child in @children)
|
||||
|
||||
# Default implementations of the common node methods.
|
||||
Node::unwrap: -> this
|
||||
Node::children: []
|
||||
|
@ -112,6 +117,7 @@ Node::top_sensitive: -> false
|
|||
|
||||
# A collection of nodes, each one representing an expression.
|
||||
Expressions: exports.Expressions: inherit Node, {
|
||||
type: 'Expressions'
|
||||
|
||||
constructor: (nodes) ->
|
||||
@children: @expressions: compact flatten nodes
|
||||
|
@ -193,6 +199,7 @@ statement Expressions
|
|||
# Literals are static values that can be passed through directly into
|
||||
# JavaScript without translation, eg.: strings, numbers, true, false, null...
|
||||
LiteralNode: exports.LiteralNode: inherit Node, {
|
||||
type: 'Literal'
|
||||
|
||||
constructor: (value) ->
|
||||
@value: value
|
||||
|
@ -214,6 +221,7 @@ LiteralNode::is_statement_only: LiteralNode::is_statement
|
|||
|
||||
# Return an expression, or wrap it in a closure and return it.
|
||||
ReturnNode: exports.ReturnNode: inherit Node, {
|
||||
type: 'Return'
|
||||
|
||||
constructor: (expression) ->
|
||||
@children: [@expression: expression]
|
||||
|
@ -229,6 +237,7 @@ statement ReturnNode, true
|
|||
|
||||
# A value, indexed or dotted into, or vanilla.
|
||||
ValueNode: exports.ValueNode: inherit Node, {
|
||||
type: 'Value'
|
||||
|
||||
SOAK: " == undefined ? undefined : "
|
||||
|
||||
|
@ -294,6 +303,7 @@ ValueNode: exports.ValueNode: inherit Node, {
|
|||
# Pass through CoffeeScript comments into JavaScript comments at the
|
||||
# same position.
|
||||
CommentNode: exports.CommentNode: inherit Node, {
|
||||
type: 'Comment'
|
||||
|
||||
constructor: (lines) ->
|
||||
@lines: lines
|
||||
|
@ -310,6 +320,7 @@ statement CommentNode
|
|||
# Node for a function invocation. Takes care of converting super() calls into
|
||||
# calls against the prototype's function of the same name.
|
||||
CallNode: exports.CallNode: inherit Node, {
|
||||
type: 'Call'
|
||||
|
||||
constructor: (variable, args) ->
|
||||
@children: flatten [@variable: variable, @args: (args or [])]
|
||||
|
@ -364,6 +375,7 @@ CallNode: exports.CallNode: inherit Node, {
|
|||
# Node to extend an object's prototype with an ancestor object.
|
||||
# After goog.inherits from the Closure Library.
|
||||
ExtendsNode: exports.ExtendsNode: inherit Node, {
|
||||
type: 'Extends'
|
||||
|
||||
constructor: (child, parent) ->
|
||||
@children: [@child: child, @parent: parent]
|
||||
|
@ -387,6 +399,7 @@ statement ExtendsNode
|
|||
# A dotted accessor into a part of a value, or the :: shorthand for
|
||||
# an accessor into the object's prototype.
|
||||
AccessorNode: exports.AccessorNode: inherit Node, {
|
||||
type: 'Accessor'
|
||||
|
||||
constructor: (name, tag) ->
|
||||
@children: [@name: name]
|
||||
|
@ -401,6 +414,7 @@ AccessorNode: exports.AccessorNode: inherit Node, {
|
|||
|
||||
# An indexed accessor into a part of an array or object.
|
||||
IndexNode: exports.IndexNode: inherit Node, {
|
||||
type: 'Index'
|
||||
|
||||
constructor: (index) ->
|
||||
@children: [@index: index]
|
||||
|
@ -413,6 +427,7 @@ IndexNode: exports.IndexNode: inherit Node, {
|
|||
|
||||
# A this-reference, using '@'.
|
||||
ThisNode: exports.ThisNode: inherit Node, {
|
||||
type: 'This'
|
||||
|
||||
constructor: (property) ->
|
||||
@property: property or null
|
||||
|
@ -426,6 +441,7 @@ ThisNode: exports.ThisNode: inherit Node, {
|
|||
# A range literal. Ranges can be used to extract portions (slices) of arrays,
|
||||
# or to specify a range for list comprehensions.
|
||||
RangeNode: exports.RangeNode: inherit Node, {
|
||||
type: 'Range'
|
||||
|
||||
constructor: (from, to, exclusive) ->
|
||||
@children: [@from: from, @to: to]
|
||||
|
@ -464,6 +480,7 @@ RangeNode: exports.RangeNode: inherit Node, {
|
|||
# specifies the index of the end of the slice (just like the first parameter)
|
||||
# is the index of the beginning.
|
||||
SliceNode: exports.SliceNode: inherit Node, {
|
||||
type: 'Slice'
|
||||
|
||||
constructor: (range) ->
|
||||
@children: [@range: range]
|
||||
|
@ -479,6 +496,7 @@ SliceNode: exports.SliceNode: inherit Node, {
|
|||
|
||||
# An object literal.
|
||||
ObjectNode: exports.ObjectNode: inherit Node, {
|
||||
type: 'Object'
|
||||
|
||||
constructor: (props) ->
|
||||
@objects: @properties: props or []
|
||||
|
@ -503,6 +521,7 @@ ObjectNode: exports.ObjectNode: inherit Node, {
|
|||
|
||||
# An array literal.
|
||||
ArrayNode: exports.ArrayNode: inherit Node, {
|
||||
type: 'Array'
|
||||
|
||||
constructor: (objects) ->
|
||||
@children: @objects: objects or []
|
||||
|
@ -549,6 +568,7 @@ ClosureNode: exports.ClosureNode: {
|
|||
|
||||
# Setting the value of a local variable, or the value of an object property.
|
||||
AssignNode: exports.AssignNode: inherit Node, {
|
||||
type: 'Assign'
|
||||
|
||||
PROTO_ASSIGN: /^(\S+)\.prototype/
|
||||
LEADING_DOT: /^\.(prototype\.)?/
|
||||
|
@ -621,6 +641,7 @@ AssignNode: exports.AssignNode: inherit Node, {
|
|||
# A function definition. The only node that creates a new Scope.
|
||||
# A CodeNode does not have any children -- they're within the new scope.
|
||||
CodeNode: exports.CodeNode: inherit Node, {
|
||||
type: 'Code'
|
||||
|
||||
constructor: (params, body, tag) ->
|
||||
@params: params
|
||||
|
@ -658,6 +679,7 @@ CodeNode: exports.CodeNode: inherit Node, {
|
|||
# A splat, either as a parameter to a function, an argument to a call,
|
||||
# or in a destructuring assignment.
|
||||
SplatNode: exports.SplatNode: inherit Node, {
|
||||
type: 'Splat'
|
||||
|
||||
constructor: (name) ->
|
||||
@children: [@name: name]
|
||||
|
@ -679,6 +701,7 @@ SplatNode: exports.SplatNode: inherit Node, {
|
|||
# A while loop, the only sort of low-level loop exposed by CoffeeScript. From
|
||||
# it, all other loops can be manufactured.
|
||||
WhileNode: exports.WhileNode: inherit Node, {
|
||||
type: 'While'
|
||||
|
||||
constructor: (condition, body) ->
|
||||
@children:[@condition: condition, @body: body]
|
||||
|
@ -710,6 +733,7 @@ statement WhileNode
|
|||
# Simple Arithmetic and logical operations. Performs some conversion from
|
||||
# CoffeeScript operations into their JavaScript equivalents.
|
||||
OpNode: exports.OpNode: inherit Node, {
|
||||
type: 'Op'
|
||||
|
||||
CONVERSIONS: {
|
||||
'==': '==='
|
||||
|
@ -771,6 +795,7 @@ OpNode: exports.OpNode: inherit Node, {
|
|||
|
||||
# A try/catch/finally block.
|
||||
TryNode: exports.TryNode: inherit Node, {
|
||||
type: 'Try'
|
||||
|
||||
constructor: (attempt, error, recovery, ensure) ->
|
||||
@children: [@attempt: attempt, @recovery: recovery, @ensure: ensure]
|
||||
|
@ -791,6 +816,7 @@ statement TryNode
|
|||
|
||||
# Throw an exception.
|
||||
ThrowNode: exports.ThrowNode: inherit Node, {
|
||||
type: 'Throw'
|
||||
|
||||
constructor: (expression) ->
|
||||
@children: [@expression: expression]
|
||||
|
@ -805,6 +831,7 @@ statement ThrowNode, true
|
|||
|
||||
# Check an expression for existence (meaning not null or undefined).
|
||||
ExistenceNode: exports.ExistenceNode: inherit Node, {
|
||||
type: 'Existence'
|
||||
|
||||
constructor: (expression) ->
|
||||
@children: [@expression: expression]
|
||||
|
@ -822,6 +849,7 @@ ExistenceNode.compile_test: (o, variable) ->
|
|||
|
||||
# An extra set of parentheses, specified explicitly in the source.
|
||||
ParentheticalNode: exports.ParentheticalNode: inherit Node, {
|
||||
type: 'Paren'
|
||||
|
||||
constructor: (expressions) ->
|
||||
@children: [@expressions: expressions]
|
||||
|
@ -840,6 +868,7 @@ ParentheticalNode: exports.ParentheticalNode: inherit Node, {
|
|||
# of the comprehenion. Unlike Python array comprehensions, it's able to pass
|
||||
# the current index of the loop as a second parameter.
|
||||
ForNode: exports.ForNode: inherit Node, {
|
||||
type: 'For'
|
||||
|
||||
constructor: (body, source, name, index) ->
|
||||
@body: body
|
||||
|
@ -914,6 +943,7 @@ statement ForNode
|
|||
# Single-expression IfNodes are compiled into ternary operators if possible,
|
||||
# because ternaries are first-class returnable assignable expressions.
|
||||
IfNode: exports.IfNode: inherit Node, {
|
||||
type: 'If'
|
||||
|
||||
constructor: (condition, body, else_body, tags) ->
|
||||
@condition: condition
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue