implementing the inline javascript in the documentation page in text/coffeescript, switching from the closure compiler to the yui compressor for building the browser version -- the closure compiler had a bug for our input -- fixable by hand but not worth the tiny savings
This commit is contained in:
parent
c1427d6558
commit
c14869f008
4
Rakefile
4
Rakefile
|
@ -2,7 +2,7 @@ require 'erb'
|
|||
require 'fileutils'
|
||||
require 'rake/testtask'
|
||||
require 'rubygems'
|
||||
require 'closure-compiler'
|
||||
require 'yui/compressor'
|
||||
|
||||
desc "Build the documentation page"
|
||||
task :doc do
|
||||
|
@ -25,7 +25,7 @@ desc "Build the single concatenated and minified script for the browser"
|
|||
task :browser do
|
||||
sources = %w(rewriter.js lexer.js parser.js scope.js nodes.js coffee-script.js)
|
||||
code = sources.map {|s| File.read('lib/' + s) }.join('')
|
||||
code = Closure::Compiler.new.compile(code)
|
||||
code = YUI::JavaScriptCompressor.new.compress(code)
|
||||
File.open('extras/coffee-script.js', 'w+') {|f| f.write(code) }
|
||||
end
|
||||
|
||||
|
|
|
@ -923,52 +923,44 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
|||
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="lib/rewriter.js"></script>
|
||||
<script type="text/javascript" src="lib/lexer.js"></script>
|
||||
<script type="text/javascript" src="lib/parser.js"></script>
|
||||
<script type="text/javascript" src="lib/scope.js"></script>
|
||||
<script type="text/javascript" src="lib/nodes.js"></script>
|
||||
<script type="text/javascript" src="lib/coffee-script.js"></script>
|
||||
<script src="extras/coffee-script.js"></script>
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
|
||||
|
||||
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
|
||||
<script type="text/coffeescript">
|
||||
|
||||
<script type="text/javascript">
|
||||
window.repl_compile = function() {
|
||||
var source = $('#repl_source').val();
|
||||
window.compiled_js = '';
|
||||
try {
|
||||
window.compiled_js = CoffeeScript.compile(source, {no_wrap: true});
|
||||
} catch(error) {
|
||||
alert(error);
|
||||
}
|
||||
$('#repl_results').html(window.compiled_js);
|
||||
};
|
||||
window.repl_run = function() {
|
||||
try {
|
||||
eval(window.compiled_js);
|
||||
} catch(error) {
|
||||
alert(error);
|
||||
}
|
||||
};
|
||||
window.repl_compile: ->
|
||||
source: $('#repl_source').val()
|
||||
window.compiled_js: ''
|
||||
try
|
||||
window.compiled_js: CoffeeScript.compile source, {no_wrap: true}
|
||||
catch error then alert error
|
||||
$('#repl_results').html window.compiled_js
|
||||
|
||||
var nav = $('.navigation');
|
||||
var currentNav = null;
|
||||
var closeMenus = function() {
|
||||
if (currentNav) currentNav.removeClass('active');
|
||||
currentNav = null;
|
||||
};
|
||||
nav.click(function(e) {
|
||||
if (e.target.tagName.toLowerCase() == 'a') return;
|
||||
if (this !== (currentNav && currentNav[0])) {
|
||||
closeMenus();
|
||||
currentNav = $(this);
|
||||
currentNav.addClass('active');
|
||||
}
|
||||
return false;
|
||||
});
|
||||
$(document.body).click(function() {
|
||||
closeMenus();
|
||||
});
|
||||
window.repl_run: ->
|
||||
try
|
||||
eval window.compiled_js
|
||||
catch error then alert error
|
||||
|
||||
nav: $('.navigation')
|
||||
current_nav: null
|
||||
|
||||
close_menus: ->
|
||||
current_nav.removeClass 'active' if current_nav
|
||||
current_nav: null
|
||||
|
||||
nav.click (e) ->
|
||||
return if e.target.tagName.toLowerCase() is 'a'
|
||||
if this isnt (current_nav and current_nav[0])
|
||||
close_menus();
|
||||
current_nav: $(this)
|
||||
current_nav.addClass 'active'
|
||||
false
|
||||
|
||||
$(document.body).click -> close_menus()
|
||||
</script>
|
||||
|
||||
<script>
|
||||
CoffeeScript.activate();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
|
File diff suppressed because one or more lines are too long
78
index.html
78
index.html
|
@ -1803,52 +1803,44 @@ task(<span class="String"><span class="String">'</span>test<span class="String">
|
|||
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="lib/rewriter.js"></script>
|
||||
<script type="text/javascript" src="lib/lexer.js"></script>
|
||||
<script type="text/javascript" src="lib/parser.js"></script>
|
||||
<script type="text/javascript" src="lib/scope.js"></script>
|
||||
<script type="text/javascript" src="lib/nodes.js"></script>
|
||||
<script type="text/javascript" src="lib/coffee-script.js"></script>
|
||||
<script src="extras/coffee-script.js"></script>
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
|
||||
|
||||
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
|
||||
<script type="text/coffeescript">
|
||||
|
||||
<script type="text/javascript">
|
||||
window.repl_compile = function() {
|
||||
var source = $('#repl_source').val();
|
||||
window.compiled_js = '';
|
||||
try {
|
||||
window.compiled_js = CoffeeScript.compile(source, {no_wrap: true});
|
||||
} catch(error) {
|
||||
alert(error);
|
||||
}
|
||||
$('#repl_results').html(window.compiled_js);
|
||||
};
|
||||
window.repl_run = function() {
|
||||
try {
|
||||
eval(window.compiled_js);
|
||||
} catch(error) {
|
||||
alert(error);
|
||||
}
|
||||
};
|
||||
window.repl_compile: ->
|
||||
source: $('#repl_source').val()
|
||||
window.compiled_js: ''
|
||||
try
|
||||
window.compiled_js: CoffeeScript.compile source, {no_wrap: true}
|
||||
catch error then alert error
|
||||
$('#repl_results').html window.compiled_js
|
||||
|
||||
var nav = $('.navigation');
|
||||
var currentNav = null;
|
||||
var closeMenus = function() {
|
||||
if (currentNav) currentNav.removeClass('active');
|
||||
currentNav = null;
|
||||
};
|
||||
nav.click(function(e) {
|
||||
if (e.target.tagName.toLowerCase() == 'a') return;
|
||||
if (this !== (currentNav && currentNav[0])) {
|
||||
closeMenus();
|
||||
currentNav = $(this);
|
||||
currentNav.addClass('active');
|
||||
}
|
||||
return false;
|
||||
});
|
||||
$(document.body).click(function() {
|
||||
closeMenus();
|
||||
});
|
||||
window.repl_run: ->
|
||||
try
|
||||
eval window.compiled_js
|
||||
catch error then alert error
|
||||
|
||||
nav: $('.navigation')
|
||||
current_nav: null
|
||||
|
||||
close_menus: ->
|
||||
current_nav.removeClass 'active' if current_nav
|
||||
current_nav: null
|
||||
|
||||
nav.click (e) ->
|
||||
return if e.target.tagName.toLowerCase() is 'a'
|
||||
if this isnt (current_nav and current_nav[0])
|
||||
close_menus();
|
||||
current_nav: $(this)
|
||||
current_nav.addClass 'active'
|
||||
false
|
||||
|
||||
$(document.body).click -> close_menus()
|
||||
</script>
|
||||
|
||||
<script>
|
||||
CoffeeScript.activate();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -87,7 +87,7 @@
|
|||
} else if (o.lint) {
|
||||
return lint(js);
|
||||
} else if (o.print || o.eval) {
|
||||
return puts(js);
|
||||
return print(js);
|
||||
} else {
|
||||
return write_js(source, js);
|
||||
}
|
||||
|
|
80
lib/nodes.js
80
lib/nodes.js
|
@ -1,5 +1,5 @@
|
|||
(function(){
|
||||
var AccessorNode, ArrayNode, AssignNode, CallNode, ClosureNode, CodeNode, CommentNode, ExistenceNode, Expressions, ExtendsNode, ForNode, IDENTIFIER, IfNode, IndexNode, LiteralNode, Node, ObjectNode, OpNode, ParentheticalNode, PushNode, RangeNode, ReturnNode, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThrowNode, TryNode, ValueNode, WhileNode, compact, del, flatten, inherit, merge, statement;
|
||||
var AccessorNode, ArrayNode, AssignNode, BaseNode, CallNode, ClosureNode, CodeNode, CommentNode, ExistenceNode, Expressions, ExtendsNode, ForNode, IDENTIFIER, IfNode, IndexNode, LiteralNode, ObjectNode, OpNode, ParentheticalNode, PushNode, RangeNode, ReturnNode, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThrowNode, TryNode, ValueNode, WhileNode, compact, del, flatten, inherit, merge, statement;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
(typeof process !== "undefined" && process !== null) ? process.mixin(require('scope')) : (this.exports = this);
|
||||
// Some helper functions
|
||||
|
@ -90,12 +90,12 @@
|
|||
// generated code should be wrapped up in a closure. An options hash is passed
|
||||
// and cloned throughout, containing messages from higher in the AST,
|
||||
// information about the current scope, and indentation level.
|
||||
Node = (exports.Node = function Node() { });
|
||||
BaseNode = (exports.BaseNode = function BaseNode() { });
|
||||
// This is extremely important -- we convert JS statements into expressions
|
||||
// by wrapping them in a closure, only if it's possible, and we're not at
|
||||
// the top level of a block (which would be unnecessary), and we haven't
|
||||
// already been asked to return the result.
|
||||
Node.prototype.compile = function compile(o) {
|
||||
BaseNode.prototype.compile = function compile(o) {
|
||||
var closure, top;
|
||||
this.options = merge(o || {});
|
||||
this.indent = o.indent;
|
||||
|
@ -110,21 +110,21 @@
|
|||
};
|
||||
// Statements converted into expressions share scope with their parent
|
||||
// closure, to preserve JavaScript-style lexical scope.
|
||||
Node.prototype.compile_closure = function compile_closure(o) {
|
||||
BaseNode.prototype.compile_closure = function compile_closure(o) {
|
||||
this.indent = o.indent;
|
||||
o.shared_scope = o.scope;
|
||||
return ClosureNode.wrap(this).compile(o);
|
||||
};
|
||||
// If the code generation wishes to use the result of a complex expression
|
||||
// in multiple places, ensure that the expression is only ever evaluated once.
|
||||
Node.prototype.compile_reference = function compile_reference(o) {
|
||||
BaseNode.prototype.compile_reference = function compile_reference(o) {
|
||||
var compiled, reference;
|
||||
reference = new LiteralNode(o.scope.free_variable());
|
||||
compiled = new AssignNode(reference, this);
|
||||
return [compiled, reference];
|
||||
};
|
||||
// Quick short method for the current indentation level, plus tabbing in.
|
||||
Node.prototype.idt = function idt(tabs) {
|
||||
BaseNode.prototype.idt = function idt(tabs) {
|
||||
var _a, _b, _c, _d, i, idt;
|
||||
idt = (this.indent || '');
|
||||
_c = 0; _d = (tabs || 0);
|
||||
|
@ -134,7 +134,7 @@
|
|||
return idt;
|
||||
};
|
||||
// Does this node, or any of its children, contain a node of a certain kind?
|
||||
Node.prototype.contains = function contains(block) {
|
||||
BaseNode.prototype.contains = function contains(block) {
|
||||
var _a, _b, node;
|
||||
_a = this.children;
|
||||
for (_b = 0; _b < _a.length; _b++) {
|
||||
|
@ -142,14 +142,14 @@
|
|||
if (block(node)) {
|
||||
return true;
|
||||
}
|
||||
if (node instanceof Node && node.contains(block)) {
|
||||
if (node instanceof BaseNode && node.contains(block)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
// toString representation of the node, for inspecting the parse tree.
|
||||
Node.prototype.toString = function toString(idt) {
|
||||
BaseNode.prototype.toString = function toString(idt) {
|
||||
var _a, _b, _c, child;
|
||||
idt = idt || '';
|
||||
return '\n' + idt + this.type + (function() {
|
||||
|
@ -162,24 +162,24 @@
|
|||
}).call(this).join('');
|
||||
};
|
||||
// Default implementations of the common node methods.
|
||||
Node.prototype.unwrap = function unwrap() {
|
||||
BaseNode.prototype.unwrap = function unwrap() {
|
||||
return this;
|
||||
};
|
||||
Node.prototype.children = [];
|
||||
Node.prototype.is_statement = function is_statement() {
|
||||
BaseNode.prototype.children = [];
|
||||
BaseNode.prototype.is_statement = function is_statement() {
|
||||
return false;
|
||||
};
|
||||
Node.prototype.is_statement_only = function is_statement_only() {
|
||||
BaseNode.prototype.is_statement_only = function is_statement_only() {
|
||||
return false;
|
||||
};
|
||||
Node.prototype.top_sensitive = function top_sensitive() {
|
||||
BaseNode.prototype.top_sensitive = function top_sensitive() {
|
||||
return false;
|
||||
};
|
||||
Node.prototype.operation_sensitive = function operation_sensitive() {
|
||||
BaseNode.prototype.operation_sensitive = function operation_sensitive() {
|
||||
return false;
|
||||
};
|
||||
// A collection of nodes, each one representing an expression.
|
||||
Expressions = (exports.Expressions = inherit(Node, {
|
||||
Expressions = (exports.Expressions = inherit(BaseNode, {
|
||||
type: 'Expressions',
|
||||
constructor: function constructor(nodes) {
|
||||
this.children = (this.expressions = compact(flatten(nodes || [])));
|
||||
|
@ -212,7 +212,7 @@
|
|||
},
|
||||
compile: function compile(o) {
|
||||
o = o || {};
|
||||
return o.scope ? Node.prototype.compile.call(this, o) : this.compile_root(o);
|
||||
return o.scope ? BaseNode.prototype.compile.call(this, o) : this.compile_root(o);
|
||||
},
|
||||
// Compile each expression in the Expressions body.
|
||||
compile_node: function compile_node(o) {
|
||||
|
@ -287,7 +287,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, {
|
||||
LiteralNode = (exports.LiteralNode = inherit(BaseNode, {
|
||||
type: 'Literal',
|
||||
constructor: function constructor(value) {
|
||||
this.value = value;
|
||||
|
@ -310,7 +310,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, {
|
||||
ReturnNode = (exports.ReturnNode = inherit(BaseNode, {
|
||||
type: 'Return',
|
||||
constructor: function constructor(expression) {
|
||||
this.children = [(this.expression = expression)];
|
||||
|
@ -327,7 +327,7 @@
|
|||
}));
|
||||
statement(ReturnNode, true);
|
||||
// A value, indexed or dotted into, or vanilla.
|
||||
ValueNode = (exports.ValueNode = inherit(Node, {
|
||||
ValueNode = (exports.ValueNode = inherit(BaseNode, {
|
||||
type: 'Value',
|
||||
SOAK: " == undefined ? undefined : ",
|
||||
constructor: function constructor(base, properties) {
|
||||
|
@ -399,7 +399,7 @@
|
|||
}));
|
||||
// Pass through CoffeeScript comments into JavaScript comments at the
|
||||
// same position.
|
||||
CommentNode = (exports.CommentNode = inherit(Node, {
|
||||
CommentNode = (exports.CommentNode = inherit(BaseNode, {
|
||||
type: 'Comment',
|
||||
constructor: function constructor(lines) {
|
||||
this.lines = lines;
|
||||
|
@ -412,7 +412,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, {
|
||||
CallNode = (exports.CallNode = inherit(BaseNode, {
|
||||
type: 'Call',
|
||||
constructor: function constructor(variable, args) {
|
||||
this.children = flatten([(this.variable = variable), (this.args = (args || []))]);
|
||||
|
@ -477,7 +477,7 @@
|
|||
}));
|
||||
// Node to extend an object's prototype with an ancestor object.
|
||||
// After goog.inherits from the Closure Library.
|
||||
ExtendsNode = (exports.ExtendsNode = inherit(Node, {
|
||||
ExtendsNode = (exports.ExtendsNode = inherit(BaseNode, {
|
||||
type: 'Extends',
|
||||
constructor: function constructor(child, parent) {
|
||||
this.children = [(this.child = child), (this.parent = parent)];
|
||||
|
@ -506,7 +506,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, {
|
||||
AccessorNode = (exports.AccessorNode = inherit(BaseNode, {
|
||||
type: 'Accessor',
|
||||
constructor: function constructor(name, tag) {
|
||||
this.children = [(this.name = name)];
|
||||
|
@ -519,7 +519,7 @@
|
|||
}
|
||||
}));
|
||||
// An indexed accessor into a part of an array or object.
|
||||
IndexNode = (exports.IndexNode = inherit(Node, {
|
||||
IndexNode = (exports.IndexNode = inherit(BaseNode, {
|
||||
type: 'Index',
|
||||
constructor: function constructor(index, tag) {
|
||||
this.children = [(this.index = index)];
|
||||
|
@ -532,7 +532,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, {
|
||||
RangeNode = (exports.RangeNode = inherit(BaseNode, {
|
||||
type: 'Range',
|
||||
constructor: function constructor(from, to, exclusive) {
|
||||
this.children = [(this.from = from), (this.to = to)];
|
||||
|
@ -577,7 +577,7 @@
|
|||
// An array slice literal. Unlike JavaScript's Array#slice, the second parameter
|
||||
// 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, {
|
||||
SliceNode = (exports.SliceNode = inherit(BaseNode, {
|
||||
type: 'Slice',
|
||||
constructor: function constructor(range) {
|
||||
this.children = [(this.range = range)];
|
||||
|
@ -592,7 +592,7 @@
|
|||
}
|
||||
}));
|
||||
// An object literal.
|
||||
ObjectNode = (exports.ObjectNode = inherit(Node, {
|
||||
ObjectNode = (exports.ObjectNode = inherit(BaseNode, {
|
||||
type: 'Object',
|
||||
constructor: function constructor(props) {
|
||||
this.children = (this.objects = (this.properties = props || []));
|
||||
|
@ -639,7 +639,7 @@
|
|||
}
|
||||
}));
|
||||
// An array literal.
|
||||
ArrayNode = (exports.ArrayNode = inherit(Node, {
|
||||
ArrayNode = (exports.ArrayNode = inherit(BaseNode, {
|
||||
type: 'Array',
|
||||
constructor: function constructor(objects) {
|
||||
this.children = (this.objects = objects || []);
|
||||
|
@ -694,7 +694,7 @@
|
|||
}
|
||||
});
|
||||
// Setting the value of a local variable, or the value of an object property.
|
||||
AssignNode = (exports.AssignNode = inherit(Node, {
|
||||
AssignNode = (exports.AssignNode = inherit(BaseNode, {
|
||||
type: 'Assign',
|
||||
PROTO_ASSIGN: /^(\S+)\.prototype/,
|
||||
LEADING_DOT: /^\.(prototype\.)?/,
|
||||
|
@ -798,7 +798,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, {
|
||||
CodeNode = (exports.CodeNode = inherit(BaseNode, {
|
||||
type: 'Code',
|
||||
constructor: function constructor(params, body, tag) {
|
||||
this.params = params;
|
||||
|
@ -865,7 +865,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, {
|
||||
SplatNode = (exports.SplatNode = inherit(BaseNode, {
|
||||
type: 'Splat',
|
||||
constructor: function constructor(name) {
|
||||
if (!(name.compile)) {
|
||||
|
@ -890,7 +890,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, {
|
||||
WhileNode = (exports.WhileNode = inherit(BaseNode, {
|
||||
type: 'While',
|
||||
constructor: function constructor(condition, opts) {
|
||||
this.children = [(this.condition = condition)];
|
||||
|
@ -933,7 +933,7 @@
|
|||
statement(WhileNode);
|
||||
// Simple Arithmetic and logical operations. Performs some conversion from
|
||||
// CoffeeScript operations into their JavaScript equivalents.
|
||||
OpNode = (exports.OpNode = inherit(Node, {
|
||||
OpNode = (exports.OpNode = inherit(BaseNode, {
|
||||
type: 'Op',
|
||||
CONVERSIONS: {
|
||||
'==': '===',
|
||||
|
@ -1019,7 +1019,7 @@
|
|||
}
|
||||
}));
|
||||
// A try/catch/finally block.
|
||||
TryNode = (exports.TryNode = inherit(Node, {
|
||||
TryNode = (exports.TryNode = inherit(BaseNode, {
|
||||
type: 'Try',
|
||||
constructor: function constructor(attempt, error, recovery, ensure) {
|
||||
this.children = compact([(this.attempt = attempt), (this.recovery = recovery), (this.ensure = ensure)]);
|
||||
|
@ -1040,7 +1040,7 @@
|
|||
}));
|
||||
statement(TryNode);
|
||||
// Throw an exception.
|
||||
ThrowNode = (exports.ThrowNode = inherit(Node, {
|
||||
ThrowNode = (exports.ThrowNode = inherit(BaseNode, {
|
||||
type: 'Throw',
|
||||
constructor: function constructor(expression) {
|
||||
this.children = [(this.expression = expression)];
|
||||
|
@ -1052,7 +1052,7 @@
|
|||
}));
|
||||
statement(ThrowNode, true);
|
||||
// Check an expression for existence (meaning not null or undefined).
|
||||
ExistenceNode = (exports.ExistenceNode = inherit(Node, {
|
||||
ExistenceNode = (exports.ExistenceNode = inherit(BaseNode, {
|
||||
type: 'Existence',
|
||||
constructor: function constructor(expression) {
|
||||
this.children = [(this.expression = expression)];
|
||||
|
@ -1075,7 +1075,7 @@
|
|||
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, {
|
||||
ParentheticalNode = (exports.ParentheticalNode = inherit(BaseNode, {
|
||||
type: 'Paren',
|
||||
constructor: function constructor(expression) {
|
||||
this.children = [(this.expression = expression)];
|
||||
|
@ -1101,7 +1101,7 @@
|
|||
// into a for loop. Also acts as an expression, able to return the result
|
||||
// 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, {
|
||||
ForNode = (exports.ForNode = inherit(BaseNode, {
|
||||
type: 'For',
|
||||
constructor: function constructor(body, source, name, index) {
|
||||
var _a;
|
||||
|
@ -1199,7 +1199,7 @@
|
|||
// expression by pushing down requested returns to the expression bodies.
|
||||
// Single-expression IfNodes are compiled into ternary operators if possible,
|
||||
// because ternaries are first-class returnable assignable expressions.
|
||||
IfNode = (exports.IfNode = inherit(Node, {
|
||||
IfNode = (exports.IfNode = inherit(BaseNode, {
|
||||
type: 'If',
|
||||
constructor: function constructor(condition, body, else_body, tags) {
|
||||
this.condition = condition;
|
||||
|
|
|
@ -77,7 +77,7 @@ compile_script: (source, code) ->
|
|||
js: coffee.compile code, compile_options()
|
||||
if o.run then eval js
|
||||
else if o.lint then lint js
|
||||
else if o.print or o.eval then puts js
|
||||
else if o.print or o.eval then print js
|
||||
else write_js source, js
|
||||
catch err
|
||||
if o.watch then puts err.message else throw err
|
||||
|
|
|
@ -54,13 +54,13 @@ statement: (klass, only) ->
|
|||
# generated code should be wrapped up in a closure. An options hash is passed
|
||||
# and cloned throughout, containing messages from higher in the AST,
|
||||
# information about the current scope, and indentation level.
|
||||
Node: exports.Node: ->
|
||||
BaseNode: exports.BaseNode: ->
|
||||
|
||||
# This is extremely important -- we convert JS statements into expressions
|
||||
# by wrapping them in a closure, only if it's possible, and we're not at
|
||||
# the top level of a block (which would be unnecessary), and we haven't
|
||||
# already been asked to return the result.
|
||||
Node::compile: (o) ->
|
||||
BaseNode::compile: (o) ->
|
||||
@options: merge o or {}
|
||||
@indent: o.indent
|
||||
del @options, 'operation' unless @operation_sensitive()
|
||||
|
@ -72,46 +72,46 @@ Node::compile: (o) ->
|
|||
|
||||
# Statements converted into expressions share scope with their parent
|
||||
# closure, to preserve JavaScript-style lexical scope.
|
||||
Node::compile_closure: (o) ->
|
||||
BaseNode::compile_closure: (o) ->
|
||||
@indent: o.indent
|
||||
o.shared_scope: o.scope
|
||||
ClosureNode.wrap(this).compile(o)
|
||||
|
||||
# If the code generation wishes to use the result of a complex expression
|
||||
# in multiple places, ensure that the expression is only ever evaluated once.
|
||||
Node::compile_reference: (o) ->
|
||||
BaseNode::compile_reference: (o) ->
|
||||
reference: new LiteralNode(o.scope.free_variable())
|
||||
compiled: new AssignNode(reference, this)
|
||||
[compiled, reference]
|
||||
|
||||
# Quick short method for the current indentation level, plus tabbing in.
|
||||
Node::idt: (tabs) ->
|
||||
BaseNode::idt: (tabs) ->
|
||||
idt: (@indent || '')
|
||||
idt += TAB for i in [0...(tabs or 0)]
|
||||
idt
|
||||
|
||||
# Does this node, or any of its children, contain a node of a certain kind?
|
||||
Node::contains: (block) ->
|
||||
BaseNode::contains: (block) ->
|
||||
for node in @children
|
||||
return true if block(node)
|
||||
return true if node instanceof Node and node.contains block
|
||||
return true if node instanceof BaseNode and node.contains block
|
||||
false
|
||||
|
||||
# toString representation of the node, for inspecting the parse tree.
|
||||
Node::toString: (idt) ->
|
||||
BaseNode::toString: (idt) ->
|
||||
idt ||= ''
|
||||
'\n' + idt + @type + (child.toString(idt + TAB) for child in @children).join('')
|
||||
|
||||
# Default implementations of the common node methods.
|
||||
Node::unwrap: -> this
|
||||
Node::children: []
|
||||
Node::is_statement: -> false
|
||||
Node::is_statement_only: -> false
|
||||
Node::top_sensitive: -> false
|
||||
Node::operation_sensitive: -> false
|
||||
BaseNode::unwrap: -> this
|
||||
BaseNode::children: []
|
||||
BaseNode::is_statement: -> false
|
||||
BaseNode::is_statement_only: -> false
|
||||
BaseNode::top_sensitive: -> false
|
||||
BaseNode::operation_sensitive: -> false
|
||||
|
||||
# A collection of nodes, each one representing an expression.
|
||||
Expressions: exports.Expressions: inherit Node, {
|
||||
Expressions: exports.Expressions: inherit BaseNode, {
|
||||
type: 'Expressions'
|
||||
|
||||
constructor: (nodes) ->
|
||||
|
@ -144,7 +144,7 @@ Expressions: exports.Expressions: inherit Node, {
|
|||
|
||||
compile: (o) ->
|
||||
o ||= {}
|
||||
if o.scope then Node::compile.call(this, o) else @compile_root(o)
|
||||
if o.scope then BaseNode::compile.call(this, o) else @compile_root(o)
|
||||
|
||||
# Compile each expression in the Expressions body.
|
||||
compile_node: (o) ->
|
||||
|
@ -192,7 +192,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, {
|
||||
LiteralNode: exports.LiteralNode: inherit BaseNode, {
|
||||
type: 'Literal'
|
||||
|
||||
constructor: (value) ->
|
||||
|
@ -217,7 +217,7 @@ LiteralNode: exports.LiteralNode: inherit Node, {
|
|||
LiteralNode::is_statement_only: LiteralNode::is_statement
|
||||
|
||||
# Return an expression, or wrap it in a closure and return it.
|
||||
ReturnNode: exports.ReturnNode: inherit Node, {
|
||||
ReturnNode: exports.ReturnNode: inherit BaseNode, {
|
||||
type: 'Return'
|
||||
|
||||
constructor: (expression) ->
|
||||
|
@ -233,7 +233,7 @@ ReturnNode: exports.ReturnNode: inherit Node, {
|
|||
statement ReturnNode, true
|
||||
|
||||
# A value, indexed or dotted into, or vanilla.
|
||||
ValueNode: exports.ValueNode: inherit Node, {
|
||||
ValueNode: exports.ValueNode: inherit BaseNode, {
|
||||
type: 'Value'
|
||||
|
||||
SOAK: " == undefined ? undefined : "
|
||||
|
@ -302,7 +302,7 @@ ValueNode: exports.ValueNode: inherit Node, {
|
|||
|
||||
# Pass through CoffeeScript comments into JavaScript comments at the
|
||||
# same position.
|
||||
CommentNode: exports.CommentNode: inherit Node, {
|
||||
CommentNode: exports.CommentNode: inherit BaseNode, {
|
||||
type: 'Comment'
|
||||
|
||||
constructor: (lines) ->
|
||||
|
@ -318,7 +318,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, {
|
||||
CallNode: exports.CallNode: inherit BaseNode, {
|
||||
type: 'Call'
|
||||
|
||||
constructor: (variable, args) ->
|
||||
|
@ -366,7 +366,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, {
|
||||
ExtendsNode: exports.ExtendsNode: inherit BaseNode, {
|
||||
type: 'Extends'
|
||||
|
||||
constructor: (child, parent) ->
|
||||
|
@ -399,7 +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, {
|
||||
AccessorNode: exports.AccessorNode: inherit BaseNode, {
|
||||
type: 'Accessor'
|
||||
|
||||
constructor: (name, tag) ->
|
||||
|
@ -414,7 +414,7 @@ AccessorNode: exports.AccessorNode: inherit Node, {
|
|||
}
|
||||
|
||||
# An indexed accessor into a part of an array or object.
|
||||
IndexNode: exports.IndexNode: inherit Node, {
|
||||
IndexNode: exports.IndexNode: inherit BaseNode, {
|
||||
type: 'Index'
|
||||
|
||||
constructor: (index, tag) ->
|
||||
|
@ -429,7 +429,7 @@ IndexNode: exports.IndexNode: 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, {
|
||||
RangeNode: exports.RangeNode: inherit BaseNode, {
|
||||
type: 'Range'
|
||||
|
||||
constructor: (from, to, exclusive) ->
|
||||
|
@ -469,7 +469,7 @@ RangeNode: exports.RangeNode: inherit Node, {
|
|||
# An array slice literal. Unlike JavaScript's Array#slice, the second parameter
|
||||
# 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, {
|
||||
SliceNode: exports.SliceNode: inherit BaseNode, {
|
||||
type: 'Slice'
|
||||
|
||||
constructor: (range) ->
|
||||
|
@ -485,7 +485,7 @@ SliceNode: exports.SliceNode: inherit Node, {
|
|||
}
|
||||
|
||||
# An object literal.
|
||||
ObjectNode: exports.ObjectNode: inherit Node, {
|
||||
ObjectNode: exports.ObjectNode: inherit BaseNode, {
|
||||
type: 'Object'
|
||||
|
||||
constructor: (props) ->
|
||||
|
@ -512,7 +512,7 @@ ObjectNode: exports.ObjectNode: inherit Node, {
|
|||
}
|
||||
|
||||
# An array literal.
|
||||
ArrayNode: exports.ArrayNode: inherit Node, {
|
||||
ArrayNode: exports.ArrayNode: inherit BaseNode, {
|
||||
type: 'Array'
|
||||
|
||||
constructor: (objects) ->
|
||||
|
@ -559,7 +559,7 @@ ClosureNode: exports.ClosureNode: {
|
|||
}
|
||||
|
||||
# Setting the value of a local variable, or the value of an object property.
|
||||
AssignNode: exports.AssignNode: inherit Node, {
|
||||
AssignNode: exports.AssignNode: inherit BaseNode, {
|
||||
type: 'Assign'
|
||||
|
||||
PROTO_ASSIGN: /^(\S+)\.prototype/
|
||||
|
@ -632,7 +632,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, {
|
||||
CodeNode: exports.CodeNode: inherit BaseNode, {
|
||||
type: 'Code'
|
||||
|
||||
constructor: (params, body, tag) ->
|
||||
|
@ -676,7 +676,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, {
|
||||
SplatNode: exports.SplatNode: inherit BaseNode, {
|
||||
type: 'Splat'
|
||||
|
||||
constructor: (name) ->
|
||||
|
@ -699,7 +699,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, {
|
||||
WhileNode: exports.WhileNode: inherit BaseNode, {
|
||||
type: 'While'
|
||||
|
||||
constructor: (condition, opts) ->
|
||||
|
@ -737,7 +737,7 @@ statement WhileNode
|
|||
|
||||
# Simple Arithmetic and logical operations. Performs some conversion from
|
||||
# CoffeeScript operations into their JavaScript equivalents.
|
||||
OpNode: exports.OpNode: inherit Node, {
|
||||
OpNode: exports.OpNode: inherit BaseNode, {
|
||||
type: 'Op'
|
||||
|
||||
CONVERSIONS: {
|
||||
|
@ -801,7 +801,7 @@ OpNode: exports.OpNode: inherit Node, {
|
|||
}
|
||||
|
||||
# A try/catch/finally block.
|
||||
TryNode: exports.TryNode: inherit Node, {
|
||||
TryNode: exports.TryNode: inherit BaseNode, {
|
||||
type: 'Try'
|
||||
|
||||
constructor: (attempt, error, recovery, ensure) ->
|
||||
|
@ -822,7 +822,7 @@ TryNode: exports.TryNode: inherit Node, {
|
|||
statement TryNode
|
||||
|
||||
# Throw an exception.
|
||||
ThrowNode: exports.ThrowNode: inherit Node, {
|
||||
ThrowNode: exports.ThrowNode: inherit BaseNode, {
|
||||
type: 'Throw'
|
||||
|
||||
constructor: (expression) ->
|
||||
|
@ -837,7 +837,7 @@ ThrowNode: exports.ThrowNode: inherit Node, {
|
|||
statement ThrowNode, true
|
||||
|
||||
# Check an expression for existence (meaning not null or undefined).
|
||||
ExistenceNode: exports.ExistenceNode: inherit Node, {
|
||||
ExistenceNode: exports.ExistenceNode: inherit BaseNode, {
|
||||
type: 'Existence'
|
||||
|
||||
constructor: (expression) ->
|
||||
|
@ -856,7 +856,7 @@ ExistenceNode.compile_test: (o, variable) ->
|
|||
'(typeof ' + first.compile(o) + ' !== "undefined" && ' + second.compile(o) + ' !== null)'
|
||||
|
||||
# An extra set of parentheses, specified explicitly in the source.
|
||||
ParentheticalNode: exports.ParentheticalNode: inherit Node, {
|
||||
ParentheticalNode: exports.ParentheticalNode: inherit BaseNode, {
|
||||
type: 'Paren'
|
||||
|
||||
constructor: (expression) ->
|
||||
|
@ -879,7 +879,7 @@ ParentheticalNode: exports.ParentheticalNode: inherit Node, {
|
|||
# into a for loop. Also acts as an expression, able to return the result
|
||||
# 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, {
|
||||
ForNode: exports.ForNode: inherit BaseNode, {
|
||||
type: 'For'
|
||||
|
||||
constructor: (body, source, name, index) ->
|
||||
|
@ -949,7 +949,7 @@ statement ForNode
|
|||
# expression by pushing down requested returns to the expression bodies.
|
||||
# Single-expression IfNodes are compiled into ternary operators if possible,
|
||||
# because ternaries are first-class returnable assignable expressions.
|
||||
IfNode: exports.IfNode: inherit Node, {
|
||||
IfNode: exports.IfNode: inherit BaseNode, {
|
||||
type: 'If'
|
||||
|
||||
constructor: (condition, body, else_body, tags) ->
|
||||
|
|
Loading…
Reference in New Issue