diff --git a/lib/coffee_script/nodes.js b/lib/coffee_script/nodes.js index bcab2c88..d7989820 100644 --- a/lib/coffee_script/nodes.js +++ b/lib/coffee_script/nodes.js @@ -1,5 +1,5 @@ (function(){ - var AccessorNode, ArrayNode, AssignNode, CallNode, ClosureNode, CodeNode, CommentNode, Expressions, ExtendsNode, IDENTIFIER, IndexNode, LiteralNode, Node, ObjectNode, OpNode, PushNode, RangeNode, ReturnNode, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThisNode, TryNode, ValueNode, WhileNode, any, compact, del, dup, flatten, inherit, merge, statement; + var AccessorNode, ArrayNode, AssignNode, CallNode, ClosureNode, CodeNode, CommentNode, ExistenceNode, Expressions, ExtendsNode, IDENTIFIER, IndexNode, LiteralNode, Node, ObjectNode, OpNode, ParentheticalNode, PushNode, RangeNode, ReturnNode, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThisNode, ThrowNode, TryNode, ValueNode, WhileNode, any, compact, del, dup, flatten, inherit, merge, statement; var __hasProp = Object.prototype.hasOwnProperty; process.mixin(require('./scope')); // The abstract base class for all CoffeeScript nodes. @@ -1134,4 +1134,53 @@ } })); statement(TryNode); + // Throw an exception. + ThrowNode = (exports.ThrowNode = inherit(Node, { + constructor: function constructor(expression) { + this.children = [(this.expression = expression)]; + return this; + }, + compile_node: function compile_node(o) { + return this.idt() + 'throw ' + this.expression.compile(o) + ';'; + } + })); + statement(ThrowNode, true); + // Check an expression for existence (meaning not null or undefined). + ExistenceNode = (exports.ExistenceNode = inherit(Node, { + constructor: function constructor(expression) { + this.children = [(this.expression = expression)]; + return this; + }, + compile_node: function compile_node(o) { + return ExistenceNode.compile_test(o, this.expression); + } + })); + ExistenceNode.compile_test = function compile_test(o, variable) { + var __a, __b, first, second; + __a = [variable, variable]; + first = __a[0]; + second = __a[1]; + if (variable instanceof CallNode) { + __b = variable.compile_reference(o); + first = __b[0]; + second = __b[1]; + } + return '(typeof ' + first.compile(o) + ' !== "undefined" && ' + second.compile(o) + ' !== null)'; + }; + // An extra set of parentheses, specified explicitly in the source. + ParentheticalNode = (exports.ParentheticalNode = inherit(Node, { + constructor: function constructor(expressions) { + this.children = [(this.expressions = expressions)]; + return this; + }, + compile_node: function compile_node(o) { + var code, l; + code = this.expressions.compile(o); + l = code.length; + if (code.substr(l - 1, 1) === ';') { + code = code.substr(o, l - 1); + } + return '(' + code + ')'; + } + })); })(); \ No newline at end of file diff --git a/lib/coffee_script/nodes.rb b/lib/coffee_script/nodes.rb index fe591213..99977810 100644 --- a/lib/coffee_script/nodes.rb +++ b/lib/coffee_script/nodes.rb @@ -853,9 +853,7 @@ module CoffeeScript end end - # An extra set of parentheses, supplied by the script source. - # You can't wrap parentheses around bits that get compiled into JS statements, - # unfortunately. + # An extra set of parentheses, specified explicitly in the source. class ParentheticalNode < Node children :expressions diff --git a/src/nodes.coffee b/src/nodes.coffee index ce97b3db..25e065f6 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -825,6 +825,51 @@ TryNode: exports.TryNode: inherit Node, { statement TryNode +# Throw an exception. +ThrowNode: exports.ThrowNode: inherit Node, { + + constructor: (expression) -> + @children: [@expression: expression] + this + + compile_node: (o) -> + @idt() + 'throw ' + @expression.compile(o) + ';' + +} + +statement ThrowNode, true + +# Check an expression for existence (meaning not null or undefined). +ExistenceNode: exports.ExistenceNode: inherit Node, { + + constructor: (expression) -> + @children: [@expression: expression] + this + + compile_node: (o) -> + ExistenceNode.compile_test(o, @expression) + +} + +ExistenceNode.compile_test: (o, variable) -> + [first, second]: [variable, variable] + [first, second]: variable.compile_reference(o) if variable instanceof CallNode + '(typeof ' + first.compile(o) + ' !== "undefined" && ' + second.compile(o) + ' !== null)' + +# An extra set of parentheses, specified explicitly in the source. +ParentheticalNode: exports.ParentheticalNode: inherit Node, { + + constructor: (expressions) -> + @children: [@expressions: expressions] + this + + compile_node: (o) -> + code: @expressions.compile(o) + l: code.length + code: code.substr(o, l-1) if code.substr(l-1, 1) is ';' + '(' + code + ')' + +}