mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-01-13 08:47:55 -05:00
Compare commits
359 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
158d37215a | ||
|
|
7ad25c90fa | ||
|
|
b06a326c7d | ||
|
|
25bdde85a9 | ||
|
|
d8905e2f87 | ||
|
|
97de09c8f1 | ||
|
|
7595cb689a | ||
|
|
2b86470665 | ||
|
|
78423e9a14 | ||
|
|
ec59a626f2 | ||
|
|
1b14c035e7 | ||
|
|
ba34f8d389 | ||
|
|
b74e73058c | ||
|
|
c29597b3bc | ||
|
|
5d7a83468a | ||
|
|
a396837fa4 | ||
|
|
1fa3da68ba | ||
|
|
219726a9c5 | ||
|
|
81c0964e48 | ||
|
|
c9388ce767 | ||
|
|
2a56f0cdf7 | ||
|
|
ace4837365 | ||
|
|
6417cf4d1b | ||
|
|
1731f7d321 | ||
|
|
8d39c1cc79 | ||
|
|
bc7e0cf09a | ||
|
|
7c29ea4d38 | ||
|
|
6c6c8bd454 | ||
|
|
81f780f1fb | ||
|
|
6838bae36e | ||
|
|
972a5299d5 | ||
|
|
b8149812cd | ||
|
|
01d4e87f57 | ||
|
|
f938a213fe | ||
|
|
df54c63b1b | ||
|
|
1810d9f318 | ||
|
|
29b9c3bb29 | ||
|
|
da2298988a | ||
|
|
f31ff7774a | ||
|
|
c6fafa1bc9 | ||
|
|
e8a8209a2b | ||
|
|
fa82859814 | ||
|
|
55e1386503 | ||
|
|
dc9565f54a | ||
|
|
c264bf04cc | ||
|
|
5c66e552d7 | ||
|
|
c4ebe352a4 | ||
|
|
79492aab36 | ||
|
|
e3454ed7fb | ||
|
|
8dcbe54e55 | ||
|
|
dac24a3d8a | ||
|
|
5c8eef2ab5 | ||
|
|
66c751be11 | ||
|
|
7792a3a6e3 | ||
|
|
e57a5de33e | ||
|
|
ed705403ad | ||
|
|
fa899ab810 | ||
|
|
fdcd99dfef | ||
|
|
d5ddd0f783 | ||
|
|
848d10594b | ||
|
|
caf3da2f66 | ||
|
|
f1b286469a | ||
|
|
46065199cd | ||
|
|
879fe3976d | ||
|
|
c1309e12f7 | ||
|
|
6bcc798a76 | ||
|
|
3e95d7f2d0 | ||
|
|
c3159e48c8 | ||
|
|
34be878257 | ||
|
|
87257ea6b3 | ||
|
|
8bc6001d27 | ||
|
|
e433098eb2 | ||
|
|
afdcdcfd54 | ||
|
|
4fc9a345bb | ||
|
|
c06487c13b | ||
|
|
7a80661ad5 | ||
|
|
2fb527a63f | ||
|
|
99394e1011 | ||
|
|
3b1a566117 | ||
|
|
d58da49cee | ||
|
|
0fada5109a | ||
|
|
46ff7705ee | ||
|
|
eabcb2c8b0 | ||
|
|
ea60dfa44d | ||
|
|
53a82da3f3 | ||
|
|
b03bea14fa | ||
|
|
2f13fae6f0 | ||
|
|
a92af02ae8 | ||
|
|
4043124135 | ||
|
|
7b66e22bc6 | ||
|
|
5542e00b80 | ||
|
|
f3a1f46679 | ||
|
|
08673261b1 | ||
|
|
60c9b94656 | ||
|
|
f0e17fc20f | ||
|
|
de511e0348 | ||
|
|
ed8d94f69c | ||
|
|
1b3af684cb | ||
|
|
53fe10e4ad | ||
|
|
b4e1e54cf7 | ||
|
|
22db7ae85a | ||
|
|
6a88ce7d1e | ||
|
|
7e32c32057 | ||
|
|
c5737764b5 | ||
|
|
ddd6e9a48b | ||
|
|
d6fbfa55b6 | ||
|
|
abb11c80d1 | ||
|
|
ef0cb46b9b | ||
|
|
209a0f5a79 | ||
|
|
44e1ccec7e | ||
|
|
7c1f4b38f4 | ||
|
|
b9cfb5a7d8 | ||
|
|
1c8411f628 | ||
|
|
de9970412a | ||
|
|
a0e3a8b420 | ||
|
|
bc2ca1ef73 | ||
|
|
9a955859fd | ||
|
|
ecfe49adca | ||
|
|
7a75b2b8d0 | ||
|
|
127653b7d4 | ||
|
|
b7f2681007 | ||
|
|
12d6461bbe | ||
|
|
28a1101b91 | ||
|
|
8248601b72 | ||
|
|
2e78508016 | ||
|
|
d9120b8365 | ||
|
|
eb8e20c3ef | ||
|
|
cb0003d894 | ||
|
|
7becf808c7 | ||
|
|
13f8348568 | ||
|
|
d6e2ae292e | ||
|
|
e42f96b76d | ||
|
|
40a9196c7f | ||
|
|
0ca255b7b8 | ||
|
|
8ade4f1077 | ||
|
|
d74c909930 | ||
|
|
c0dac45fe1 | ||
|
|
eb5c4057a1 | ||
|
|
a080bd40fb | ||
|
|
b7b92eddbd | ||
|
|
e0ec397046 | ||
|
|
34e517de09 | ||
|
|
f40ba672db | ||
|
|
8ac440fd52 | ||
|
|
c3a8a4f81f | ||
|
|
7c56da26f6 | ||
|
|
97cd2dbc41 | ||
|
|
8affc297fc | ||
|
|
6d69812046 | ||
|
|
de8d16f5e7 | ||
|
|
b4712c6a93 | ||
|
|
3fc4f10248 | ||
|
|
ec55335092 | ||
|
|
af51300887 | ||
|
|
233cd27d70 | ||
|
|
c1f7db8275 | ||
|
|
0bf488ea49 | ||
|
|
bf8e0aa1ea | ||
|
|
4372138fdd | ||
|
|
8b179fb391 | ||
|
|
0b7cfba94a | ||
|
|
f43ec97e30 | ||
|
|
7521068ba3 | ||
|
|
a2ef66f197 | ||
|
|
3a694d7dfa | ||
|
|
cad108eca0 | ||
|
|
66eb186a74 | ||
|
|
6e1e77d46d | ||
|
|
e207c983c1 | ||
|
|
9a23511965 | ||
|
|
df7ab264ab | ||
|
|
9e1d418d7a | ||
|
|
ee9311c025 | ||
|
|
2ec4c38433 | ||
|
|
b6310d0365 | ||
|
|
77670b0f3e | ||
|
|
fd1fa7d551 | ||
|
|
0c5726d3ab | ||
|
|
5816de39ba | ||
|
|
80677a9d2b | ||
|
|
8d952c245f | ||
|
|
6d33a2e1a0 | ||
|
|
ff05575b78 | ||
|
|
16e297ab61 | ||
|
|
447ce82721 | ||
|
|
86e4d79ffb | ||
|
|
11342ef97b | ||
|
|
48c17e2c3d | ||
|
|
36a69864e3 | ||
|
|
64b0e50609 | ||
|
|
806df9bc1e | ||
|
|
f98c613ecc | ||
|
|
642fcbbbfe | ||
|
|
58bb6725e4 | ||
|
|
3484ca5e64 | ||
|
|
0b1b7c36d2 | ||
|
|
8eb04cd80b | ||
|
|
8dfec65034 | ||
|
|
4a0e8139ea | ||
|
|
c8059a752f | ||
|
|
62a331a3dc | ||
|
|
90e0ce97e4 | ||
|
|
3b3c069c3b | ||
|
|
46b34d4b43 | ||
|
|
080ed2e8dd | ||
|
|
0c4cb309b0 | ||
|
|
8d5f800e2f | ||
|
|
e2a205ab22 | ||
|
|
21a499c726 | ||
|
|
e5f3750de2 | ||
|
|
4944fba3f7 | ||
|
|
65d21766b7 | ||
|
|
2a0521fba6 | ||
|
|
97cd7cc1c9 | ||
|
|
d3f60599e8 | ||
|
|
8728706237 | ||
|
|
c6c527e830 | ||
|
|
fc0a169a9a | ||
|
|
5b7366583d | ||
|
|
01e03ae2d8 | ||
|
|
8a1deee8d8 | ||
|
|
2e06316e31 | ||
|
|
6870af36b7 | ||
|
|
0f1dbffa40 | ||
|
|
cfb9cb6fe9 | ||
|
|
9de0d886eb | ||
|
|
5c24b80367 | ||
|
|
a477880edc | ||
|
|
00f5f54b77 | ||
|
|
1018c51359 | ||
|
|
8d8c345216 | ||
|
|
dd25ac03e4 | ||
|
|
3ff194dd61 | ||
|
|
215979c9e0 | ||
|
|
6d3acdcd2f | ||
|
|
9abe614ea8 | ||
|
|
36c171d78e | ||
|
|
c75c4421a7 | ||
|
|
55998f7481 | ||
|
|
d5acd7f338 | ||
|
|
d3cc05bdfc | ||
|
|
07ccd91022 | ||
|
|
edd0b661f3 | ||
|
|
4b0fabd7cb | ||
|
|
55e794dbe5 | ||
|
|
988dedd08d | ||
|
|
f66564273c | ||
|
|
dfc602159e | ||
|
|
9fde794858 | ||
|
|
ed1ddbce50 | ||
|
|
cda95afd3e | ||
|
|
0e40feb9af | ||
|
|
846306f85e | ||
|
|
a0aa090f2c | ||
|
|
460b5d6edb | ||
|
|
b9805f3f80 | ||
|
|
0069c4901f | ||
|
|
93b118bfa2 | ||
|
|
7c6bc95a84 | ||
|
|
ee8a1a3b68 | ||
|
|
5bca978444 | ||
|
|
347409e354 | ||
|
|
c284f3f226 | ||
|
|
cdd3c13ce9 | ||
|
|
f6dbaa7c31 | ||
|
|
a4553c970c | ||
|
|
38b6a43e26 | ||
|
|
121009dec4 | ||
|
|
510fb59e29 | ||
|
|
e4b3e838e2 | ||
|
|
4b70a16cf9 | ||
|
|
af0ee70ea3 | ||
|
|
ad39150565 | ||
|
|
686ef9e7f4 | ||
|
|
fac615108c | ||
|
|
ddfe89d916 | ||
|
|
b0948f81dd | ||
|
|
00f9e244f2 | ||
|
|
eb55f2d8f4 | ||
|
|
b50315d8a0 | ||
|
|
85286b8ca5 | ||
|
|
74944da211 | ||
|
|
c9a0a33fa2 | ||
|
|
b12be3188f | ||
|
|
26a28abcb5 | ||
|
|
5f1314cd66 | ||
|
|
0ad9d4bf16 | ||
|
|
621e5648e3 | ||
|
|
f0728fcf8f | ||
|
|
63ab886e9f | ||
|
|
7b4f1b165d | ||
|
|
8855eede5f | ||
|
|
69d49e137a | ||
|
|
94e17e0d88 | ||
|
|
5debc3c903 | ||
|
|
0ce332edca | ||
|
|
b122406683 | ||
|
|
35dc56d785 | ||
|
|
6cb13f4c44 | ||
|
|
26d5c99570 | ||
|
|
24836ccf6d | ||
|
|
7d22a011ab | ||
|
|
e9e5ae119f | ||
|
|
2c92904109 | ||
|
|
2fb6d0beb9 | ||
|
|
b9c17cab3c | ||
|
|
d2c3b79617 | ||
|
|
03b8222c9e | ||
|
|
57e109ff11 | ||
|
|
30614c5721 | ||
|
|
55521a2f4c | ||
|
|
8762e37e58 | ||
|
|
fba69f5651 | ||
|
|
bde1c6282e | ||
|
|
a24451b6d3 | ||
|
|
d0b8cded6b | ||
|
|
1e25c9da30 | ||
|
|
fe78e65b16 | ||
|
|
9e1d1f57f0 | ||
|
|
73acfa18a3 | ||
|
|
266d97f8f5 | ||
|
|
a70753e6d3 | ||
|
|
97dbb7bb49 | ||
|
|
79945ad473 | ||
|
|
1d7a3b4d0f | ||
|
|
5bf8b422f8 | ||
|
|
9633816d7a | ||
|
|
cc8708493e | ||
|
|
51b25fb3d8 | ||
|
|
b41a69da2d | ||
|
|
1ce92d1aeb | ||
|
|
496978abdd | ||
|
|
424bb17224 | ||
|
|
6d6a5f609a | ||
|
|
a296957771 | ||
|
|
fbe84e376c | ||
|
|
d30aa6d621 | ||
|
|
966063db0c | ||
|
|
13717e2e65 | ||
|
|
7aaaac42bc | ||
|
|
65930224ee | ||
|
|
97d1eedd5a | ||
|
|
11544f2717 | ||
|
|
590bd3dec9 | ||
|
|
74501f643c | ||
|
|
cebfe394ad | ||
|
|
2e037dcb93 | ||
|
|
8a41ee95c7 | ||
|
|
3564f51fb5 | ||
|
|
df641261d6 | ||
|
|
f3486499ac | ||
|
|
a768f167cf | ||
|
|
03a8340a85 | ||
|
|
036197fac3 | ||
|
|
b8d60a9cf1 | ||
|
|
b02ac3a733 | ||
|
|
70a5402509 | ||
|
|
f2c0ea7fa4 | ||
|
|
216ad777de |
9
CONTRIBUTING.md
Normal file
9
CONTRIBUTING.md
Normal file
@@ -0,0 +1,9 @@
|
||||
## How to contribute to CoffeeScript
|
||||
|
||||
* Before you open a ticket or send a pull request, [search](https://github.com/jashkenas/coffee-script/issues) for previous discussions about the same feature or issue. Add to the earlier ticket if you find one.
|
||||
|
||||
* Before sending a pull request for a feature, be sure to have [tests](https://github.com/jashkenas/coffee-script/tree/master/test).
|
||||
|
||||
* Use the same coding style as the rest of the [codebase](https://github.com/jashkenas/coffee-script/tree/master/src). If you're just getting started with CoffeeScript, there's a nice [style guide](https://github.com/polarmobile/coffeescript-style-guide).
|
||||
|
||||
* In your pull request, do not add documentation to `index.html` or re-build the minified `coffee-script.js` file. We'll do those things before cutting a new release.
|
||||
28
Cakefile
28
Cakefile
@@ -11,10 +11,10 @@ unless process.platform is 'win32'
|
||||
|
||||
bold = red = green = reset = ''
|
||||
if enableColors
|
||||
bold = '\033[0;1m'
|
||||
red = '\033[0;31m'
|
||||
green = '\033[0;32m'
|
||||
reset = '\033[0m'
|
||||
bold = '\x1B[0;1m'
|
||||
red = '\x1B[0;31m'
|
||||
green = '\x1B[0;32m'
|
||||
reset = '\x1B[0m'
|
||||
|
||||
# Built file header.
|
||||
header = """
|
||||
@@ -34,7 +34,7 @@ sources = [
|
||||
|
||||
# Run a CoffeeScript through our node/coffee interpreter.
|
||||
run = (args, cb) ->
|
||||
proc = spawn 'bin/coffee', args
|
||||
proc = spawn 'node', ['bin/coffee'].concat(args)
|
||||
proc.stderr.on 'data', (buffer) -> console.log buffer.toString()
|
||||
proc.on 'exit', (status) ->
|
||||
process.exit(1) if status != 0
|
||||
@@ -104,11 +104,19 @@ task 'build:browser', 'rebuild the merged script for inclusion in the browser',
|
||||
};
|
||||
"""
|
||||
code = """
|
||||
this.CoffeeScript = function() {
|
||||
function require(path){ return require[path]; }
|
||||
#{code}
|
||||
return require['./coffee-script']
|
||||
}()
|
||||
(function(root) {
|
||||
var CoffeeScript = function() {
|
||||
function require(path){ return require[path]; }
|
||||
#{code}
|
||||
return require['./coffee-script'];
|
||||
}();
|
||||
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(function() { return CoffeeScript; });
|
||||
} else {
|
||||
root.CoffeeScript = CoffeeScript;
|
||||
}
|
||||
}(this));
|
||||
"""
|
||||
unless process.env.MINIFY is 'false'
|
||||
{parser, uglify} = require 'uglify-js'
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2011 Jeremy Ashkenas
|
||||
Copyright (c) 2009-2012 Jeremy Ashkenas
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Eat lunch.
|
||||
eat food for food in ['toast', 'cheese', 'wine']
|
||||
|
||||
# Fine dining
|
||||
courses = ['salad', 'entree', 'dessert']
|
||||
menu course + 1, dish for dish, course in courses
|
||||
# Fine five course dining.
|
||||
courses = ['greens', 'caviar', 'truffles', 'roast', 'cake']
|
||||
menu i + 1, dish for dish, i in courses
|
||||
|
||||
# Health conscious meal
|
||||
# Health conscious meal.
|
||||
foods = ['broccoli', 'spinach', 'chocolate']
|
||||
eat food for food in foods when food isnt 'chocolate'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
###
|
||||
CoffeeScript Compiler v1.1.3
|
||||
CoffeeScript Compiler v1.4.0
|
||||
Released under the MIT License
|
||||
###
|
||||
|
||||
|
||||
@@ -8,6 +8,5 @@ else
|
||||
|
||||
date = if friday then sue else jill
|
||||
|
||||
options or= defaults
|
||||
|
||||
|
||||
|
||||
@@ -3,3 +3,4 @@ hi = `function() {
|
||||
}`
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
solipsism = true if mind? and not world?
|
||||
|
||||
speed ?= 75
|
||||
speed = 0
|
||||
speed ?= 15
|
||||
|
||||
footprints = yeti ? "bear"
|
||||
|
||||
@@ -8,3 +9,5 @@ footprints = yeti ? "bear"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
html = '''
|
||||
html = """
|
||||
<strong>
|
||||
cup of coffeescript
|
||||
</strong>
|
||||
'''
|
||||
|
||||
|
||||
"""
|
||||
|
||||
|
||||
@@ -4,3 +4,6 @@ quote = "A picture is a fact. -- #{ author }"
|
||||
sentence = "#{ 22 / 7 } is a decent approximation of π"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,3 +5,5 @@ weatherReport = (location) ->
|
||||
[city, temp, forecast] = weatherReport "Berkeley, CA"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -11,3 +11,4 @@ futurists =
|
||||
{poet: {name, address: [street, city]}} = futurists
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,3 +4,6 @@ theSwitch = 0
|
||||
[theBait, theSwitch] = [theSwitch, theBait]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,3 +5,5 @@ tag = "<impossible>"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
|
||||
copy = numbers[0...numbers.length]
|
||||
start = numbers[0..2]
|
||||
|
||||
middle = copy[3..6]
|
||||
middle = numbers[3...6]
|
||||
|
||||
end = numbers[6..]
|
||||
|
||||
copy = numbers[..]
|
||||
|
||||
@@ -3,3 +3,5 @@ numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
numbers[3..6] = [-3, -4, -5, -6]
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,36 +1,40 @@
|
||||
<!DOCTYPE html> <html> <head> <title>browser.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> browser.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> <p>Override exported methods for non-Node.js engines.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s1">'./coffee-script'</span>
|
||||
<span class="nv">CoffeeScript.require = </span><span class="nx">require</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>Use standard JavaScript <code>eval</code> to eval code.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.eval = </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nb">eval</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Running code does not provide access to this scope.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.run = </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nv">options = </span><span class="p">{})</span> <span class="o">-></span>
|
||||
<!DOCTYPE html> <html> <head> <title>browser.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> browser.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> <p>Override exported methods for non-Node.js engines.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s">'./coffee-script'</span>
|
||||
<span class="nv">CoffeeScript.require = </span><span class="nx">require</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>Use standard JavaScript <code>eval</code> to eval code.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.eval = </span><span class="nf">(code, options = {}) -></span>
|
||||
<span class="nx">options</span><span class="p">.</span><span class="nx">bare</span> <span class="o">?=</span> <span class="kc">on</span>
|
||||
<span class="nb">eval</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Running code does not provide access to this scope.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.run = </span><span class="nf">(code, options = {}) -></span>
|
||||
<span class="nv">options.bare = </span><span class="kc">on</span>
|
||||
<span class="nb">Function</span><span class="p">(</span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)()</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>If we're not in a browser environment, we're finished with the public API.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">return</span> <span class="nx">unless</span> <span class="nb">window</span><span class="o">?</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Load a remote script from the current domain via XHR.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.load = </span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">xhr = </span><span class="k">new</span> <span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">ActiveXObject</span> <span class="o">or</span> <span class="nx">XMLHttpRequest</span><span class="p">)(</span><span class="s1">'Microsoft.XMLHTTP'</span><span class="p">)</span>
|
||||
<span class="nx">xhr</span><span class="p">.</span><span class="nx">open</span> <span class="s1">'GET'</span><span class="p">,</span> <span class="nx">url</span><span class="p">,</span> <span class="kc">true</span>
|
||||
<span class="nx">xhr</span><span class="p">.</span><span class="nx">overrideMimeType</span> <span class="s1">'text/plain'</span> <span class="k">if</span> <span class="s1">'overrideMimeType'</span> <span class="k">of</span> <span class="nx">xhr</span>
|
||||
<span class="nv">xhr.onreadystatechange = </span><span class="o">-></span>
|
||||
<span class="nb">Function</span><span class="p">(</span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)()</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>If we're not in a browser environment, we're finished with the public API.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">return</span> <span class="k">unless</span> <span class="nb">window</span><span class="o">?</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Load a remote script from the current domain via XHR.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.load = </span><span class="nf">(url, callback) -></span>
|
||||
<span class="nv">xhr = </span><span class="k">if</span> <span class="nb">window</span><span class="p">.</span><span class="nx">ActiveXObject</span>
|
||||
<span class="k">new</span> <span class="nb">window</span><span class="p">.</span><span class="nx">ActiveXObject</span><span class="p">(</span><span class="s">'Microsoft.XMLHTTP'</span><span class="p">)</span>
|
||||
<span class="k">else</span>
|
||||
<span class="k">new</span> <span class="nx">XMLHttpRequest</span><span class="p">()</span>
|
||||
<span class="nx">xhr</span><span class="p">.</span><span class="nx">open</span> <span class="s">'GET'</span><span class="p">,</span> <span class="nx">url</span><span class="p">,</span> <span class="kc">true</span>
|
||||
<span class="nx">xhr</span><span class="p">.</span><span class="nx">overrideMimeType</span> <span class="s">'text/plain'</span> <span class="k">if</span> <span class="s">'overrideMimeType'</span> <span class="k">of</span> <span class="nx">xhr</span>
|
||||
<span class="nv">xhr.onreadystatechange = </span><span class="nf">-></span>
|
||||
<span class="k">if</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">readyState</span> <span class="o">is</span> <span class="mi">4</span>
|
||||
<span class="k">if</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">status</span> <span class="k">in</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">200</span><span class="p">]</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">responseText</span>
|
||||
<span class="k">else</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"Could not load #{url}"</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">"Could not load </span><span class="si">#{</span><span class="nx">url</span><span class="si">}</span><span class="s">"</span>
|
||||
<span class="nx">callback</span><span class="p">()</span> <span class="k">if</span> <span class="nx">callback</span>
|
||||
<span class="nx">xhr</span><span class="p">.</span><span class="nx">send</span> <span class="kc">null</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Activate CoffeeScript in the browser by having it compile and evaluate
|
||||
all script tags with a content-type of <code>text/coffeescript</code>.
|
||||
This happens on page load.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">runScripts = </span><span class="o">-></span>
|
||||
<span class="nv">scripts = </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span> <span class="s1">'script'</span>
|
||||
<span class="nv">coffees = </span><span class="p">(</span><span class="nx">s</span> <span class="k">for</span> <span class="nx">s</span> <span class="k">in</span> <span class="nx">scripts</span> <span class="k">when</span> <span class="nx">s</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s1">'text/coffeescript'</span><span class="p">)</span>
|
||||
This happens on page load.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">runScripts = </span><span class="nf">-></span>
|
||||
<span class="nv">scripts = </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span> <span class="s">'script'</span>
|
||||
<span class="nv">coffees = </span><span class="p">(</span><span class="nx">s</span> <span class="k">for</span> <span class="nx">s</span> <span class="k">in</span> <span class="nx">scripts</span> <span class="k">when</span> <span class="nx">s</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s">'text/coffeescript'</span><span class="p">)</span>
|
||||
<span class="nv">index = </span><span class="mi">0</span>
|
||||
<span class="nv">length = </span><span class="nx">coffees</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nx">do</span> <span class="nv">execute = </span><span class="o">-></span>
|
||||
<span class="nx">do</span> <span class="nv">execute = </span><span class="nf">-></span>
|
||||
<span class="nv">script = </span><span class="nx">coffees</span><span class="p">[</span><span class="nx">index</span><span class="o">++</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="nx">script</span><span class="o">?</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s1">'text/coffeescript'</span>
|
||||
<span class="k">if</span> <span class="nx">script</span><span class="o">?</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s">'text/coffeescript'</span>
|
||||
<span class="k">if</span> <span class="nx">script</span><span class="p">.</span><span class="nx">src</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">load</span> <span class="nx">script</span><span class="p">.</span><span class="nx">src</span><span class="p">,</span> <span class="nx">execute</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">script</span><span class="p">.</span><span class="nx">innerHTML</span>
|
||||
<span class="nx">execute</span><span class="p">()</span>
|
||||
<span class="kc">null</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Listen for window load, both in browsers and in IE.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">if</span> <span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span>
|
||||
<span class="nx">addEventListener</span> <span class="s1">'DOMContentLoaded'</span><span class="p">,</span> <span class="nx">runScripts</span><span class="p">,</span> <span class="kc">no</span>
|
||||
<span class="nx">addEventListener</span> <span class="s">'DOMContentLoaded'</span><span class="p">,</span> <span class="nx">runScripts</span><span class="p">,</span> <span class="kc">no</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">attachEvent</span> <span class="s1">'onload'</span><span class="p">,</span> <span class="nx">runScripts</span>
|
||||
<span class="nx">attachEvent</span> <span class="s">'onload'</span><span class="p">,</span> <span class="nx">runScripts</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -4,46 +4,56 @@ for CoffeeScript. You define tasks with names and descriptions in a Cakefile,
|
||||
and can call them from the command line, or invoke them from other tasks.</p>
|
||||
|
||||
<p>Running <code>cake</code> with no arguments will print out a list of all the tasks in the
|
||||
current directory's Cakefile.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>External dependencies.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">fs = </span><span class="nx">require</span> <span class="s1">'fs'</span>
|
||||
<span class="nv">path = </span><span class="nx">require</span> <span class="s1">'path'</span>
|
||||
<span class="nv">helpers = </span><span class="nx">require</span> <span class="s1">'./helpers'</span>
|
||||
<span class="nv">optparse = </span><span class="nx">require</span> <span class="s1">'./optparse'</span>
|
||||
<span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s1">'./coffee-script'</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Keep track of the list of defined tasks, the accepted options, and so on.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">tasks = </span><span class="p">{}</span>
|
||||
current directory's Cakefile.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>External dependencies.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">fs = </span><span class="nx">require</span> <span class="s">'fs'</span>
|
||||
<span class="nv">path = </span><span class="nx">require</span> <span class="s">'path'</span>
|
||||
<span class="nv">helpers = </span><span class="nx">require</span> <span class="s">'./helpers'</span>
|
||||
<span class="nv">optparse = </span><span class="nx">require</span> <span class="s">'./optparse'</span>
|
||||
<span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s">'./coffee-script'</span>
|
||||
|
||||
<span class="nv">existsSync = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">existsSync</span> <span class="o">or</span> <span class="nx">path</span><span class="p">.</span><span class="nx">existsSync</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Keep track of the list of defined tasks, the accepted options, and so on.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">tasks = </span><span class="p">{}</span>
|
||||
<span class="nv">options = </span><span class="p">{}</span>
|
||||
<span class="nv">switches = </span><span class="p">[]</span>
|
||||
<span class="nv">oparse = </span><span class="kc">null</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Mixin the top-level Cake functions for Cakefiles to use directly.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">helpers</span><span class="p">.</span><span class="nx">extend</span> <span class="nx">global</span><span class="p">,</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Define a Cake task with a short name, an optional sentence description,
|
||||
and the function to run as the action itself.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">task</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">description</span><span class="p">,</span> <span class="nx">action</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="p">[</span><span class="nx">action</span><span class="p">,</span> <span class="nx">description</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">description</span><span class="p">,</span> <span class="nx">action</span><span class="p">]</span> <span class="nx">unless</span> <span class="nx">action</span>
|
||||
and the function to run as the action itself.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">task: </span><span class="nf">(name, description, action) -></span>
|
||||
<span class="p">[</span><span class="nx">action</span><span class="p">,</span> <span class="nx">description</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">description</span><span class="p">,</span> <span class="nx">action</span><span class="p">]</span> <span class="k">unless</span> <span class="nx">action</span>
|
||||
<span class="nx">tasks</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="nx">name</span><span class="p">,</span> <span class="nx">description</span><span class="p">,</span> <span class="nx">action</span><span class="p">}</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Define an option that the Cakefile accepts. The parsed options hash,
|
||||
containing all of the command-line options passed, will be made available
|
||||
as the first argument to the action.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">option</span><span class="o">:</span> <span class="p">(</span><span class="nx">letter</span><span class="p">,</span> <span class="nx">flag</span><span class="p">,</span> <span class="nx">description</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">switches</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="nx">letter</span><span class="p">,</span> <span class="nx">flag</span><span class="p">,</span> <span class="nx">description</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Invoke another task in the current Cakefile.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">invoke</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">missingTask</span> <span class="nx">name</span> <span class="nx">unless</span> <span class="nx">tasks</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span>
|
||||
as the first argument to the action.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">option: </span><span class="nf">(letter, flag, description) -></span>
|
||||
<span class="nx">switches</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="nx">letter</span><span class="p">,</span> <span class="nx">flag</span><span class="p">,</span> <span class="nx">description</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Invoke another task in the current Cakefile.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">invoke: </span><span class="nf">(name) -></span>
|
||||
<span class="nx">missingTask</span> <span class="nx">name</span> <span class="k">unless</span> <span class="nx">tasks</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span>
|
||||
<span class="nx">tasks</span><span class="p">[</span><span class="nx">name</span><span class="p">].</span><span class="nx">action</span> <span class="nx">options</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>Run <code>cake</code>. Executes all of the tasks you pass, in order. Note that Node's
|
||||
asynchrony may cause tasks to execute in a different order than you'd expect.
|
||||
If no tasks are passed, print the help screen. Keep a reference to the
|
||||
original directory name, when running Cake tasks from subdirectories. </p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.run = </span><span class="o">-></span>
|
||||
<span class="nv">global.__originalDirname = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span> <span class="s1">'.'</span>
|
||||
If no tasks are passed, print the help screen. Keep a reference to the
|
||||
original directory name, when running Cake tasks from subdirectories.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.run = </span><span class="nf">-></span>
|
||||
<span class="nv">global.__originalDirname = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span> <span class="s">'.'</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">chdir</span> <span class="nx">cakefileDirectory</span> <span class="nx">__originalDirname</span>
|
||||
<span class="nv">args = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">.</span><span class="nx">slice</span> <span class="mi">2</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="s1">'Cakefile'</span><span class="p">).</span><span class="nx">toString</span><span class="p">(),</span> <span class="nx">filename</span><span class="o">:</span> <span class="s1">'Cakefile'</span>
|
||||
<span class="nv">args = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">..]</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="s">'Cakefile'</span><span class="p">).</span><span class="nx">toString</span><span class="p">(),</span> <span class="nv">filename: </span><span class="s">'Cakefile'</span>
|
||||
<span class="nv">oparse = </span><span class="k">new</span> <span class="nx">optparse</span><span class="p">.</span><span class="nx">OptionParser</span> <span class="nx">switches</span>
|
||||
<span class="k">return</span> <span class="nx">printTasks</span><span class="p">()</span> <span class="nx">unless</span> <span class="nx">args</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">options = </span><span class="nx">oparse</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">args</span><span class="p">)</span>
|
||||
<span class="nx">invoke</span> <span class="nx">arg</span> <span class="k">for</span> <span class="nx">arg</span> <span class="k">in</span> <span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Display the list of Cake tasks in a format similar to <code>rake -T</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">printTasks = </span><span class="o">-></span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s1">''</span>
|
||||
<span class="k">return</span> <span class="nx">printTasks</span><span class="p">()</span> <span class="k">unless</span> <span class="nx">args</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="k">try</span>
|
||||
<span class="nv">options = </span><span class="nx">oparse</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">args</span><span class="p">)</span>
|
||||
<span class="k">catch</span> <span class="nx">e</span>
|
||||
<span class="k">return</span> <span class="nx">fatalError</span> <span class="s">"</span><span class="si">#{</span><span class="nx">e</span><span class="si">}</span><span class="s">"</span>
|
||||
<span class="nx">invoke</span> <span class="nx">arg</span> <span class="k">for</span> <span class="nx">arg</span> <span class="k">in</span> <span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Display the list of Cake tasks in a format similar to <code>rake -T</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">printTasks = </span><span class="nf">-></span>
|
||||
<span class="nv">relative = </span><span class="nx">path</span><span class="p">.</span><span class="nx">relative</span> <span class="o">or</span> <span class="nx">path</span><span class="p">.</span><span class="nx">resolve</span>
|
||||
<span class="nv">cakefilePath = </span><span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">relative</span><span class="p">(</span><span class="nx">__originalDirname</span><span class="p">,</span> <span class="nx">process</span><span class="p">.</span><span class="nx">cwd</span><span class="p">()),</span> <span class="s">'Cakefile'</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s">"</span><span class="si">#{</span><span class="nx">cakefilePath</span><span class="si">}</span><span class="s"> defines the following tasks:\n"</span>
|
||||
<span class="k">for</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">task</span> <span class="k">of</span> <span class="nx">tasks</span>
|
||||
<span class="nv">spaces = </span><span class="mi">20</span> <span class="o">-</span> <span class="nx">name</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">spaces = </span><span class="k">if</span> <span class="nx">spaces</span> <span class="o">></span> <span class="mi">0</span> <span class="k">then</span> <span class="nb">Array</span><span class="p">(</span><span class="nx">spaces</span> <span class="o">+</span> <span class="mi">1</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s1">' '</span><span class="p">)</span> <span class="k">else</span> <span class="s1">''</span>
|
||||
<span class="nv">desc = </span><span class="k">if</span> <span class="nx">task</span><span class="p">.</span><span class="nx">description</span> <span class="k">then</span> <span class="s2">"# #{task.description}"</span> <span class="k">else</span> <span class="s1">''</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s2">"cake #{name}#{spaces} #{desc}"</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="nx">oparse</span><span class="p">.</span><span class="nx">help</span><span class="p">()</span> <span class="k">if</span> <span class="nx">switches</span><span class="p">.</span><span class="nx">length</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Print an error and exit when attempting to call an undefined task.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">missingTask = </span><span class="p">(</span><span class="nx">task</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s2">"No such task: \"#{task}\""</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>When <code>cake</code> is invoked, search in the current and all parent directories
|
||||
to find the relevant Cakefile.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">cakefileDirectory = </span><span class="p">(</span><span class="nx">dir</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="nx">dir</span> <span class="k">if</span> <span class="nx">path</span><span class="p">.</span><span class="nx">existsSync</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">dir</span><span class="p">,</span> <span class="s1">'Cakefile'</span>
|
||||
<span class="nv">parent = </span><span class="nx">path</span><span class="p">.</span><span class="nx">normalize</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">dir</span><span class="p">,</span> <span class="s1">'..'</span>
|
||||
<span class="k">return</span> <span class="nx">cakefileDirectory</span> <span class="nx">parent</span> <span class="nx">unless</span> <span class="nx">parent</span> <span class="o">is</span> <span class="nx">dir</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"Cakefile not found in #{process.cwd()}"</span>
|
||||
<span class="nv">spaces = </span><span class="k">if</span> <span class="nx">spaces</span> <span class="o">></span> <span class="mi">0</span> <span class="k">then</span> <span class="nb">Array</span><span class="p">(</span><span class="nx">spaces</span> <span class="o">+</span> <span class="mi">1</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s">' '</span><span class="p">)</span> <span class="k">else</span> <span class="s">''</span>
|
||||
<span class="nv">desc = </span><span class="k">if</span> <span class="nx">task</span><span class="p">.</span><span class="nx">description</span> <span class="k">then</span> <span class="s">"</span><span class="err">#</span><span class="s"> </span><span class="si">#{</span><span class="nx">task</span><span class="p">.</span><span class="nx">description</span><span class="si">}</span><span class="s">"</span> <span class="k">else</span> <span class="s">''</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s">"cake </span><span class="si">#{</span><span class="nx">name</span><span class="si">}#{</span><span class="nx">spaces</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="nx">desc</span><span class="si">}</span><span class="s">"</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="nx">oparse</span><span class="p">.</span><span class="nx">help</span><span class="p">()</span> <span class="k">if</span> <span class="nx">switches</span><span class="p">.</span><span class="nx">length</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Print an error and exit when attempting to use an invalid task/option.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">fatalError = </span><span class="nf">(message) -></span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span> <span class="nx">message</span> <span class="o">+</span> <span class="s">'\n'</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s">'To see a list of all tasks/options, run "cake"'</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span>
|
||||
|
||||
<span class="nv">missingTask = </span><span class="nf">(task) -></span> <span class="nx">fatalError</span> <span class="s">"No such task: </span><span class="si">#{</span><span class="nx">task</span><span class="si">}</span><span class="s">"</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>When <code>cake</code> is invoked, search in the current and all parent directories
|
||||
to find the relevant Cakefile.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">cakefileDirectory = </span><span class="nf">(dir) -></span>
|
||||
<span class="k">return</span> <span class="nx">dir</span> <span class="k">if</span> <span class="nx">existsSync</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">dir</span><span class="p">,</span> <span class="s">'Cakefile'</span>
|
||||
<span class="nv">parent = </span><span class="nx">path</span><span class="p">.</span><span class="nx">normalize</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">dir</span><span class="p">,</span> <span class="s">'..'</span>
|
||||
<span class="k">return</span> <span class="nx">cakefileDirectory</span> <span class="nx">parent</span> <span class="k">unless</span> <span class="nx">parent</span> <span class="o">is</span> <span class="nx">dir</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">"Cakefile not found in </span><span class="si">#{</span><span class="nx">process</span><span class="p">.</span><span class="nx">cwd</span><span class="p">()</span><span class="si">}</span><span class="s">"</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -4,37 +4,44 @@ contains the main entry functions for tokenizing, parsing, and compiling
|
||||
source CoffeeScript into JavaScript.</p>
|
||||
|
||||
<p>If included on a webpage, it will automatically sniff out, compile, and
|
||||
execute all scripts present in <code>text/coffeescript</code> tags.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">fs = </span><span class="nx">require</span> <span class="s1">'fs'</span>
|
||||
<span class="nv">path = </span><span class="nx">require</span> <span class="s1">'path'</span>
|
||||
<span class="p">{</span><span class="nx">Lexer</span><span class="p">,</span><span class="nx">RESERVED</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'./lexer'</span>
|
||||
<span class="p">{</span><span class="nx">parser</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'./parser'</span>
|
||||
<span class="nv">vm = </span><span class="nx">require</span> <span class="s1">'vm'</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>TODO: Remove registerExtension when fully deprecated.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">if</span> <span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span>
|
||||
<span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span><span class="p">[</span><span class="s1">'.coffee'</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="nx">module</span><span class="p">,</span> <span class="nx">filename</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">content = </span><span class="nx">compile</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="nx">filename</span><span class="p">,</span> <span class="s1">'utf8'</span><span class="p">),</span> <span class="p">{</span><span class="nx">filename</span><span class="p">}</span>
|
||||
<span class="nx">module</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">content</span><span class="p">,</span> <span class="nx">filename</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">require</span><span class="p">.</span><span class="nx">registerExtension</span>
|
||||
<span class="nx">require</span><span class="p">.</span><span class="nx">registerExtension</span> <span class="s1">'.coffee'</span><span class="p">,</span> <span class="p">(</span><span class="nx">content</span><span class="p">)</span> <span class="o">-></span> <span class="nx">compile</span> <span class="nx">content</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>The current CoffeeScript version number.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.VERSION = </span><span class="s1">'1.1.3'</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Words that cannot be used as identifiers in CoffeeScript code</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.RESERVED = </span><span class="nx">RESERVED</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Expose helpers for testing.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.helpers = </span><span class="nx">require</span> <span class="s1">'./helpers'</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
|
||||
compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.compile = compile = </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nv">options = </span><span class="p">{})</span> <span class="o">-></span>
|
||||
execute all scripts present in <code>text/coffeescript</code> tags.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">fs = </span><span class="nx">require</span> <span class="s">'fs'</span>
|
||||
<span class="nv">path = </span><span class="nx">require</span> <span class="s">'path'</span>
|
||||
<span class="p">{</span><span class="nx">Lexer</span><span class="p">,</span><span class="nx">RESERVED</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">'./lexer'</span>
|
||||
<span class="p">{</span><span class="nx">parser</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">'./parser'</span>
|
||||
<span class="nv">vm = </span><span class="nx">require</span> <span class="s">'vm'</span>
|
||||
|
||||
<span class="nv">stripBOM = </span><span class="nf">(content) -></span>
|
||||
<span class="k">if</span> <span class="nx">content</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">is</span> <span class="mh">0xFEFF</span> <span class="k">then</span> <span class="nx">content</span><span class="p">.</span><span class="nx">substring</span> <span class="mi">1</span> <span class="k">else</span> <span class="nx">content</span>
|
||||
|
||||
<span class="k">if</span> <span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span>
|
||||
<span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span><span class="p">[</span><span class="s">'.coffee'</span><span class="p">]</span> <span class="o">=</span> <span class="nf">(module, filename) -></span>
|
||||
<span class="nv">content = </span><span class="nx">compile</span> <span class="nx">stripBOM</span><span class="p">(</span><span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span> <span class="nx">filename</span><span class="p">,</span> <span class="s">'utf8'</span><span class="p">),</span> <span class="p">{</span><span class="nx">filename</span><span class="p">}</span>
|
||||
<span class="nx">module</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">content</span><span class="p">,</span> <span class="nx">filename</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>The current CoffeeScript version number.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.VERSION = </span><span class="s">'1.4.0'</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Words that cannot be used as identifiers in CoffeeScript code</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.RESERVED = </span><span class="nx">RESERVED</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Expose helpers for testing.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.helpers = </span><span class="nx">require</span> <span class="s">'./helpers'</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
|
||||
compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.compile = compile = </span><span class="nf">(code, options = {}) -></span>
|
||||
<span class="p">{</span><span class="nx">merge</span><span class="p">}</span> <span class="o">=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">helpers</span>
|
||||
<span class="k">try</span>
|
||||
<span class="p">(</span><span class="nx">parser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="nx">code</span><span class="p">).</span><span class="nx">compile</span> <span class="nx">options</span>
|
||||
<span class="nv">js = </span><span class="p">(</span><span class="nx">parser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="nx">code</span><span class="p">).</span><span class="nx">compile</span> <span class="nx">options</span>
|
||||
<span class="k">return</span> <span class="nx">js</span> <span class="k">unless</span> <span class="nx">options</span><span class="p">.</span><span class="nx">header</span>
|
||||
<span class="k">catch</span> <span class="nx">err</span>
|
||||
<span class="nv">err.message = </span><span class="s2">"In #{options.filename}, #{err.message}"</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span>
|
||||
<span class="k">throw</span> <span class="nx">err</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Tokenize a string of CoffeeScript code, and return the array of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.tokens = </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>Parse a string of CoffeeScript code or an array of lexed tokens, and
|
||||
<span class="nv">err.message = </span><span class="s">"In </span><span class="si">#{</span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span><span class="si">}</span><span class="s">, </span><span class="si">#{</span><span class="nx">err</span><span class="p">.</span><span class="nx">message</span><span class="si">}</span><span class="s">"</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span>
|
||||
<span class="k">throw</span> <span class="nx">err</span>
|
||||
<span class="nv">header = </span><span class="s">"Generated by CoffeeScript </span><span class="si">#{</span><span class="nx">@VERSION</span><span class="si">}</span><span class="s">"</span>
|
||||
<span class="s">"// </span><span class="si">#{</span><span class="nx">header</span><span class="si">}</span><span class="s">\n</span><span class="si">#{</span><span class="nx">js</span><span class="si">}</span><span class="s">"</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Tokenize a string of CoffeeScript code, and return the array of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.tokens = </span><span class="nf">(code, options) -></span>
|
||||
<span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Parse a string of CoffeeScript code or an array of lexed tokens, and
|
||||
return the AST. You can then compile it by calling <code>.compile()</code> on the root,
|
||||
or traverse it by using <code>.traverse()</code> with a callback.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.nodes = </span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="k">typeof</span> <span class="nx">source</span> <span class="o">is</span> <span class="s1">'string'</span>
|
||||
or traverse it by using <code>.traverseChildren()</code> with a callback.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.nodes = </span><span class="nf">(source, options) -></span>
|
||||
<span class="k">if</span> <span class="k">typeof</span> <span class="nx">source</span> <span class="o">is</span> <span class="s">'string'</span>
|
||||
<span class="nx">parser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">options</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">parser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">source</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Compile and execute a string of CoffeeScript (on the server), correctly
|
||||
setting <code>__filename</code>, <code>__dirname</code>, and relative <code>require()</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.run = </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">mainModule = </span><span class="nx">require</span><span class="p">.</span><span class="nx">main</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Set the filename.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">mainModule.filename = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span>
|
||||
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span> <span class="k">then</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span><span class="p">)</span> <span class="k">else</span> <span class="s1">'.'</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Clear the module cache.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">mainModule</span><span class="p">.</span><span class="nx">moduleCache</span> <span class="o">and=</span> <span class="p">{}</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Assign paths for node_modules loading</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">mainModule.paths = </span><span class="nx">require</span><span class="p">(</span><span class="s1">'module'</span><span class="p">).</span><span class="nx">_nodeModulePaths</span> <span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Compile.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">mainModule</span><span class="p">.</span><span class="nx">filename</span><span class="p">)</span> <span class="o">isnt</span> <span class="s1">'.coffee'</span> <span class="o">or</span> <span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span>
|
||||
<span class="nx">parser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">source</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>Compile and execute a string of CoffeeScript (on the server), correctly
|
||||
setting <code>__filename</code>, <code>__dirname</code>, and relative <code>require()</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.run = </span><span class="nf">(code, options = {}) -></span>
|
||||
<span class="nv">mainModule = </span><span class="nx">require</span><span class="p">.</span><span class="nx">main</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Set the filename.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">mainModule.filename = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span>
|
||||
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span> <span class="k">then</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span><span class="p">)</span> <span class="k">else</span> <span class="s">'.'</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Clear the module cache.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">mainModule</span><span class="p">.</span><span class="nx">moduleCache</span> <span class="o">and=</span> <span class="p">{}</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Assign paths for node_modules loading</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">mainModule.paths = </span><span class="nx">require</span><span class="p">(</span><span class="s">'module'</span><span class="p">).</span><span class="nx">_nodeModulePaths</span> <span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Compile.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">mainModule</span><span class="p">.</span><span class="nx">filename</span><span class="p">)</span> <span class="o">isnt</span> <span class="s">'.coffee'</span> <span class="o">or</span> <span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span>
|
||||
<span class="nx">mainModule</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">compile</span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">),</span> <span class="nx">mainModule</span><span class="p">.</span><span class="nx">filename</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">mainModule</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">mainModule</span><span class="p">.</span><span class="nx">filename</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Compile and evaluate a string of CoffeeScript (in a Node.js-like environment).
|
||||
The CoffeeScript REPL uses this to run the input.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.eval = </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nv">options = </span><span class="p">{})</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="nx">unless</span> <span class="nv">code = </span><span class="nx">code</span><span class="p">.</span><span class="nx">trim</span><span class="p">()</span>
|
||||
<span class="nx">mainModule</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">mainModule</span><span class="p">.</span><span class="nx">filename</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Compile and evaluate a string of CoffeeScript (in a Node.js-like environment).
|
||||
The CoffeeScript REPL uses this to run the input.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.eval = </span><span class="nf">(code, options = {}) -></span>
|
||||
<span class="k">return</span> <span class="k">unless</span> <span class="nv">code = </span><span class="nx">code</span><span class="p">.</span><span class="nx">trim</span><span class="p">()</span>
|
||||
<span class="nv">Script = </span><span class="nx">vm</span><span class="p">.</span><span class="nx">Script</span>
|
||||
<span class="k">if</span> <span class="nx">Script</span>
|
||||
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sandbox</span><span class="o">?</span>
|
||||
@@ -42,36 +49,36 @@ The CoffeeScript REPL uses this to run the input.</p> </td>
|
||||
<span class="nv">sandbox = </span><span class="nx">options</span><span class="p">.</span><span class="nx">sandbox</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">sandbox = </span><span class="nx">Script</span><span class="p">.</span><span class="nx">createContext</span><span class="p">()</span>
|
||||
<span class="nx">sandbox</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">v</span> <span class="k">for</span> <span class="nx">own</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sandbox</span>
|
||||
<span class="nx">sandbox</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">v</span> <span class="k">for</span> <span class="k">own</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sandbox</span>
|
||||
<span class="nv">sandbox.global = sandbox.root = sandbox.GLOBAL = </span><span class="nx">sandbox</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">sandbox = </span><span class="nx">global</span>
|
||||
<span class="nv">sandbox.__filename = </span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span> <span class="o">||</span> <span class="s1">'eval'</span>
|
||||
<span class="nv">sandbox.__dirname = </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">__filename</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>define module/require only if they chose not to specify their own</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">unless</span> <span class="nx">sandbox</span> <span class="o">isnt</span> <span class="nx">global</span> <span class="o">or</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">module</span> <span class="o">or</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">require</span>
|
||||
<span class="nv">Module = </span><span class="nx">require</span> <span class="s1">'module'</span>
|
||||
<span class="nv">sandbox.module = _module = </span><span class="k">new</span> <span class="nx">Module</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">modulename</span> <span class="o">||</span> <span class="s1">'eval'</span><span class="p">)</span>
|
||||
<span class="nv">sandbox.require = _require = </span><span class="p">(</span><span class="nx">path</span><span class="p">)</span> <span class="o">-></span> <span class="nx">Module</span><span class="p">.</span><span class="nx">_load</span> <span class="nx">path</span><span class="p">,</span> <span class="nx">_module</span><span class="p">,</span> <span class="kc">true</span>
|
||||
<span class="nv">sandbox.__filename = </span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span> <span class="o">||</span> <span class="s">'eval'</span>
|
||||
<span class="nv">sandbox.__dirname = </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">__filename</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>define module/require only if they chose not to specify their own</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">unless</span> <span class="nx">sandbox</span> <span class="o">isnt</span> <span class="nx">global</span> <span class="o">or</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">module</span> <span class="o">or</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">require</span>
|
||||
<span class="nv">Module = </span><span class="nx">require</span> <span class="s">'module'</span>
|
||||
<span class="nv">sandbox.module = _module = </span><span class="k">new</span> <span class="nx">Module</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">modulename</span> <span class="o">||</span> <span class="s">'eval'</span><span class="p">)</span>
|
||||
<span class="nv">sandbox.require = _require = </span><span class="nf">(path) -></span> <span class="nx">Module</span><span class="p">.</span><span class="nx">_load</span> <span class="nx">path</span><span class="p">,</span> <span class="nx">_module</span><span class="p">,</span> <span class="kc">true</span>
|
||||
<span class="nv">_module.filename = </span><span class="nx">sandbox</span><span class="p">.</span><span class="nx">__filename</span>
|
||||
<span class="nx">_require</span><span class="p">[</span><span class="nx">r</span><span class="p">]</span> <span class="o">=</span> <span class="nx">require</span><span class="p">[</span><span class="nx">r</span><span class="p">]</span> <span class="k">for</span> <span class="nx">r</span> <span class="k">in</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">getOwnPropertyNames</span> <span class="nx">require</span> <span class="k">when</span> <span class="nx">r</span> <span class="o">isnt</span> <span class="s1">'paths'</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>use the same hack node currently uses for their own REPL</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">_require.paths = _module.paths = </span><span class="nx">Module</span><span class="p">.</span><span class="nx">_nodeModulePaths</span> <span class="nx">process</span><span class="p">.</span><span class="nx">cwd</span><span class="p">()</span>
|
||||
<span class="nv">_require.resolve = </span><span class="p">(</span><span class="nx">request</span><span class="p">)</span> <span class="o">-></span> <span class="nx">Module</span><span class="p">.</span><span class="nx">_resolveFilename</span> <span class="nx">request</span><span class="p">,</span> <span class="nx">_module</span>
|
||||
<span class="nx">_require</span><span class="p">[</span><span class="nx">r</span><span class="p">]</span> <span class="o">=</span> <span class="nx">require</span><span class="p">[</span><span class="nx">r</span><span class="p">]</span> <span class="k">for</span> <span class="nx">r</span> <span class="k">in</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">getOwnPropertyNames</span> <span class="nx">require</span> <span class="k">when</span> <span class="nx">r</span> <span class="o">isnt</span> <span class="s">'paths'</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>use the same hack node currently uses for their own REPL</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">_require.paths = _module.paths = </span><span class="nx">Module</span><span class="p">.</span><span class="nx">_nodeModulePaths</span> <span class="nx">process</span><span class="p">.</span><span class="nx">cwd</span><span class="p">()</span>
|
||||
<span class="nv">_require.resolve = </span><span class="nf">(request) -></span> <span class="nx">Module</span><span class="p">.</span><span class="nx">_resolveFilename</span> <span class="nx">request</span><span class="p">,</span> <span class="nx">_module</span>
|
||||
<span class="nv">o = </span><span class="p">{}</span>
|
||||
<span class="nx">o</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">v</span> <span class="k">for</span> <span class="nx">own</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">options</span>
|
||||
<span class="nx">o</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">v</span> <span class="k">for</span> <span class="k">own</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">options</span>
|
||||
<span class="nv">o.bare = </span><span class="kc">on</span> <span class="c1"># ensure return value</span>
|
||||
<span class="nv">js = </span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">o</span>
|
||||
<span class="k">if</span> <span class="nx">sandbox</span> <span class="o">is</span> <span class="nx">global</span>
|
||||
<span class="nx">vm</span><span class="p">.</span><span class="nx">runInThisContext</span> <span class="nx">js</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">vm</span><span class="p">.</span><span class="nx">runInContext</span> <span class="nx">js</span><span class="p">,</span> <span class="nx">sandbox</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <p>Instantiate a Lexer for our use here.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lexer = </span><span class="k">new</span> <span class="nx">Lexer</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <p>The real Lexer produces a generic stream of tokens. This object provides a
|
||||
<span class="nx">vm</span><span class="p">.</span><span class="nx">runInContext</span> <span class="nx">js</span><span class="p">,</span> <span class="nx">sandbox</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>Instantiate a Lexer for our use here.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lexer = </span><span class="k">new</span> <span class="nx">Lexer</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <p>The real Lexer produces a generic stream of tokens. This object provides a
|
||||
thin wrapper around it, compatible with the Jison API. We can then pass it
|
||||
directly as a "Jison lexer".</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">parser.lexer =</span>
|
||||
<span class="nx">lex</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="p">[</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">@yytext</span><span class="p">,</span> <span class="nx">@yylineno</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">@pos</span><span class="o">++</span><span class="p">]</span> <span class="o">or</span> <span class="p">[</span><span class="s1">''</span><span class="p">]</span>
|
||||
<span class="nv">lex: </span><span class="nf">-></span>
|
||||
<span class="p">[</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">@yytext</span><span class="p">,</span> <span class="nx">@yylineno</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">@pos</span><span class="o">++</span><span class="p">]</span> <span class="o">or</span> <span class="p">[</span><span class="s">''</span><span class="p">]</span>
|
||||
<span class="nx">tag</span>
|
||||
<span class="nx">setInput</span><span class="o">:</span> <span class="p">(</span><span class="nx">@tokens</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">setInput: </span><span class="nf">(@tokens) -></span>
|
||||
<span class="vi">@pos = </span><span class="mi">0</span>
|
||||
<span class="nx">upcomingInput</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="s2">""</span>
|
||||
<span class="nv">upcomingInput: </span><span class="nf">-></span>
|
||||
<span class="s">""</span>
|
||||
|
||||
<span class="nv">parser.yy = </span><span class="nx">require</span> <span class="s1">'./nodes'</span>
|
||||
<span class="nv">parser.yy = </span><span class="nx">require</span> <span class="s">'./nodes'</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -2,197 +2,265 @@
|
||||
into various forms: saved into <code>.js</code> files or printed to stdout, piped to
|
||||
<a href="http://javascriptlint.com/">JavaScript Lint</a> or recompiled every time the source is
|
||||
saved, printed as a token stream or as the syntax tree, or launch an
|
||||
interactive REPL.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>External dependencies.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">fs = </span><span class="nx">require</span> <span class="s1">'fs'</span>
|
||||
<span class="nv">path = </span><span class="nx">require</span> <span class="s1">'path'</span>
|
||||
<span class="nv">helpers = </span><span class="nx">require</span> <span class="s1">'./helpers'</span>
|
||||
<span class="nv">optparse = </span><span class="nx">require</span> <span class="s1">'./optparse'</span>
|
||||
<span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s1">'./coffee-script'</span>
|
||||
<span class="p">{</span><span class="nx">spawn</span><span class="p">,</span> <span class="nx">exec</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'child_process'</span>
|
||||
<span class="p">{</span><span class="nx">EventEmitter</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'events'</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Allow CoffeeScript to emit Node.js events.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">helpers</span><span class="p">.</span><span class="nx">extend</span> <span class="nx">CoffeeScript</span><span class="p">,</span> <span class="k">new</span> <span class="nx">EventEmitter</span>
|
||||
interactive REPL.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>External dependencies.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">fs = </span><span class="nx">require</span> <span class="s">'fs'</span>
|
||||
<span class="nv">path = </span><span class="nx">require</span> <span class="s">'path'</span>
|
||||
<span class="nv">helpers = </span><span class="nx">require</span> <span class="s">'./helpers'</span>
|
||||
<span class="nv">optparse = </span><span class="nx">require</span> <span class="s">'./optparse'</span>
|
||||
<span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s">'./coffee-script'</span>
|
||||
<span class="p">{</span><span class="nx">spawn</span><span class="p">,</span> <span class="nx">exec</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">'child_process'</span>
|
||||
<span class="p">{</span><span class="nx">EventEmitter</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">'events'</span>
|
||||
|
||||
<span class="nv">printLine = </span><span class="p">(</span><span class="nx">line</span><span class="p">)</span> <span class="o">-></span> <span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="nx">line</span> <span class="o">+</span> <span class="s1">'\n'</span>
|
||||
<span class="nv">printWarn = </span><span class="p">(</span><span class="nx">line</span><span class="p">)</span> <span class="o">-></span> <span class="nx">process</span><span class="p">.</span><span class="nx">stderr</span><span class="p">.</span><span class="nx">write</span> <span class="nx">line</span> <span class="o">+</span> <span class="s1">'\n'</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>The help banner that is printed when <code>coffee</code> is called without arguments.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BANNER = </span><span class="s1">'''</span>
|
||||
<span class="s1"> Usage: coffee [options] path/to/script.coffee</span>
|
||||
<span class="nv">exists = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">exists</span> <span class="o">or</span> <span class="nx">path</span><span class="p">.</span><span class="nx">exists</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Allow CoffeeScript to emit Node.js events.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">helpers</span><span class="p">.</span><span class="nx">extend</span> <span class="nx">CoffeeScript</span><span class="p">,</span> <span class="k">new</span> <span class="nx">EventEmitter</span>
|
||||
|
||||
<span class="s1"> If called without options, `coffee` will run your script.</span>
|
||||
<span class="s1"> '''</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>The list of all the valid option flags that <code>coffee</code> knows how to handle.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">SWITCHES = </span><span class="p">[</span>
|
||||
<span class="p">[</span><span class="s1">'-b'</span><span class="p">,</span> <span class="s1">'--bare'</span><span class="p">,</span> <span class="s1">'compile without a top-level function wrapper'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-c'</span><span class="p">,</span> <span class="s1">'--compile'</span><span class="p">,</span> <span class="s1">'compile to JavaScript and save as .js files'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-e'</span><span class="p">,</span> <span class="s1">'--eval'</span><span class="p">,</span> <span class="s1">'pass a string from the command line as input'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-h'</span><span class="p">,</span> <span class="s1">'--help'</span><span class="p">,</span> <span class="s1">'display this help message'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-i'</span><span class="p">,</span> <span class="s1">'--interactive'</span><span class="p">,</span> <span class="s1">'run an interactive CoffeeScript REPL'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-j'</span><span class="p">,</span> <span class="s1">'--join [FILE]'</span><span class="p">,</span> <span class="s1">'concatenate the source CoffeeScript before compiling'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-l'</span><span class="p">,</span> <span class="s1">'--lint'</span><span class="p">,</span> <span class="s1">'pipe the compiled JavaScript through JavaScript Lint'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-n'</span><span class="p">,</span> <span class="s1">'--nodes'</span><span class="p">,</span> <span class="s1">'print out the parse tree that the parser produces'</span><span class="p">]</span>
|
||||
<span class="p">[</span> <span class="s1">'--nodejs [ARGS]'</span><span class="p">,</span> <span class="s1">'pass options directly to the "node" binary'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-o'</span><span class="p">,</span> <span class="s1">'--output [DIR]'</span><span class="p">,</span> <span class="s1">'set the output directory for compiled JavaScript'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-p'</span><span class="p">,</span> <span class="s1">'--print'</span><span class="p">,</span> <span class="s1">'print out the compiled JavaScript'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-r'</span><span class="p">,</span> <span class="s1">'--require [FILE*]'</span><span class="p">,</span> <span class="s1">'require a library before executing your script'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-s'</span><span class="p">,</span> <span class="s1">'--stdio'</span><span class="p">,</span> <span class="s1">'listen for and compile scripts over stdio'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-t'</span><span class="p">,</span> <span class="s1">'--tokens'</span><span class="p">,</span> <span class="s1">'print out the tokens that the lexer/rewriter produce'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-v'</span><span class="p">,</span> <span class="s1">'--version'</span><span class="p">,</span> <span class="s1">'display the version number'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-w'</span><span class="p">,</span> <span class="s1">'--watch'</span><span class="p">,</span> <span class="s1">'watch scripts for changes and rerun commands'</span><span class="p">]</span>
|
||||
<span class="nv">printLine = </span><span class="nf">(line) -></span> <span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="nx">line</span> <span class="o">+</span> <span class="s">'\n'</span>
|
||||
<span class="nv">printWarn = </span><span class="nf">(line) -></span> <span class="nx">process</span><span class="p">.</span><span class="nx">stderr</span><span class="p">.</span><span class="nx">write</span> <span class="nx">line</span> <span class="o">+</span> <span class="s">'\n'</span>
|
||||
|
||||
<span class="nv">hidden = </span><span class="nf">(file) -></span> <span class="o">/^</span><span class="err">\</span><span class="p">.</span><span class="o">|~</span><span class="nx">$</span><span class="o">/</span><span class="p">.</span><span class="nx">test</span> <span class="nx">file</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>The help banner that is printed when <code>coffee</code> is called without arguments.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BANNER = </span><span class="s">'''</span>
|
||||
<span class="s"> Usage: coffee [options] path/to/script.coffee -- [args]</span>
|
||||
|
||||
<span class="s"> If called without options, `coffee` will run your script.</span>
|
||||
<span class="s">'''</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>The list of all the valid option flags that <code>coffee</code> knows how to handle.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">SWITCHES = </span><span class="p">[</span>
|
||||
<span class="p">[</span><span class="s">'-b'</span><span class="p">,</span> <span class="s">'--bare'</span><span class="p">,</span> <span class="s">'compile without a top-level function wrapper'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-c'</span><span class="p">,</span> <span class="s">'--compile'</span><span class="p">,</span> <span class="s">'compile to JavaScript and save as .js files'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-e'</span><span class="p">,</span> <span class="s">'--eval'</span><span class="p">,</span> <span class="s">'pass a string from the command line as input'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-h'</span><span class="p">,</span> <span class="s">'--help'</span><span class="p">,</span> <span class="s">'display this help message'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-i'</span><span class="p">,</span> <span class="s">'--interactive'</span><span class="p">,</span> <span class="s">'run an interactive CoffeeScript REPL'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-j'</span><span class="p">,</span> <span class="s">'--join [FILE]'</span><span class="p">,</span> <span class="s">'concatenate the source CoffeeScript before compiling'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-l'</span><span class="p">,</span> <span class="s">'--lint'</span><span class="p">,</span> <span class="s">'pipe the compiled JavaScript through JavaScript Lint'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-n'</span><span class="p">,</span> <span class="s">'--nodes'</span><span class="p">,</span> <span class="s">'print out the parse tree that the parser produces'</span><span class="p">]</span>
|
||||
<span class="p">[</span> <span class="s">'--nodejs [ARGS]'</span><span class="p">,</span> <span class="s">'pass options directly to the "node" binary'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-o'</span><span class="p">,</span> <span class="s">'--output [DIR]'</span><span class="p">,</span> <span class="s">'set the output directory for compiled JavaScript'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-p'</span><span class="p">,</span> <span class="s">'--print'</span><span class="p">,</span> <span class="s">'print out the compiled JavaScript'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-r'</span><span class="p">,</span> <span class="s">'--require [FILE*]'</span><span class="p">,</span> <span class="s">'require a library before executing your script'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-s'</span><span class="p">,</span> <span class="s">'--stdio'</span><span class="p">,</span> <span class="s">'listen for and compile scripts over stdio'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-t'</span><span class="p">,</span> <span class="s">'--tokens'</span><span class="p">,</span> <span class="s">'print out the tokens that the lexer/rewriter produce'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-v'</span><span class="p">,</span> <span class="s">'--version'</span><span class="p">,</span> <span class="s">'display the version number'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-w'</span><span class="p">,</span> <span class="s">'--watch'</span><span class="p">,</span> <span class="s">'watch scripts for changes and rerun commands'</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Top-level objects shared by all the functions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">opts = </span><span class="p">{}</span>
|
||||
<span class="nv">sources = </span><span class="p">[]</span>
|
||||
<span class="nv">contents = </span><span class="p">[]</span>
|
||||
<span class="nv">sourceCode = </span><span class="p">[]</span>
|
||||
<span class="nv">notSources = </span><span class="p">{}</span>
|
||||
<span class="nv">watchers = </span><span class="p">{}</span>
|
||||
<span class="nv">optionParser = </span><span class="kc">null</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Run <code>coffee</code> by parsing passed options and determining what action to take.
|
||||
Many flags cause us to divert before compiling anything. Flags passed after
|
||||
<code>--</code> will be passed verbatim to your script as arguments in <code>process.argv</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.run = </span><span class="o">-></span>
|
||||
<code>--</code> will be passed verbatim to your script as arguments in <code>process.argv</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.run = </span><span class="nf">-></span>
|
||||
<span class="nx">parseOptions</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="nx">forkNode</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">nodejs</span>
|
||||
<span class="k">return</span> <span class="nx">usage</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">help</span>
|
||||
<span class="k">return</span> <span class="nx">version</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">version</span>
|
||||
<span class="nx">loadRequires</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">require</span>
|
||||
<span class="k">return</span> <span class="nx">require</span> <span class="s1">'./repl'</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">interactive</span>
|
||||
<span class="k">return</span> <span class="nx">require</span> <span class="s">'./repl'</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">interactive</span>
|
||||
<span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span> <span class="o">and</span> <span class="o">!</span><span class="nx">fs</span><span class="p">.</span><span class="nx">watch</span>
|
||||
<span class="k">return</span> <span class="nx">printWarn</span> <span class="s">"The --watch feature depends on Node v0.6.0+. You are running </span><span class="si">#{</span><span class="nx">process</span><span class="p">.</span><span class="nx">version</span><span class="si">}</span><span class="s">."</span>
|
||||
<span class="k">return</span> <span class="nx">compileStdio</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">stdio</span>
|
||||
<span class="k">return</span> <span class="nx">compileScript</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">sources</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nb">eval</span>
|
||||
<span class="k">return</span> <span class="nx">require</span> <span class="s1">'./repl'</span> <span class="nx">unless</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">run</span>
|
||||
<span class="nv">opts.literals = </span><span class="nx">sources</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="mi">1</span><span class="p">).</span><span class="nx">concat</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">literals</span>
|
||||
<span class="nv">process.argv = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">).</span><span class="nx">concat</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">literals</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'coffee'</span>
|
||||
<span class="k">return</span> <span class="nx">require</span> <span class="s">'./repl'</span> <span class="k">unless</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">literals = </span><span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">run</span> <span class="k">then</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">splice</span> <span class="mi">1</span> <span class="k">else</span> <span class="p">[]</span>
|
||||
<span class="nv">process.argv = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">..</span><span class="mi">1</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">literals</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s">'coffee'</span>
|
||||
<span class="nv">process.execPath = </span><span class="nx">require</span><span class="p">.</span><span class="nx">main</span><span class="p">.</span><span class="nx">filename</span>
|
||||
<span class="nx">compileScripts</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>Asynchronously read in each CoffeeScript in a list of source files and
|
||||
compile them. If a directory is passed, recursively compile all
|
||||
'.coffee' extension source files in it and all subdirectories.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileScripts = </span><span class="o">-></span>
|
||||
<span class="nv">unprocessed = </span><span class="p">[]</span>
|
||||
<span class="nv">remaining_files = </span><span class="o">-></span>
|
||||
<span class="nv">total = </span><span class="mi">0</span>
|
||||
<span class="nx">total</span> <span class="o">+=</span> <span class="nx">x</span> <span class="k">for</span> <span class="nx">x</span> <span class="k">in</span> <span class="nx">unprocessed</span>
|
||||
<span class="nx">total</span>
|
||||
<span class="nv">trackUnprocessedFiles = </span><span class="p">(</span><span class="nx">sourceIndex</span><span class="p">,</span> <span class="nx">fileCount</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">unprocessed</span><span class="p">[</span><span class="nx">sourceIndex</span><span class="p">]</span> <span class="o">?=</span> <span class="mi">0</span>
|
||||
<span class="nx">unprocessed</span><span class="p">[</span><span class="nx">sourceIndex</span><span class="p">]</span> <span class="o">+=</span> <span class="nx">fileCount</span>
|
||||
<span class="nv">trackCompleteFiles = </span><span class="p">(</span><span class="nx">sourceIndex</span><span class="p">,</span> <span class="nx">fileCount</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">unprocessed</span><span class="p">[</span><span class="nx">sourceIndex</span><span class="p">]</span> <span class="o">-=</span> <span class="nx">fileCount</span>
|
||||
<span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span>
|
||||
<span class="k">if</span> <span class="nx">helpers</span><span class="p">.</span><span class="nx">compact</span><span class="p">(</span><span class="nx">contents</span><span class="p">).</span><span class="nx">length</span> <span class="o">></span> <span class="mi">0</span> <span class="o">and</span> <span class="nx">remaining_files</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span>
|
||||
<span class="nx">compileJoin</span><span class="p">()</span>
|
||||
<span class="k">for</span> <span class="nx">source</span> <span class="k">in</span> <span class="nx">sources</span>
|
||||
<span class="nx">trackUnprocessedFiles</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">source</span><span class="p">),</span> <span class="mi">1</span>
|
||||
<span class="k">for</span> <span class="nx">source</span> <span class="k">in</span> <span class="nx">sources</span>
|
||||
<span class="nv">base = </span><span class="nx">path</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span>
|
||||
<span class="nv">compile = </span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">sourceIndex</span><span class="p">,</span> <span class="nx">topLevel</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">path</span><span class="p">.</span><span class="nx">exists</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">exists</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">topLevel</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">exists</span> <span class="o">and</span> <span class="nx">source</span><span class="p">[</span><span class="o">-</span><span class="mi">7</span><span class="p">..]</span> <span class="o">isnt</span> <span class="s1">'.coffee'</span>
|
||||
<span class="k">return</span> <span class="nx">compile</span> <span class="s2">"#{source}.coffee"</span><span class="p">,</span> <span class="nx">sourceIndex</span><span class="p">,</span> <span class="nx">topLevel</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"File not found: #{source}"</span> <span class="k">if</span> <span class="nx">topLevel</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">exists</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">stat</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">stats</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
|
||||
<span class="k">if</span> <span class="nx">stats</span><span class="p">.</span><span class="nx">isDirectory</span><span class="p">()</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">readdir</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">files</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
|
||||
<span class="nx">trackUnprocessedFiles</span> <span class="nx">sourceIndex</span><span class="p">,</span> <span class="nx">files</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="k">for</span> <span class="nx">file</span> <span class="k">in</span> <span class="nx">files</span>
|
||||
<span class="nx">compile</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">file</span><span class="p">),</span> <span class="nx">sourceIndex</span>
|
||||
<span class="nx">trackCompleteFiles</span> <span class="nx">sourceIndex</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">topLevel</span> <span class="o">or</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'.coffee'</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">code</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
|
||||
<span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span>
|
||||
<span class="nx">contents</span><span class="p">[</span><span class="nx">sourceIndex</span><span class="p">]</span> <span class="o">=</span> <span class="nx">helpers</span><span class="p">.</span><span class="nx">compact</span><span class="p">([</span><span class="nx">contents</span><span class="p">[</span><span class="nx">sourceIndex</span><span class="p">],</span> <span class="nx">code</span><span class="p">.</span><span class="nx">toString</span><span class="p">()]).</span><span class="nx">join</span><span class="p">(</span><span class="s1">'\n'</span><span class="p">)</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">compileScript</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">code</span><span class="p">.</span><span class="nx">toString</span><span class="p">(),</span> <span class="nx">base</span><span class="p">)</span>
|
||||
<span class="nx">trackCompleteFiles</span> <span class="nx">sourceIndex</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">trackCompleteFiles</span> <span class="nx">sourceIndex</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="nx">compile</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">source</span><span class="p">),</span> <span class="kc">true</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Compile a single source script, containing the given code, according to the
|
||||
<span class="nx">compilePath</span> <span class="nx">source</span><span class="p">,</span> <span class="kc">yes</span><span class="p">,</span> <span class="nx">path</span><span class="p">.</span><span class="nx">normalize</span> <span class="nx">source</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>Compile a path, which could be a script or a directory. If a directory
|
||||
is passed, recursively compile all '.coffee' extension source files in it
|
||||
and all subdirectories.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compilePath = </span><span class="nf">(source, topLevel, base) -></span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">stat</span> <span class="nx">source</span><span class="p">,</span> <span class="nf">(err, stats) -></span>
|
||||
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">code</span> <span class="o">isnt</span> <span class="s">'ENOENT'</span>
|
||||
<span class="k">if</span> <span class="nx">err</span><span class="o">?</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s">'ENOENT'</span>
|
||||
<span class="k">if</span> <span class="nx">topLevel</span> <span class="o">and</span> <span class="nx">source</span><span class="p">[</span><span class="o">-</span><span class="mi">7</span><span class="p">..]</span> <span class="o">isnt</span> <span class="s">'.coffee'</span>
|
||||
<span class="nv">source = </span><span class="nx">sources</span><span class="p">[</span><span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">source</span><span class="p">)]</span> <span class="o">=</span> <span class="s">"</span><span class="si">#{</span><span class="nx">source</span><span class="si">}</span><span class="s">.coffee"</span>
|
||||
<span class="k">return</span> <span class="nx">compilePath</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">topLevel</span><span class="p">,</span> <span class="nx">base</span>
|
||||
<span class="k">if</span> <span class="nx">topLevel</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span> <span class="s">"File not found: </span><span class="si">#{</span><span class="nx">source</span><span class="si">}</span><span class="s">"</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span>
|
||||
<span class="k">return</span>
|
||||
<span class="k">if</span> <span class="nx">stats</span><span class="p">.</span><span class="nx">isDirectory</span><span class="p">()</span>
|
||||
<span class="nx">watchDir</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">readdir</span> <span class="nx">source</span><span class="p">,</span> <span class="nf">(err, files) -></span>
|
||||
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">code</span> <span class="o">isnt</span> <span class="s">'ENOENT'</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">err</span><span class="o">?</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s">'ENOENT'</span>
|
||||
<span class="nv">index = </span><span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span> <span class="nx">source</span>
|
||||
<span class="nv">files = </span><span class="nx">files</span><span class="p">.</span><span class="nx">filter</span> <span class="nf">(file) -></span> <span class="o">not</span> <span class="nx">hidden</span> <span class="nx">file</span>
|
||||
<span class="nx">sources</span><span class="p">[</span><span class="nx">index</span><span class="p">..</span><span class="nx">index</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">file</span> <span class="k">for</span> <span class="nx">file</span> <span class="k">in</span> <span class="nx">files</span><span class="p">)</span>
|
||||
<span class="nx">sourceCode</span><span class="p">[</span><span class="nx">index</span><span class="p">..</span><span class="nx">index</span><span class="p">]</span> <span class="o">=</span> <span class="nx">files</span><span class="p">.</span><span class="nx">map</span> <span class="nf">-></span> <span class="kc">null</span>
|
||||
<span class="nx">files</span><span class="p">.</span><span class="nx">forEach</span> <span class="nf">(file) -></span>
|
||||
<span class="nx">compilePath</span> <span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">file</span><span class="p">),</span> <span class="kc">no</span><span class="p">,</span> <span class="nx">base</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">topLevel</span> <span class="o">or</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">is</span> <span class="s">'.coffee'</span>
|
||||
<span class="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span> <span class="nx">source</span><span class="p">,</span> <span class="nf">(err, code) -></span>
|
||||
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">code</span> <span class="o">isnt</span> <span class="s">'ENOENT'</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">err</span><span class="o">?</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s">'ENOENT'</span>
|
||||
<span class="nx">compileScript</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">code</span><span class="p">.</span><span class="nx">toString</span><span class="p">(),</span> <span class="nx">base</span><span class="p">)</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">notSources</span><span class="p">[</span><span class="nx">source</span><span class="p">]</span> <span class="o">=</span> <span class="kc">yes</span>
|
||||
<span class="nx">removeSource</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Compile a single source script, containing the given code, according to the
|
||||
requested options. If evaluating the script directly sets <code>__filename</code>,
|
||||
<code>__dirname</code> and <code>module.filename</code> to be correct relative to the script's path.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileScript = </span><span class="p">(</span><span class="nx">file</span><span class="p">,</span> <span class="nx">input</span><span class="p">,</span> <span class="nx">base</span><span class="p">)</span> <span class="o">-></span>
|
||||
<code>__dirname</code> and <code>module.filename</code> to be correct relative to the script's path.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileScript = </span><span class="nf">(file, input, base) -></span>
|
||||
<span class="nv">o = </span><span class="nx">opts</span>
|
||||
<span class="nv">options = </span><span class="nx">compileOptions</span> <span class="nx">file</span>
|
||||
<span class="k">try</span>
|
||||
<span class="nv">t = task = </span><span class="p">{</span><span class="nx">file</span><span class="p">,</span> <span class="nx">input</span><span class="p">,</span> <span class="nx">options</span><span class="p">}</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s1">'compile'</span><span class="p">,</span> <span class="nx">task</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s">'compile'</span><span class="p">,</span> <span class="nx">task</span>
|
||||
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">tokens</span> <span class="k">then</span> <span class="nx">printTokens</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">tokens</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">nodes</span> <span class="k">then</span> <span class="nx">printLine</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">nodes</span><span class="p">(</span><span class="nx">t</span><span class="p">.</span><span class="nx">input</span><span class="p">).</span><span class="nx">toString</span><span class="p">().</span><span class="nx">trim</span><span class="p">()</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">run</span> <span class="k">then</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">options</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">join</span> <span class="o">and</span> <span class="nx">t</span><span class="p">.</span><span class="nx">file</span> <span class="o">isnt</span> <span class="nx">o</span><span class="p">.</span><span class="nx">join</span>
|
||||
<span class="nx">sourceCode</span><span class="p">[</span><span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">t</span><span class="p">.</span><span class="nx">file</span><span class="p">)]</span> <span class="o">=</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span>
|
||||
<span class="nx">compileJoin</span><span class="p">()</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">t.output = </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">options</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s1">'success'</span><span class="p">,</span> <span class="nx">task</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s">'success'</span><span class="p">,</span> <span class="nx">task</span>
|
||||
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="k">then</span> <span class="nx">printLine</span> <span class="nx">t</span><span class="p">.</span><span class="nx">output</span><span class="p">.</span><span class="nx">trim</span><span class="p">()</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="k">then</span> <span class="nx">writeJs</span> <span class="nx">t</span><span class="p">.</span><span class="nx">file</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">output</span><span class="p">,</span> <span class="nx">base</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">lint</span> <span class="k">then</span> <span class="nx">lint</span> <span class="nx">t</span><span class="p">.</span><span class="nx">file</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">output</span>
|
||||
<span class="k">catch</span> <span class="nx">err</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s1">'failure'</span><span class="p">,</span> <span class="nx">err</span><span class="p">,</span> <span class="nx">task</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">listeners</span><span class="p">(</span><span class="s1">'failure'</span><span class="p">).</span><span class="nx">length</span>
|
||||
<span class="k">return</span> <span class="nx">printLine</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">watch</span>
|
||||
<span class="nx">printWarn</span> <span class="nx">err</span> <span class="k">instanceof</span> <span class="nb">Error</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">stack</span> <span class="o">or</span> <span class="s2">"ERROR: #{err}"</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s">'failure'</span><span class="p">,</span> <span class="nx">err</span><span class="p">,</span> <span class="nx">task</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">listeners</span><span class="p">(</span><span class="s">'failure'</span><span class="p">).</span><span class="nx">length</span>
|
||||
<span class="k">return</span> <span class="nx">printLine</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span> <span class="o">+</span> <span class="s">'\x07'</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">watch</span>
|
||||
<span class="nx">printWarn</span> <span class="nx">err</span> <span class="k">instanceof</span> <span class="nb">Error</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">stack</span> <span class="o">or</span> <span class="s">"ERROR: </span><span class="si">#{</span><span class="nx">err</span><span class="si">}</span><span class="s">"</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Attach the appropriate listeners to compile scripts incoming over <strong>stdin</strong>,
|
||||
and write them back to <strong>stdout</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileStdio = </span><span class="o">-></span>
|
||||
<span class="nv">code = </span><span class="s1">''</span>
|
||||
and write them back to <strong>stdout</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileStdio = </span><span class="nf">-></span>
|
||||
<span class="nv">code = </span><span class="s">''</span>
|
||||
<span class="nv">stdin = </span><span class="nx">process</span><span class="p">.</span><span class="nx">openStdin</span><span class="p">()</span>
|
||||
<span class="nx">stdin</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'data'</span><span class="p">,</span> <span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">on</span> <span class="s">'data'</span><span class="p">,</span> <span class="nf">(buffer) -></span>
|
||||
<span class="nx">code</span> <span class="o">+=</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span> <span class="k">if</span> <span class="nx">buffer</span>
|
||||
<span class="nx">stdin</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'end'</span><span class="p">,</span> <span class="o">-></span>
|
||||
<span class="nx">compileScript</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">code</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>After all of the source files are done being read, concatenate and compile
|
||||
them together.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileJoin = </span><span class="o">-></span>
|
||||
<span class="nv">code = </span><span class="nx">contents</span><span class="p">.</span><span class="nx">join</span> <span class="s1">'\n'</span>
|
||||
<span class="nx">compileScript</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span><span class="p">,</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Load files that are to-be-required before compilation occurs.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">loadRequires = </span><span class="o">-></span>
|
||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">on</span> <span class="s">'end'</span><span class="p">,</span> <span class="nf">-></span>
|
||||
<span class="nx">compileScript</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">code</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>If all of the source files are done being read, concatenate and compile
|
||||
them together.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">joinTimeout = </span><span class="kc">null</span>
|
||||
<span class="nv">compileJoin = </span><span class="nf">-></span>
|
||||
<span class="k">return</span> <span class="k">unless</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span>
|
||||
<span class="k">unless</span> <span class="nx">sourceCode</span><span class="p">.</span><span class="nx">some</span><span class="p">(</span><span class="nf">(code) -></span> <span class="nx">code</span> <span class="o">is</span> <span class="kc">null</span><span class="p">)</span>
|
||||
<span class="nx">clearTimeout</span> <span class="nx">joinTimeout</span>
|
||||
<span class="nv">joinTimeout = </span><span class="nx">wait</span> <span class="mi">100</span><span class="p">,</span> <span class="nf">-></span>
|
||||
<span class="nx">compileScript</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span><span class="p">,</span> <span class="nx">sourceCode</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s">'\n'</span><span class="p">),</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Load files that are to-be-required before compilation occurs.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">loadRequires = </span><span class="nf">-></span>
|
||||
<span class="nv">realFilename = </span><span class="nx">module</span><span class="p">.</span><span class="nx">filename</span>
|
||||
<span class="nv">module.filename = </span><span class="s1">'.'</span>
|
||||
<span class="nv">module.filename = </span><span class="s">'.'</span>
|
||||
<span class="nx">require</span> <span class="nx">req</span> <span class="k">for</span> <span class="nx">req</span> <span class="k">in</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">require</span>
|
||||
<span class="nv">module.filename = </span><span class="nx">realFilename</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Watch a source CoffeeScript file using <code>fs.watch</code>, recompiling it every
|
||||
time the file is updated. May be used in combination with other options,
|
||||
such as <code>--lint</code> or <code>--print</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">watch = </span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">base</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">stat</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">prevStats</span><span class="p">)</span><span class="o">-></span>
|
||||
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">event</span> <span class="o">is</span> <span class="s1">'change'</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">stat</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">stats</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">stats</span><span class="p">.</span><span class="nx">size</span> <span class="o">is</span> <span class="nx">prevStats</span><span class="p">.</span><span class="nx">size</span> <span class="o">and</span>
|
||||
<span class="nx">stats</span><span class="p">.</span><span class="nx">mtime</span><span class="p">.</span><span class="nx">getTime</span><span class="p">()</span> <span class="o">is</span> <span class="nx">prevStats</span><span class="p">.</span><span class="nx">mtime</span><span class="p">.</span><span class="nx">getTime</span><span class="p">()</span>
|
||||
<span class="nv">prevStats = </span><span class="nx">stats</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">code</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
|
||||
<span class="nx">compileScript</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">code</span><span class="p">.</span><span class="nx">toString</span><span class="p">(),</span> <span class="nx">base</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Write out a JavaScript source file with the compiled code. By default, files
|
||||
are written out in <code>cwd</code> as <code>.js</code> files with the same name, but the output
|
||||
directory can be customized with <code>--output</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">writeJs = </span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">js</span><span class="p">,</span> <span class="nx">base</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">filename = </span><span class="nx">path</span><span class="p">.</span><span class="nx">basename</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">source</span><span class="p">))</span> <span class="o">+</span> <span class="s1">'.js'</span>
|
||||
such as <code>--lint</code> or <code>--print</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">watch = </span><span class="nf">(source, base) -></span>
|
||||
|
||||
<span class="nv">prevStats = </span><span class="kc">null</span>
|
||||
<span class="nv">compileTimeout = </span><span class="kc">null</span>
|
||||
|
||||
<span class="nv">watchErr = </span><span class="nf">(e) -></span>
|
||||
<span class="k">if</span> <span class="nx">e</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s">'ENOENT'</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">is</span> <span class="o">-</span><span class="mi">1</span>
|
||||
<span class="k">try</span>
|
||||
<span class="nx">rewatch</span><span class="p">()</span>
|
||||
<span class="nx">compile</span><span class="p">()</span>
|
||||
<span class="k">catch</span> <span class="nx">e</span>
|
||||
<span class="nx">removeSource</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span><span class="p">,</span> <span class="kc">yes</span>
|
||||
<span class="nx">compileJoin</span><span class="p">()</span>
|
||||
<span class="k">else</span> <span class="k">throw</span> <span class="nx">e</span>
|
||||
|
||||
<span class="nv">compile = </span><span class="nf">-></span>
|
||||
<span class="nx">clearTimeout</span> <span class="nx">compileTimeout</span>
|
||||
<span class="nv">compileTimeout = </span><span class="nx">wait</span> <span class="mi">25</span><span class="p">,</span> <span class="nf">-></span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">stat</span> <span class="nx">source</span><span class="p">,</span> <span class="nf">(err, stats) -></span>
|
||||
<span class="k">return</span> <span class="nx">watchErr</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
|
||||
<span class="k">return</span> <span class="nx">rewatch</span><span class="p">()</span> <span class="k">if</span> <span class="nx">prevStats</span> <span class="o">and</span> <span class="nx">stats</span><span class="p">.</span><span class="nx">size</span> <span class="o">is</span> <span class="nx">prevStats</span><span class="p">.</span><span class="nx">size</span> <span class="o">and</span>
|
||||
<span class="nx">stats</span><span class="p">.</span><span class="nx">mtime</span><span class="p">.</span><span class="nx">getTime</span><span class="p">()</span> <span class="o">is</span> <span class="nx">prevStats</span><span class="p">.</span><span class="nx">mtime</span><span class="p">.</span><span class="nx">getTime</span><span class="p">()</span>
|
||||
<span class="nv">prevStats = </span><span class="nx">stats</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span> <span class="nx">source</span><span class="p">,</span> <span class="nf">(err, code) -></span>
|
||||
<span class="k">return</span> <span class="nx">watchErr</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
|
||||
<span class="nx">compileScript</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">code</span><span class="p">.</span><span class="nx">toString</span><span class="p">(),</span> <span class="nx">base</span><span class="p">)</span>
|
||||
<span class="nx">rewatch</span><span class="p">()</span>
|
||||
|
||||
<span class="k">try</span>
|
||||
<span class="nv">watcher = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">compile</span>
|
||||
<span class="k">catch</span> <span class="nx">e</span>
|
||||
<span class="nx">watchErr</span> <span class="nx">e</span>
|
||||
|
||||
<span class="nv">rewatch = </span><span class="nf">-></span>
|
||||
<span class="nx">watcher</span><span class="o">?</span><span class="p">.</span><span class="nx">close</span><span class="p">()</span>
|
||||
<span class="nv">watcher = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">compile</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Watch a directory of files for new additions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">watchDir = </span><span class="nf">(source, base) -></span>
|
||||
<span class="nv">readdirTimeout = </span><span class="kc">null</span>
|
||||
<span class="k">try</span>
|
||||
<span class="nv">watcher = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="nf">-></span>
|
||||
<span class="nx">clearTimeout</span> <span class="nx">readdirTimeout</span>
|
||||
<span class="nv">readdirTimeout = </span><span class="nx">wait</span> <span class="mi">25</span><span class="p">,</span> <span class="nf">-></span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">readdir</span> <span class="nx">source</span><span class="p">,</span> <span class="nf">(err, files) -></span>
|
||||
<span class="k">if</span> <span class="nx">err</span>
|
||||
<span class="k">throw</span> <span class="nx">err</span> <span class="k">unless</span> <span class="nx">err</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s">'ENOENT'</span>
|
||||
<span class="nx">watcher</span><span class="p">.</span><span class="nx">close</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="nx">unwatchDir</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span>
|
||||
<span class="k">for</span> <span class="nx">file</span> <span class="k">in</span> <span class="nx">files</span> <span class="k">when</span> <span class="o">not</span> <span class="nx">hidden</span><span class="p">(</span><span class="nx">file</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">notSources</span><span class="p">[</span><span class="nx">file</span><span class="p">]</span>
|
||||
<span class="nv">file = </span><span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">file</span>
|
||||
<span class="k">continue</span> <span class="k">if</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">some</span> <span class="nf">(s) -></span> <span class="nx">s</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">file</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span>
|
||||
<span class="nx">sources</span><span class="p">.</span><span class="nx">push</span> <span class="nx">file</span>
|
||||
<span class="nx">sourceCode</span><span class="p">.</span><span class="nx">push</span> <span class="kc">null</span>
|
||||
<span class="nx">compilePath</span> <span class="nx">file</span><span class="p">,</span> <span class="kc">no</span><span class="p">,</span> <span class="nx">base</span>
|
||||
<span class="k">catch</span> <span class="nx">e</span>
|
||||
<span class="k">throw</span> <span class="nx">e</span> <span class="k">unless</span> <span class="nx">e</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s">'ENOENT'</span>
|
||||
|
||||
<span class="nv">unwatchDir = </span><span class="nf">(source, base) -></span>
|
||||
<span class="nv">prevSources = </span><span class="nx">sources</span><span class="p">[..]</span>
|
||||
<span class="nv">toRemove = </span><span class="p">(</span><span class="nx">file</span> <span class="k">for</span> <span class="nx">file</span> <span class="k">in</span> <span class="nx">sources</span> <span class="k">when</span> <span class="nx">file</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">)</span>
|
||||
<span class="nx">removeSource</span> <span class="nx">file</span><span class="p">,</span> <span class="nx">base</span><span class="p">,</span> <span class="kc">yes</span> <span class="k">for</span> <span class="nx">file</span> <span class="k">in</span> <span class="nx">toRemove</span>
|
||||
<span class="k">return</span> <span class="k">unless</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">some</span> <span class="nf">(s, i) -></span> <span class="nx">prevSources</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">isnt</span> <span class="nx">s</span>
|
||||
<span class="nx">compileJoin</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>Remove a file from our source list, and source code cache. Optionally remove
|
||||
the compiled JS version as well.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">removeSource = </span><span class="nf">(source, base, removeJs) -></span>
|
||||
<span class="nv">index = </span><span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span> <span class="nx">source</span>
|
||||
<span class="nx">sources</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">index</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="nx">sourceCode</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">index</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="k">if</span> <span class="nx">removeJs</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span>
|
||||
<span class="nv">jsPath = </span><span class="nx">outputPath</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span>
|
||||
<span class="nx">exists</span> <span class="nx">jsPath</span><span class="p">,</span> <span class="nf">(itExists) -></span>
|
||||
<span class="k">if</span> <span class="nx">itExists</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">unlink</span> <span class="nx">jsPath</span><span class="p">,</span> <span class="nf">(err) -></span>
|
||||
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">code</span> <span class="o">isnt</span> <span class="s">'ENOENT'</span>
|
||||
<span class="nx">timeLog</span> <span class="s">"removed </span><span class="si">#{</span><span class="nx">source</span><span class="si">}</span><span class="s">"</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>Get the corresponding output JavaScript path for a source file.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">outputPath = </span><span class="nf">(source, base) -></span>
|
||||
<span class="nv">filename = </span><span class="nx">path</span><span class="p">.</span><span class="nx">basename</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">source</span><span class="p">))</span> <span class="o">+</span> <span class="s">'.js'</span>
|
||||
<span class="nv">srcDir = </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">source</span>
|
||||
<span class="nv">baseDir = </span><span class="k">if</span> <span class="nx">base</span> <span class="o">is</span> <span class="s1">'.'</span> <span class="k">then</span> <span class="nx">srcDir</span> <span class="k">else</span> <span class="nx">srcDir</span><span class="p">.</span><span class="nx">substring</span> <span class="nx">base</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">baseDir = </span><span class="k">if</span> <span class="nx">base</span> <span class="o">is</span> <span class="s">'.'</span> <span class="k">then</span> <span class="nx">srcDir</span> <span class="k">else</span> <span class="nx">srcDir</span><span class="p">.</span><span class="nx">substring</span> <span class="nx">base</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">dir = </span><span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">output</span> <span class="k">then</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">output</span><span class="p">,</span> <span class="nx">baseDir</span> <span class="k">else</span> <span class="nx">srcDir</span>
|
||||
<span class="nv">jsPath = </span><span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">dir</span><span class="p">,</span> <span class="nx">filename</span>
|
||||
<span class="nv">compile = </span><span class="o">-></span>
|
||||
<span class="nv">js = </span><span class="s1">' '</span> <span class="k">if</span> <span class="nx">js</span><span class="p">.</span><span class="nx">length</span> <span class="o"><=</span> <span class="mi">0</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">writeFile</span> <span class="nx">jsPath</span><span class="p">,</span> <span class="nx">js</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">dir</span><span class="p">,</span> <span class="nx">filename</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <p>Write out a JavaScript source file with the compiled code. By default, files
|
||||
are written out in <code>cwd</code> as <code>.js</code> files with the same name, but the output
|
||||
directory can be customized with <code>--output</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">writeJs = </span><span class="nf">(source, js, base) -></span>
|
||||
<span class="nv">jsPath = </span><span class="nx">outputPath</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span>
|
||||
<span class="nv">jsDir = </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">jsPath</span>
|
||||
<span class="nv">compile = </span><span class="nf">-></span>
|
||||
<span class="nv">js = </span><span class="s">' '</span> <span class="k">if</span> <span class="nx">js</span><span class="p">.</span><span class="nx">length</span> <span class="o"><=</span> <span class="mi">0</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">writeFile</span> <span class="nx">jsPath</span><span class="p">,</span> <span class="nx">js</span><span class="p">,</span> <span class="nf">(err) -></span>
|
||||
<span class="k">if</span> <span class="nx">err</span>
|
||||
<span class="nx">printLine</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">compile</span> <span class="o">and</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s2">"#{(new Date).toLocaleTimeString()} - compiled #{source}"</span>
|
||||
<span class="nx">path</span><span class="p">.</span><span class="nx">exists</span> <span class="nx">dir</span><span class="p">,</span> <span class="p">(</span><span class="nx">exists</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">exists</span> <span class="k">then</span> <span class="nx">compile</span><span class="p">()</span> <span class="k">else</span> <span class="nx">exec</span> <span class="s2">"mkdir -p #{dir}"</span><span class="p">,</span> <span class="nx">compile</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>Pipe compiled JS through JSLint (requires a working <code>jsl</code> command), printing
|
||||
any errors or warnings that arise.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lint = </span><span class="p">(</span><span class="nx">file</span><span class="p">,</span> <span class="nx">js</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">printIt = </span><span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-></span> <span class="nx">printLine</span> <span class="nx">file</span> <span class="o">+</span> <span class="s1">':\t'</span> <span class="o">+</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">().</span><span class="nx">trim</span><span class="p">()</span>
|
||||
<span class="nv">conf = </span><span class="nx">__dirname</span> <span class="o">+</span> <span class="s1">'/../../extras/jsl.conf'</span>
|
||||
<span class="nv">jsl = </span><span class="nx">spawn</span> <span class="s1">'jsl'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'-nologo'</span><span class="p">,</span> <span class="s1">'-stdin'</span><span class="p">,</span> <span class="s1">'-conf'</span><span class="p">,</span> <span class="nx">conf</span><span class="p">]</span>
|
||||
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'data'</span><span class="p">,</span> <span class="nx">printIt</span>
|
||||
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stderr</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'data'</span><span class="p">,</span> <span class="nx">printIt</span>
|
||||
<span class="nx">timeLog</span> <span class="s">"compiled </span><span class="si">#{</span><span class="nx">source</span><span class="si">}</span><span class="s">"</span>
|
||||
<span class="nx">exists</span> <span class="nx">jsDir</span><span class="p">,</span> <span class="nf">(itExists) -></span>
|
||||
<span class="k">if</span> <span class="nx">itExists</span> <span class="k">then</span> <span class="nx">compile</span><span class="p">()</span> <span class="k">else</span> <span class="nx">exec</span> <span class="s">"mkdir -p </span><span class="si">#{</span><span class="nx">jsDir</span><span class="si">}</span><span class="s">"</span><span class="p">,</span> <span class="nx">compile</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <p>Convenience for cleaner setTimeouts.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">wait = </span><span class="nf">(milliseconds, func) -></span> <span class="nx">setTimeout</span> <span class="nx">func</span><span class="p">,</span> <span class="nx">milliseconds</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</a> </div> <p>When watching scripts, it's useful to log changes with the timestamp.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">timeLog = </span><span class="nf">(message) -></span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s">"</span><span class="si">#{</span><span class="p">(</span><span class="k">new</span> <span class="nb">Date</span><span class="p">).</span><span class="nx">toLocaleTimeString</span><span class="p">()</span><span class="si">}</span><span class="s"> - </span><span class="si">#{</span><span class="nx">message</span><span class="si">}</span><span class="s">"</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">¶</a> </div> <p>Pipe compiled JS through JSLint (requires a working <code>jsl</code> command), printing
|
||||
any errors or warnings that arise.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lint = </span><span class="nf">(file, js) -></span>
|
||||
<span class="nv">printIt = </span><span class="nf">(buffer) -></span> <span class="nx">printLine</span> <span class="nx">file</span> <span class="o">+</span> <span class="s">':\t'</span> <span class="o">+</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">().</span><span class="nx">trim</span><span class="p">()</span>
|
||||
<span class="nv">conf = </span><span class="nx">__dirname</span> <span class="o">+</span> <span class="s">'/../../extras/jsl.conf'</span>
|
||||
<span class="nv">jsl = </span><span class="nx">spawn</span> <span class="s">'jsl'</span><span class="p">,</span> <span class="p">[</span><span class="s">'-nologo'</span><span class="p">,</span> <span class="s">'-stdin'</span><span class="p">,</span> <span class="s">'-conf'</span><span class="p">,</span> <span class="nx">conf</span><span class="p">]</span>
|
||||
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">on</span> <span class="s">'data'</span><span class="p">,</span> <span class="nx">printIt</span>
|
||||
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stderr</span><span class="p">.</span><span class="nx">on</span> <span class="s">'data'</span><span class="p">,</span> <span class="nx">printIt</span>
|
||||
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdin</span><span class="p">.</span><span class="nx">write</span> <span class="nx">js</span>
|
||||
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdin</span><span class="p">.</span><span class="nx">end</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>Pretty-print a stream of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">printTokens = </span><span class="p">(</span><span class="nx">tokens</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdin</span><span class="p">.</span><span class="nx">end</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">¶</a> </div> <p>Pretty-print a stream of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">printTokens = </span><span class="nf">(tokens) -></span>
|
||||
<span class="nv">strings = </span><span class="k">for</span> <span class="nx">token</span> <span class="k">in</span> <span class="nx">tokens</span>
|
||||
<span class="p">[</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">token</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">toString</span><span class="p">().</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/\n/</span><span class="p">,</span> <span class="s1">'\\n'</span><span class="p">)]</span>
|
||||
<span class="s2">"[#{tag} #{value}]"</span>
|
||||
<span class="nx">printLine</span> <span class="nx">strings</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s1">' '</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <p>Use the <a href="optparse.html">OptionParser module</a> to extract all options from
|
||||
<code>process.argv</code> that are specified in <code>SWITCHES</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">parseOptions = </span><span class="o">-></span>
|
||||
<span class="p">[</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">token</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">toString</span><span class="p">().</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/\n/</span><span class="p">,</span> <span class="s">'\\n'</span><span class="p">)]</span>
|
||||
<span class="s">"[</span><span class="si">#{</span><span class="nx">tag</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="nx">value</span><span class="si">}</span><span class="s">]"</span>
|
||||
<span class="nx">printLine</span> <span class="nx">strings</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s">' '</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">¶</a> </div> <p>Use the <a href="optparse.html">OptionParser module</a> to extract all options from
|
||||
<code>process.argv</code> that are specified in <code>SWITCHES</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">parseOptions = </span><span class="nf">-></span>
|
||||
<span class="nv">optionParser = </span><span class="k">new</span> <span class="nx">optparse</span><span class="p">.</span><span class="nx">OptionParser</span> <span class="nx">SWITCHES</span><span class="p">,</span> <span class="nx">BANNER</span>
|
||||
<span class="nv">o = opts = </span><span class="nx">optionParser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">.</span><span class="nx">slice</span> <span class="mi">2</span>
|
||||
<span class="nv">o = opts = </span><span class="nx">optionParser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">..]</span>
|
||||
<span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="o">or=</span> <span class="o">!!</span><span class="nx">o</span><span class="p">.</span><span class="nx">output</span>
|
||||
<span class="nv">o.run = </span><span class="o">not</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">lint</span><span class="p">)</span>
|
||||
<span class="nv">o.print = </span><span class="o">!!</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nb">eval</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">stdio</span> <span class="o">and</span> <span class="nx">o</span><span class="p">.</span><span class="nx">compile</span><span class="p">))</span>
|
||||
<span class="nv">sources = </span><span class="nx">o</span><span class="p">.</span><span class="nx">arguments</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <p>The compile-time options to pass to the CoffeeScript compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileOptions = </span><span class="p">(</span><span class="nx">filename</span><span class="p">)</span> <span class="o">-></span> <span class="p">{</span><span class="nx">filename</span><span class="p">,</span> <span class="nx">bare</span><span class="o">:</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">bare</span><span class="p">}</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</a> </div> <p>Start up a new Node.js instance with the arguments in <code>--nodejs</code> passed to
|
||||
the <code>node</code> binary, preserving the other options.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">forkNode = </span><span class="o">-></span>
|
||||
<span class="nv">sources = </span><span class="nx">o</span><span class="p">.</span><span class="nx">arguments</span>
|
||||
<span class="nx">sourceCode</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="kc">null</span> <span class="k">for</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">sources</span>
|
||||
<span class="k">return</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">¶</a> </div> <p>The compile-time options to pass to the CoffeeScript compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileOptions = </span><span class="nf">(filename) -></span>
|
||||
<span class="p">{</span><span class="nx">filename</span><span class="p">,</span> <span class="nv">bare: </span><span class="nx">opts</span><span class="p">.</span><span class="nx">bare</span><span class="p">,</span> <span class="nv">header: </span><span class="nx">opts</span><span class="p">.</span><span class="nx">compile</span><span class="p">}</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">¶</a> </div> <p>Start up a new Node.js instance with the arguments in <code>--nodejs</code> passed to
|
||||
the <code>node</code> binary, preserving the other options.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">forkNode = </span><span class="nf">-></span>
|
||||
<span class="nv">nodeArgs = </span><span class="nx">opts</span><span class="p">.</span><span class="nx">nodejs</span><span class="p">.</span><span class="nx">split</span> <span class="sr">/\s+/</span>
|
||||
<span class="nv">args = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">..]</span>
|
||||
<span class="nx">args</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">args</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">'--nodejs'</span><span class="p">),</span> <span class="mi">2</span>
|
||||
<span class="nx">args</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">args</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s">'--nodejs'</span><span class="p">),</span> <span class="mi">2</span>
|
||||
<span class="nx">spawn</span> <span class="nx">process</span><span class="p">.</span><span class="nx">execPath</span><span class="p">,</span> <span class="nx">nodeArgs</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">args</span><span class="p">),</span>
|
||||
<span class="nx">cwd</span><span class="o">:</span> <span class="nx">process</span><span class="p">.</span><span class="nx">cwd</span><span class="p">()</span>
|
||||
<span class="nx">env</span><span class="o">:</span> <span class="nx">process</span><span class="p">.</span><span class="nx">env</span>
|
||||
<span class="nx">customFds</span><span class="o">:</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">¶</a> </div> <p>Print the <code>--help</code> usage message and exit. Deprecated switches are not
|
||||
shown.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">usage = </span><span class="o">-></span>
|
||||
<span class="nx">printLine</span> <span class="p">(</span><span class="k">new</span> <span class="nx">optparse</span><span class="p">.</span><span class="nx">OptionParser</span> <span class="nx">SWITCHES</span><span class="p">,</span> <span class="nx">BANNER</span><span class="p">).</span><span class="nx">help</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">¶</a> </div> <p>Print the <code>--version</code> message and exit.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">version = </span><span class="o">-></span>
|
||||
<span class="nx">printLine</span> <span class="s2">"CoffeeScript version #{CoffeeScript.VERSION}"</span>
|
||||
<span class="nv">cwd: </span> <span class="nx">process</span><span class="p">.</span><span class="nx">cwd</span><span class="p">()</span>
|
||||
<span class="nv">env: </span> <span class="nx">process</span><span class="p">.</span><span class="nx">env</span>
|
||||
<span class="nv">customFds: </span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">¶</a> </div> <p>Print the <code>--help</code> usage message and exit. Deprecated switches are not
|
||||
shown.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">usage = </span><span class="nf">-></span>
|
||||
<span class="nx">printLine</span> <span class="p">(</span><span class="k">new</span> <span class="nx">optparse</span><span class="p">.</span><span class="nx">OptionParser</span> <span class="nx">SWITCHES</span><span class="p">,</span> <span class="nx">BANNER</span><span class="p">).</span><span class="nx">help</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">¶</a> </div> <p>Print the <code>--version</code> message and exit.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">version = </span><span class="nf">-></span>
|
||||
<span class="nx">printLine</span> <span class="s">"CoffeeScript version </span><span class="si">#{</span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">VERSION</span><span class="si">}</span><span class="s">"</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -21,6 +21,12 @@ h1, h2, h3, h4, h5, h6 {
|
||||
h1 {
|
||||
margin-top: 40px;
|
||||
}
|
||||
hr {
|
||||
border: 0 none;
|
||||
border-top: 1px solid #e5e5ee;
|
||||
height: 1px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
#container {
|
||||
position: relative;
|
||||
}
|
||||
@@ -115,7 +121,7 @@ table td {
|
||||
}
|
||||
pre, tt, code {
|
||||
font-size: 12px; line-height: 18px;
|
||||
font-family: Monaco, Consolas, "Lucida Console", monospace;
|
||||
font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace;
|
||||
margin: 0; padding: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,19 +12,19 @@ reduces into the <a href="http://en.wikipedia.org/wiki/Terminal_and_nonterminal_
|
||||
(the enclosing name at the top), and we proceed from there.</p>
|
||||
|
||||
<p>If you run the <code>cake build:parser</code> command, Jison constructs a parse table
|
||||
from our rules and saves it into <code>lib/parser.js</code>.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>The only dependency is on the <strong>Jison.Parser</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="p">{</span><span class="nx">Parser</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'jison'</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <h2>Jison DSL</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Since we're going to be wrapped in a function by Jison in any case, if our
|
||||
from our rules and saves it into <code>lib/parser.js</code>.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>The only dependency is on the <strong>Jison.Parser</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="p">{</span><span class="nx">Parser</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">'jison'</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <h2>Jison DSL</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Since we're going to be wrapped in a function by Jison in any case, if our
|
||||
action immediately returns a value, we can optimize by removing the function
|
||||
wrapper and just returning the value directly.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">unwrap = </span><span class="sr">/^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Our handy DSL for Jison grammar generation, thanks to
|
||||
<a href="http://github.com/creationix">Tim Caswell</a>. For every rule in the grammar,
|
||||
we pass the pattern-defining string, the action to run, and extra options,
|
||||
optionally. If no action is specified, we simply pass the value of the
|
||||
previous nonterminal.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">o = </span><span class="p">(</span><span class="nx">patternString</span><span class="p">,</span> <span class="nx">action</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">patternString = </span><span class="nx">patternString</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\s{2,}/g</span><span class="p">,</span> <span class="s1">' '</span>
|
||||
<span class="k">return</span> <span class="p">[</span><span class="nx">patternString</span><span class="p">,</span> <span class="s1">'$$ = $1;'</span><span class="p">,</span> <span class="nx">options</span><span class="p">]</span> <span class="nx">unless</span> <span class="nx">action</span>
|
||||
<span class="nv">action = </span><span class="k">if</span> <span class="nv">match = </span><span class="nx">unwrap</span><span class="p">.</span><span class="nx">exec</span> <span class="nx">action</span> <span class="k">then</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">else</span> <span class="s2">"(#{action}())"</span>
|
||||
<span class="nv">action = </span><span class="nx">action</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\bnew /g</span><span class="p">,</span> <span class="s1">'$&yy.'</span>
|
||||
<span class="nv">action = </span><span class="nx">action</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\b(?:Block\.wrap|extend)\b/g</span><span class="p">,</span> <span class="s1">'yy.$&'</span>
|
||||
<span class="p">[</span><span class="nx">patternString</span><span class="p">,</span> <span class="s2">"$$ = #{action};"</span><span class="p">,</span> <span class="nx">options</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <h2>Grammatical Rules</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>In all of the rules that follow, you'll see the name of the nonterminal as
|
||||
previous nonterminal.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">o = </span><span class="nf">(patternString, action, options) -></span>
|
||||
<span class="nv">patternString = </span><span class="nx">patternString</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\s{2,}/g</span><span class="p">,</span> <span class="s">' '</span>
|
||||
<span class="k">return</span> <span class="p">[</span><span class="nx">patternString</span><span class="p">,</span> <span class="s">'$$ = $1;'</span><span class="p">,</span> <span class="nx">options</span><span class="p">]</span> <span class="k">unless</span> <span class="nx">action</span>
|
||||
<span class="nv">action = </span><span class="k">if</span> <span class="nv">match = </span><span class="nx">unwrap</span><span class="p">.</span><span class="nx">exec</span> <span class="nx">action</span> <span class="k">then</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">else</span> <span class="s">"(</span><span class="si">#{</span><span class="nx">action</span><span class="si">}</span><span class="s">())"</span>
|
||||
<span class="nv">action = </span><span class="nx">action</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\bnew /g</span><span class="p">,</span> <span class="s">'$&yy.'</span>
|
||||
<span class="nv">action = </span><span class="nx">action</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\b(?:Block\.wrap|extend)\b/g</span><span class="p">,</span> <span class="s">'yy.$&'</span>
|
||||
<span class="p">[</span><span class="nx">patternString</span><span class="p">,</span> <span class="s">"$$ = </span><span class="si">#{</span><span class="nx">action</span><span class="si">}</span><span class="s">;"</span><span class="p">,</span> <span class="nx">options</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <h2>Grammatical Rules</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>In all of the rules that follow, you'll see the name of the nonterminal as
|
||||
the key to a list of alternative matches. With each match's action, the
|
||||
dollar-sign variables are provided by Jison as references to the value of
|
||||
their numeric position, so in this rule:</p>
|
||||
@@ -35,326 +35,331 @@ their numeric position, so in this rule:</p>
|
||||
<p><code>$1</code> would be the value of the first <code>Expression</code>, <code>$2</code> would be the token
|
||||
for the <code>UNLESS</code> terminal, and <code>$3</code> would be the value of the second
|
||||
<code>Expression</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">grammar =</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>The <strong>Root</strong> is the top-level node in the syntax tree. Since we parse bottom-up,
|
||||
all parsing must end here.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Root</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">''</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Block</span>
|
||||
<span class="nx">o</span> <span class="s1">'Body'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Block TERMINATOR'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Any list of statements and expressions, separated by line breaks or semicolons.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Body</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Line'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s1">'Body TERMINATOR Line'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">push</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'Body TERMINATOR'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Block and statements, which make up a line in a body.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Line</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Statement'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Pure statements which cannot be expressions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Statement</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Return'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Throw'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Comment'</span>
|
||||
<span class="nx">o</span> <span class="s1">'STATEMENT'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
all parsing must end here.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Root: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">''</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Block</span>
|
||||
<span class="nx">o</span> <span class="s">'Body'</span>
|
||||
<span class="nx">o</span> <span class="s">'Block TERMINATOR'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Any list of statements and expressions, separated by line breaks or semicolons.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Body: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Line'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s">'Body TERMINATOR Line'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">push</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'Body TERMINATOR'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Block and statements, which make up a line in a body.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Line: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression'</span>
|
||||
<span class="nx">o</span> <span class="s">'Statement'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Pure statements which cannot be expressions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Statement: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Return'</span>
|
||||
<span class="nx">o</span> <span class="s">'Comment'</span>
|
||||
<span class="nx">o</span> <span class="s">'STATEMENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>All the different types of expressions in our language. The basic unit of
|
||||
CoffeeScript is the <strong>Expression</strong> -- everything that can be an expression
|
||||
is one. Blocks serve as the building blocks of many other rules, making
|
||||
them somewhat circular.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Expression</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Value'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Invocation'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Code'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Operation'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Assign'</span>
|
||||
<span class="nx">o</span> <span class="s1">'If'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Try'</span>
|
||||
<span class="nx">o</span> <span class="s1">'While'</span>
|
||||
<span class="nx">o</span> <span class="s1">'For'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Switch'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Class'</span>
|
||||
them somewhat circular.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Expression: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Value'</span>
|
||||
<span class="nx">o</span> <span class="s">'Invocation'</span>
|
||||
<span class="nx">o</span> <span class="s">'Code'</span>
|
||||
<span class="nx">o</span> <span class="s">'Operation'</span>
|
||||
<span class="nx">o</span> <span class="s">'Assign'</span>
|
||||
<span class="nx">o</span> <span class="s">'If'</span>
|
||||
<span class="nx">o</span> <span class="s">'Try'</span>
|
||||
<span class="nx">o</span> <span class="s">'While'</span>
|
||||
<span class="nx">o</span> <span class="s">'For'</span>
|
||||
<span class="nx">o</span> <span class="s">'Switch'</span>
|
||||
<span class="nx">o</span> <span class="s">'Class'</span>
|
||||
<span class="nx">o</span> <span class="s">'Throw'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>An indented block of expressions. Note that the <a href="rewriter.html">Rewriter</a>
|
||||
will convert some postfix forms into blocks for us, by adjusting the
|
||||
token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Block</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'INDENT OUTDENT'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Block</span>
|
||||
<span class="nx">o</span> <span class="s1">'INDENT Body OUTDENT'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>A literal identifier, a variable name or property.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Identifier</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Block: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'INDENT OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Block</span>
|
||||
<span class="nx">o</span> <span class="s">'INDENT Body OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>A literal identifier, a variable name or property.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Identifier: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'IDENTIFIER'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>Alphanumerics are separated from the other <strong>Literal</strong> matchers because
|
||||
they can also serve as keys in object literals.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">AlphaNumeric</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'NUMBER'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'STRING'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
they can also serve as keys in object literals.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">AlphaNumeric: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'NUMBER'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'STRING'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>All of our immediate values. Generally these can be passed straight
|
||||
through and printed to JavaScript.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Literal</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'AlphaNumeric'</span>
|
||||
<span class="nx">o</span> <span class="s1">'JS'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'REGEX'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'BOOL'</span><span class="p">,</span> <span class="o">-></span>
|
||||
<span class="nv">val = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="nv">val.isUndefined = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">$1</span> <span class="o">is</span> <span class="s1">'undefined'</span>
|
||||
<span class="nx">val</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <p>Assignment of a variable, property, or index to a value.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Assign</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Assignable = Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'Assignable = INDENT Expression OUTDENT'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
through and printed to JavaScript.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Literal: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'AlphaNumeric'</span>
|
||||
<span class="nx">o</span> <span class="s">'JS'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'REGEX'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'DEBUGGER'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'UNDEFINED'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Undefined</span>
|
||||
<span class="nx">o</span> <span class="s">'NULL'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Null</span>
|
||||
<span class="nx">o</span> <span class="s">'BOOL'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Bool</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <p>Assignment of a variable, property, or index to a value.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Assign: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Assignable = Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'Assignable = TERMINATOR Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s">'Assignable = INDENT Expression OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <p>Assignment when it happens within an object literal. The difference from
|
||||
the ordinary <strong>Assign</strong> is that these allow numbers and strings as keys.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">AssignObj</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'ObjAssignable'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'ObjAssignable : Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="nx">$1</span><span class="p">),</span> <span class="nx">$3</span><span class="p">,</span> <span class="s1">'object'</span>
|
||||
<span class="nx">o</span> <span class="s1">'ObjAssignable :</span>
|
||||
<span class="s1"> INDENT Expression OUTDENT'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="nx">$1</span><span class="p">),</span> <span class="nx">$4</span><span class="p">,</span> <span class="s1">'object'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Comment'</span>
|
||||
the ordinary <strong>Assign</strong> is that these allow numbers and strings as keys.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">AssignObj: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'ObjAssignable'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'ObjAssignable : Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="nx">$1</span><span class="p">),</span> <span class="nx">$3</span><span class="p">,</span> <span class="s">'object'</span>
|
||||
<span class="nx">o</span> <span class="s">'ObjAssignable :</span>
|
||||
<span class="s"> INDENT Expression OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="nx">$1</span><span class="p">),</span> <span class="nx">$4</span><span class="p">,</span> <span class="s">'object'</span>
|
||||
<span class="nx">o</span> <span class="s">'Comment'</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nx">ObjAssignable</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Identifier'</span>
|
||||
<span class="nx">o</span> <span class="s1">'AlphaNumeric'</span>
|
||||
<span class="nx">o</span> <span class="s1">'ThisProperty'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</a> </div> <p>A return statement from a function body.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Return</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'RETURN Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Return</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'RETURN'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Return</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">¶</a> </div> <p>A block comment.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Comment</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'HERECOMMENT'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Comment</span> <span class="nx">$1</span>
|
||||
<span class="nv">ObjAssignable: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Identifier'</span>
|
||||
<span class="nx">o</span> <span class="s">'AlphaNumeric'</span>
|
||||
<span class="nx">o</span> <span class="s">'ThisProperty'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</a> </div> <p>A return statement from a function body.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Return: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'RETURN Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Return</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'RETURN'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Return</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">¶</a> </div> <p>A block comment.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Comment: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'HERECOMMENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Comment</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">¶</a> </div> <p>The <strong>Code</strong> node is the function literal. It's defined by an indented block
|
||||
of <strong>Block</strong> preceded by a function arrow, with an optional parameter
|
||||
list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Code</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'PARAM_START ParamList PARAM_END FuncGlyph Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Code</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$5</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s1">'FuncGlyph Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Code</span> <span class="p">[],</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span>
|
||||
list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Code: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'PARAM_START ParamList PARAM_END FuncGlyph Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Code</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$5</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s">'FuncGlyph Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Code</span> <span class="p">[],</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">¶</a> </div> <p>CoffeeScript has two different symbols for functions. <code>-></code> is for ordinary
|
||||
functions, and <code>=></code> is for functions bound to the current value of <em>this</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">FuncGlyph</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'->'</span><span class="p">,</span> <span class="o">-></span> <span class="s1">'func'</span>
|
||||
<span class="nx">o</span> <span class="s1">'=>'</span><span class="p">,</span> <span class="o">-></span> <span class="s1">'boundfunc'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">¶</a> </div> <p>An optional, trailing comma.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">OptComma</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">''</span>
|
||||
<span class="nx">o</span> <span class="s1">','</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">¶</a> </div> <p>The list of parameters that a function accepts can be of any length.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ParamList</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">''</span><span class="p">,</span> <span class="o">-></span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s1">'Param'</span><span class="p">,</span> <span class="o">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s1">'ParamList , Param'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$3</span>
|
||||
functions, and <code>=></code> is for functions bound to the current value of <em>this</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">FuncGlyph: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'->'</span><span class="p">,</span> <span class="nf">-></span> <span class="s">'func'</span>
|
||||
<span class="nx">o</span> <span class="s">'=>'</span><span class="p">,</span> <span class="nf">-></span> <span class="s">'boundfunc'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">¶</a> </div> <p>An optional, trailing comma.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">OptComma: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">''</span>
|
||||
<span class="nx">o</span> <span class="s">','</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">¶</a> </div> <p>The list of parameters that a function accepts can be of any length.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ParamList: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">''</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s">'Param'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s">'ParamList , Param'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'ParamList OptComma TERMINATOR Param'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s">'ParamList OptComma INDENT ParamList OptComma OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$4</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">¶</a> </div> <p>A single parameter in a function definition can be ordinary, or a splat
|
||||
that hoovers up the remaining arguments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Param</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'ParamVar'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Param</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'ParamVar ...'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Param</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">on</span>
|
||||
<span class="nx">o</span> <span class="s1">'ParamVar = Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Param</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">¶</a> </div> <p>Function Parameters</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ParamVar</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Identifier'</span>
|
||||
<span class="nx">o</span> <span class="s1">'ThisProperty'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Array'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Object'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">¶</a> </div> <p>A splat that occurs outside of a parameter list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Splat</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression ...'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Splat</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-28">¶</a> </div> <p>Variables and properties that can be assigned to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">SimpleAssignable</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Identifier'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'Value Accessor'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">add</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'Invocation Accessor'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span><span class="p">,</span> <span class="p">[</span><span class="nx">$2</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s1">'ThisProperty'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-29">¶</a> </div> <p>Everything that can be assigned to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Assignable</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'SimpleAssignable'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Array'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'Object'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
that hoovers up the remaining arguments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Param: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'ParamVar'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Param</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'ParamVar ...'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Param</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">on</span>
|
||||
<span class="nx">o</span> <span class="s">'ParamVar = Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Param</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">¶</a> </div> <p>Function Parameters</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ParamVar: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Identifier'</span>
|
||||
<span class="nx">o</span> <span class="s">'ThisProperty'</span>
|
||||
<span class="nx">o</span> <span class="s">'Array'</span>
|
||||
<span class="nx">o</span> <span class="s">'Object'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">¶</a> </div> <p>A splat that occurs outside of a parameter list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Splat: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression ...'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Splat</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-28">¶</a> </div> <p>Variables and properties that can be assigned to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">SimpleAssignable: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Identifier'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'Value Accessor'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">add</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'Invocation Accessor'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span><span class="p">,</span> <span class="p">[].</span><span class="nx">concat</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'ThisProperty'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-29">¶</a> </div> <p>Everything that can be assigned to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Assignable: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'SimpleAssignable'</span>
|
||||
<span class="nx">o</span> <span class="s">'Array'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'Object'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-30">¶</a> </div> <p>The types of things that can be treated as values -- assigned to, invoked
|
||||
as functions, indexed into, named as a class, etc.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Value</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Assignable'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Literal'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'Parenthetical'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'Range'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'This'</span>
|
||||
as functions, indexed into, named as a class, etc.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Value: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Assignable'</span>
|
||||
<span class="nx">o</span> <span class="s">'Literal'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'Parenthetical'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'Range'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'This'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-31">¶</a> </div> <p>The general group of accessors into an object, by property, by prototype
|
||||
or by array index or slice.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Accessor</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'. Identifier'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Access</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'?. Identifier'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Access</span> <span class="nx">$2</span><span class="p">,</span> <span class="s1">'soak'</span>
|
||||
<span class="nx">o</span> <span class="s1">':: Identifier'</span><span class="p">,</span> <span class="o">-></span> <span class="p">[(</span><span class="k">new</span> <span class="nx">Access</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s1">'prototype'</span><span class="p">),</span> <span class="k">new</span> <span class="nx">Access</span> <span class="nx">$2</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s1">'::'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Access</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s1">'prototype'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Index'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-32">¶</a> </div> <p>Indexing into an object or array using bracket notation.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Index</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'INDEX_START IndexValue INDEX_END'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'INDEX_SOAK Index'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">extend</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">soak</span> <span class="o">:</span> <span class="kc">yes</span>
|
||||
or by array index or slice.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Accessor: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'. Identifier'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Access</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'?. Identifier'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Access</span> <span class="nx">$2</span><span class="p">,</span> <span class="s">'soak'</span>
|
||||
<span class="nx">o</span> <span class="s">':: Identifier'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[(</span><span class="k">new</span> <span class="nx">Access</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">'prototype'</span><span class="p">),</span> <span class="k">new</span> <span class="nx">Access</span> <span class="nx">$2</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s">'::'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Access</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">'prototype'</span>
|
||||
<span class="nx">o</span> <span class="s">'Index'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-32">¶</a> </div> <p>Indexing into an object or array using bracket notation.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Index: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'INDEX_START IndexValue INDEX_END'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'INDEX_SOAK Index'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">extend</span> <span class="nx">$2</span><span class="p">,</span> <span class="nv">soak : </span><span class="kc">yes</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nx">IndexValue</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Index</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'Slice'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Slice</span> <span class="nx">$1</span>
|
||||
<span class="nv">IndexValue: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Index</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'Slice'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Slice</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-33"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-33">¶</a> </div> <p>In CoffeeScript, an object literal is simply a list of assignments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nb">Object</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'{ AssignList OptComma }'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Obj</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">generated</span>
|
||||
<span class="nx">o</span> <span class="s">'{ AssignList OptComma }'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Obj</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">generated</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-34">¶</a> </div> <p>Assignment of properties within an object literal can be separated by
|
||||
comma, as in JavaScript, or simply by newline.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">AssignList</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">''</span><span class="p">,</span> <span class="o">-></span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s1">'AssignObj'</span><span class="p">,</span> <span class="o">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s1">'AssignList , AssignObj'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'AssignList OptComma TERMINATOR AssignObj'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s1">'AssignList OptComma INDENT AssignList OptComma OUTDENT'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$4</span>
|
||||
comma, as in JavaScript, or simply by newline.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">AssignList: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">''</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s">'AssignObj'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s">'AssignList , AssignObj'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'AssignList OptComma TERMINATOR AssignObj'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s">'AssignList OptComma INDENT AssignList OptComma OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$4</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-35">¶</a> </div> <p>Class definitions have optional bodies of prototype property assignments,
|
||||
and optional references to the superclass.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Class</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'CLASS'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Class</span>
|
||||
<span class="nx">o</span> <span class="s1">'CLASS Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'CLASS EXTENDS Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'CLASS EXTENDS Expression Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s1">'CLASS SimpleAssignable'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'CLASS SimpleAssignable Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'CLASS SimpleAssignable EXTENDS Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s1">'CLASS SimpleAssignable EXTENDS Expression Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$5</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-36"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-36">¶</a> </div> <p>Ordinary function invocation, or a chained series of calls.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Invocation</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Value OptFuncExist Arguments'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Call</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'Invocation OptFuncExist Arguments'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Call</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'SUPER'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Call</span> <span class="s1">'super'</span><span class="p">,</span> <span class="p">[</span><span class="k">new</span> <span class="nx">Splat</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s1">'arguments'</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s1">'SUPER Arguments'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Call</span> <span class="s1">'super'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-37"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-37">¶</a> </div> <p>An optional existence check on a function.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">OptFuncExist</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">''</span><span class="p">,</span> <span class="o">-></span> <span class="kc">no</span>
|
||||
<span class="nx">o</span> <span class="s1">'FUNC_EXIST'</span><span class="p">,</span> <span class="o">-></span> <span class="kc">yes</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-38"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-38">¶</a> </div> <p>The list of arguments to a function call.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Arguments</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'CALL_START CALL_END'</span><span class="p">,</span> <span class="o">-></span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s1">'CALL_START ArgList OptComma CALL_END'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-39"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-39">¶</a> </div> <p>A reference to the <em>this</em> current object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">This</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'THIS'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s1">'this'</span>
|
||||
<span class="nx">o</span> <span class="s1">'@'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s1">'this'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-40">¶</a> </div> <p>A reference to a property on <em>this</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ThisProperty</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'@ Identifier'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="k">new</span> <span class="nx">Literal</span><span class="p">(</span><span class="s1">'this'</span><span class="p">),</span> <span class="p">[</span><span class="k">new</span> <span class="nx">Access</span><span class="p">(</span><span class="nx">$2</span><span class="p">)],</span> <span class="s1">'this'</span>
|
||||
and optional references to the superclass.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Class: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'CLASS'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Class</span>
|
||||
<span class="nx">o</span> <span class="s">'CLASS Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'CLASS EXTENDS Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'CLASS EXTENDS Expression Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s">'CLASS SimpleAssignable'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'CLASS SimpleAssignable Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'CLASS SimpleAssignable EXTENDS Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s">'CLASS SimpleAssignable EXTENDS Expression Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$5</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-36"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-36">¶</a> </div> <p>Ordinary function invocation, or a chained series of calls.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Invocation: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Value OptFuncExist Arguments'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Call</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'Invocation OptFuncExist Arguments'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Call</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'SUPER'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Call</span> <span class="s">'super'</span><span class="p">,</span> <span class="p">[</span><span class="k">new</span> <span class="nx">Splat</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">'arguments'</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s">'SUPER Arguments'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Call</span> <span class="s">'super'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-37"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-37">¶</a> </div> <p>An optional existence check on a function.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">OptFuncExist: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">''</span><span class="p">,</span> <span class="nf">-></span> <span class="kc">no</span>
|
||||
<span class="nx">o</span> <span class="s">'FUNC_EXIST'</span><span class="p">,</span> <span class="nf">-></span> <span class="kc">yes</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-38"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-38">¶</a> </div> <p>The list of arguments to a function call.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Arguments: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'CALL_START CALL_END'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s">'CALL_START ArgList OptComma CALL_END'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-39"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-39">¶</a> </div> <p>A reference to the <em>this</em> current object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">This: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'THIS'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">'this'</span>
|
||||
<span class="nx">o</span> <span class="s">'@'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">'this'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-40">¶</a> </div> <p>A reference to a property on <em>this</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ThisProperty: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'@ Identifier'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="k">new</span> <span class="nx">Literal</span><span class="p">(</span><span class="s">'this'</span><span class="p">),</span> <span class="p">[</span><span class="k">new</span> <span class="nx">Access</span><span class="p">(</span><span class="nx">$2</span><span class="p">)],</span> <span class="s">'this'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-41">¶</a> </div> <p>The array literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nb">Array</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'[ ]'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Arr</span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s1">'[ ArgList OptComma ]'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Arr</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-42">¶</a> </div> <p>Inclusive and exclusive range dots.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">RangeDots</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'..'</span><span class="p">,</span> <span class="o">-></span> <span class="s1">'inclusive'</span>
|
||||
<span class="nx">o</span> <span class="s1">'...'</span><span class="p">,</span> <span class="o">-></span> <span class="s1">'exclusive'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-43">¶</a> </div> <p>The CoffeeScript range literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Range</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'[ Expression RangeDots Expression ]'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Range</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-44"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-44">¶</a> </div> <p>Array slice literals.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Slice</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression RangeDots Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Range</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression RangeDots'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Range</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'RangeDots Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Range</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'[ ]'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Arr</span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s">'[ ArgList OptComma ]'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Arr</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-42">¶</a> </div> <p>Inclusive and exclusive range dots.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">RangeDots: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'..'</span><span class="p">,</span> <span class="nf">-></span> <span class="s">'inclusive'</span>
|
||||
<span class="nx">o</span> <span class="s">'...'</span><span class="p">,</span> <span class="nf">-></span> <span class="s">'exclusive'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-43">¶</a> </div> <p>The CoffeeScript range literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Range: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'[ Expression RangeDots Expression ]'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Range</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-44"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-44">¶</a> </div> <p>Array slice literals.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Slice: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression RangeDots Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Range</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression RangeDots'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Range</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'RangeDots Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Range</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'RangeDots'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Range</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-45"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-45">¶</a> </div> <p>The <strong>ArgList</strong> is both the list of objects passed into a function call,
|
||||
as well as the contents of an array literal
|
||||
(i.e. comma-separated expressions). Newlines work as well.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ArgList</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Arg'</span><span class="p">,</span> <span class="o">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s1">'ArgList , Arg'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'ArgList OptComma TERMINATOR Arg'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s1">'INDENT ArgList OptComma OUTDENT'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'ArgList OptComma INDENT ArgList OptComma OUTDENT'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$4</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-46"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-46">¶</a> </div> <p>Valid arguments are Blocks or Splats.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Arg</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Splat'</span>
|
||||
(i.e. comma-separated expressions). Newlines work as well.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ArgList: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Arg'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s">'ArgList , Arg'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'ArgList OptComma TERMINATOR Arg'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s">'INDENT ArgList OptComma OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'ArgList OptComma INDENT ArgList OptComma OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$4</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-46"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-46">¶</a> </div> <p>Valid arguments are Blocks or Splats.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Arg: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression'</span>
|
||||
<span class="nx">o</span> <span class="s">'Splat'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-47"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-47">¶</a> </div> <p>Just simple, comma-separated, required arguments (no fancy syntax). We need
|
||||
this to be separate from the <strong>ArgList</strong> for use in <strong>Switch</strong> blocks, where
|
||||
having the newlines wouldn't make sense.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">SimpleArgs</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression'</span>
|
||||
<span class="nx">o</span> <span class="s1">'SimpleArgs , Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="p">[].</span><span class="nx">concat</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-48"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-48">¶</a> </div> <p>The variants of <em>try/catch/finally</em> exception handling blocks.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Try</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'TRY Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Try</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'TRY Block Catch'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Try</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s1">'TRY Block FINALLY Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Try</span> <span class="nx">$2</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s1">'TRY Block Catch FINALLY Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Try</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="nx">$5</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-49">¶</a> </div> <p>A catch clause names its error and runs a block of code.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Catch</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'CATCH Identifier Block'</span><span class="p">,</span> <span class="o">-></span> <span class="p">[</span><span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-50"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-50">¶</a> </div> <p>Throw an exception object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Throw</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'THROW Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Throw</span> <span class="nx">$2</span>
|
||||
having the newlines wouldn't make sense.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">SimpleArgs: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression'</span>
|
||||
<span class="nx">o</span> <span class="s">'SimpleArgs , Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[].</span><span class="nx">concat</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-48"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-48">¶</a> </div> <p>The variants of <em>try/catch/finally</em> exception handling blocks.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Try: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'TRY Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Try</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'TRY Block Catch'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Try</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s">'TRY Block FINALLY Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Try</span> <span class="nx">$2</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s">'TRY Block Catch FINALLY Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Try</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="nx">$5</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-49">¶</a> </div> <p>A catch clause names its error and runs a block of code.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Catch: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'CATCH Identifier Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[</span><span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-50"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-50">¶</a> </div> <p>Throw an exception object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Throw: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'THROW Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Throw</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-51">¶</a> </div> <p>Parenthetical expressions. Note that the <strong>Parenthetical</strong> is a <strong>Value</strong>,
|
||||
not an <strong>Expression</strong>, so if you need to use an expression in a place
|
||||
where only values are accepted, wrapping it in parentheses will always do
|
||||
the trick.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Parenthetical</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'( Body )'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Parens</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'( INDENT Body OUTDENT )'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Parens</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-52">¶</a> </div> <p>The condition portion of a while loop.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">WhileSource</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'WHILE Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">While</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'WHILE Expression WHEN Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">While</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s1">'UNTIL Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">While</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">invert</span><span class="o">:</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s1">'UNTIL Expression WHEN Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">While</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">invert</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$4</span>
|
||||
the trick.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Parenthetical: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'( Body )'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Parens</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'( INDENT Body OUTDENT )'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Parens</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-52">¶</a> </div> <p>The condition portion of a while loop.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">WhileSource: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'WHILE Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">While</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'WHILE Expression WHEN Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">While</span> <span class="nx">$2</span><span class="p">,</span> <span class="nv">guard: </span><span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s">'UNTIL Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">While</span> <span class="nx">$2</span><span class="p">,</span> <span class="nv">invert: </span><span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s">'UNTIL Expression WHEN Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">While</span> <span class="nx">$2</span><span class="p">,</span> <span class="nv">invert: </span><span class="kc">true</span><span class="p">,</span> <span class="nv">guard: </span><span class="nx">$4</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-53"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-53">¶</a> </div> <p>The while loop can either be normal, with a block of expressions to execute,
|
||||
or postfix, with a single expression. There is no do..while.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">While</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'WhileSource Block'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">addBody</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'Statement WhileSource'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span><span class="p">.</span><span class="nx">addBody</span> <span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression WhileSource'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span><span class="p">.</span><span class="nx">addBody</span> <span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s1">'Loop'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span>
|
||||
or postfix, with a single expression. There is no do..while.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">While: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'WhileSource Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">addBody</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'Statement WhileSource'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$2</span><span class="p">.</span><span class="nx">addBody</span> <span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression WhileSource'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$2</span><span class="p">.</span><span class="nx">addBody</span> <span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s">'Loop'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nx">Loop</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'LOOP Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">While</span><span class="p">(</span><span class="k">new</span> <span class="nx">Literal</span> <span class="s1">'true'</span><span class="p">).</span><span class="nx">addBody</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'LOOP Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">While</span><span class="p">(</span><span class="k">new</span> <span class="nx">Literal</span> <span class="s1">'true'</span><span class="p">).</span><span class="nx">addBody</span> <span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$2</span><span class="p">]</span>
|
||||
<span class="nv">Loop: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'LOOP Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">While</span><span class="p">(</span><span class="k">new</span> <span class="nx">Literal</span> <span class="s">'true'</span><span class="p">).</span><span class="nx">addBody</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'LOOP Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">While</span><span class="p">(</span><span class="k">new</span> <span class="nx">Literal</span> <span class="s">'true'</span><span class="p">).</span><span class="nx">addBody</span> <span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$2</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-54">¶</a> </div> <p>Array, object, and range comprehensions, at the most generic level.
|
||||
Comprehensions can either be normal, with a block of expressions to execute,
|
||||
or postfix, with a single expression.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">For</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Statement ForBody'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">For</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression ForBody'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">For</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'ForBody Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">For</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span>
|
||||
or postfix, with a single expression.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">For: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Statement ForBody'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">For</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression ForBody'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">For</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'ForBody Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">For</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nx">ForBody</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'FOR Range'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">source</span><span class="o">:</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="nx">$2</span><span class="p">)</span>
|
||||
<span class="nx">o</span> <span class="s1">'ForStart ForSource'</span><span class="p">,</span> <span class="o">-></span> <span class="nv">$2.own = </span><span class="nx">$1</span><span class="p">.</span><span class="nx">own</span><span class="p">;</span> <span class="nv">$2.name = </span><span class="nx">$1</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> <span class="nv">$2.index = </span><span class="nx">$1</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span> <span class="nx">$2</span>
|
||||
<span class="nv">ForBody: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'FOR Range'</span><span class="p">,</span> <span class="nf">-></span> <span class="nv">source: </span><span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="nx">$2</span><span class="p">)</span>
|
||||
<span class="nx">o</span> <span class="s">'ForStart ForSource'</span><span class="p">,</span> <span class="nf">-></span> <span class="nv">$2.own = </span><span class="nx">$1</span><span class="p">.</span><span class="nx">own</span><span class="p">;</span> <span class="nv">$2.name = </span><span class="nx">$1</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> <span class="nv">$2.index = </span><span class="nx">$1</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nx">ForStart</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'FOR ForVariables'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'FOR OWN ForVariables'</span><span class="p">,</span> <span class="o">-></span> <span class="nv">$3.own = </span><span class="kc">yes</span><span class="p">;</span> <span class="nx">$3</span>
|
||||
<span class="nv">ForStart: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'FOR ForVariables'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'FOR OWN ForVariables'</span><span class="p">,</span> <span class="nf">-></span> <span class="nv">$3.own = </span><span class="kc">yes</span><span class="p">;</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-55">¶</a> </div> <p>An array of all accepted values for a variable inside the loop.
|
||||
This enables support for pattern matching.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ForValue</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Identifier'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Array'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'Object'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
This enables support for pattern matching.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ForValue: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Identifier'</span>
|
||||
<span class="nx">o</span> <span class="s">'ThisProperty'</span>
|
||||
<span class="nx">o</span> <span class="s">'Array'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'Object'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-56"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-56">¶</a> </div> <p>An array or range comprehension has variables for the current element
|
||||
and (optional) reference to the current index. Or, <em>key, value</em>, in the case
|
||||
of object comprehensions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ForVariables</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'ForValue'</span><span class="p">,</span> <span class="o">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s1">'ForValue , ForValue'</span><span class="p">,</span> <span class="o">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]</span>
|
||||
of object comprehensions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ForVariables: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'ForValue'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s">'ForValue , ForValue'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-57"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-57">¶</a> </div> <p>The source of a comprehension is an array or object with an optional guard
|
||||
clause. If it's an array comprehension, you can also choose to step through
|
||||
in fixed-size increments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ForSource</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'FORIN Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'FOROF Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">object</span><span class="o">:</span> <span class="kc">yes</span>
|
||||
<span class="nx">o</span> <span class="s1">'FORIN Expression WHEN Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s1">'FOROF Expression WHEN Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">object</span><span class="o">:</span> <span class="kc">yes</span>
|
||||
<span class="nx">o</span> <span class="s1">'FORIN Expression BY Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">step</span><span class="o">:</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s1">'FORIN Expression WHEN Expression BY Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">step</span><span class="o">:</span> <span class="nx">$6</span>
|
||||
<span class="nx">o</span> <span class="s1">'FORIN Expression BY Expression WHEN Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">step</span><span class="o">:</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$6</span>
|
||||
in fixed-size increments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ForSource: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'FORIN Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="nv">source: </span><span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'FOROF Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">object: </span><span class="kc">yes</span>
|
||||
<span class="nx">o</span> <span class="s">'FORIN Expression WHEN Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">guard: </span><span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s">'FOROF Expression WHEN Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">guard: </span><span class="nx">$4</span><span class="p">,</span> <span class="nv">object: </span><span class="kc">yes</span>
|
||||
<span class="nx">o</span> <span class="s">'FORIN Expression BY Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">step: </span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s">'FORIN Expression WHEN Expression BY Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">guard: </span><span class="nx">$4</span><span class="p">,</span> <span class="nv">step: </span><span class="nx">$6</span>
|
||||
<span class="nx">o</span> <span class="s">'FORIN Expression BY Expression WHEN Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">step: </span> <span class="nx">$4</span><span class="p">,</span> <span class="nv">guard: </span><span class="nx">$6</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nx">Switch</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'SWITCH Expression INDENT Whens OUTDENT'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Switch</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s1">'SWITCH Expression INDENT Whens ELSE Block OUTDENT'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Switch</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$6</span>
|
||||
<span class="nx">o</span> <span class="s1">'SWITCH INDENT Whens OUTDENT'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Switch</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'SWITCH INDENT Whens ELSE Block OUTDENT'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Switch</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$5</span>
|
||||
<span class="nv">Switch: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'SWITCH Expression INDENT Whens OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Switch</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s">'SWITCH Expression INDENT Whens ELSE Block OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Switch</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$6</span>
|
||||
<span class="nx">o</span> <span class="s">'SWITCH INDENT Whens OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Switch</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'SWITCH INDENT Whens ELSE Block OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Switch</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$5</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nx">Whens</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'When'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Whens When'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-58"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-58">¶</a> </div> <p>An individual <strong>When</strong> clause, with action.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">When</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'LEADING_WHEN SimpleArgs Block'</span><span class="p">,</span> <span class="o">-></span> <span class="p">[[</span><span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]]</span>
|
||||
<span class="nx">o</span> <span class="s1">'LEADING_WHEN SimpleArgs Block TERMINATOR'</span><span class="p">,</span> <span class="o">-></span> <span class="p">[[</span><span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]]</span>
|
||||
<span class="nv">Whens: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'When'</span>
|
||||
<span class="nx">o</span> <span class="s">'Whens When'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-58"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-58">¶</a> </div> <p>An individual <strong>When</strong> clause, with action.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">When: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'LEADING_WHEN SimpleArgs Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[[</span><span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]]</span>
|
||||
<span class="nx">o</span> <span class="s">'LEADING_WHEN SimpleArgs Block TERMINATOR'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[[</span><span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-59"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-59">¶</a> </div> <p>The most basic form of <em>if</em> is a condition and an action. The following
|
||||
if-related rules are broken up along these lines in order to avoid
|
||||
ambiguity.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">IfBlock</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'IF Expression Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'IfBlock ELSE IF Expression Block'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">addElse</span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$5</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="nx">$3</span>
|
||||
ambiguity.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">IfBlock: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'IF Expression Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nv">type: </span><span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'IfBlock ELSE IF Expression Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">addElse</span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$5</span><span class="p">,</span> <span class="nv">type: </span><span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-60"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-60">¶</a> </div> <p>The full complement of <em>if</em> expressions, including postfix one-liner
|
||||
<em>if</em> and <em>unless</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">If</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'IfBlock'</span>
|
||||
<span class="nx">o</span> <span class="s1">'IfBlock ELSE Block'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">addElse</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'Statement POST_IF Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="nx">$1</span><span class="p">]),</span> <span class="nx">type</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">statement</span><span class="o">:</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression POST_IF Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="nx">$1</span><span class="p">]),</span> <span class="nx">type</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">statement</span><span class="o">:</span> <span class="kc">true</span>
|
||||
<em>if</em> and <em>unless</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">If: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'IfBlock'</span>
|
||||
<span class="nx">o</span> <span class="s">'IfBlock ELSE Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">addElse</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'Statement POST_IF Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="nx">$1</span><span class="p">]),</span> <span class="nv">type: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">statement: </span><span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression POST_IF Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="nx">$1</span><span class="p">]),</span> <span class="nv">type: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">statement: </span><span class="kc">true</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-61"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-61">¶</a> </div> <p>Arithmetic and logical operators, working on one or more operands.
|
||||
Here they are grouped by order of precedence. The actual precedence rules
|
||||
are defined at the bottom of the page. It would be shorter if we could
|
||||
combine most of these rules into a single generic <em>Operand OpSymbol Operand</em>
|
||||
-type rule, but in order to make the precedence binding possible, separate
|
||||
rules are necessary.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Operation</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'UNARY Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="nx">$1</span> <span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'- Expression'</span><span class="p">,</span> <span class="p">(</span><span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="s1">'-'</span><span class="p">,</span> <span class="nx">$2</span><span class="p">),</span> <span class="nx">prec</span><span class="o">:</span> <span class="s1">'UNARY'</span>
|
||||
<span class="nx">o</span> <span class="s1">'+ Expression'</span><span class="p">,</span> <span class="p">(</span><span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="s1">'+'</span><span class="p">,</span> <span class="nx">$2</span><span class="p">),</span> <span class="nx">prec</span><span class="o">:</span> <span class="s1">'UNARY'</span>
|
||||
rules are necessary.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Operation: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'UNARY Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="nx">$1</span> <span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'- Expression'</span><span class="p">,</span> <span class="p">(</span><span class="nf">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="s">'-'</span><span class="p">,</span> <span class="nx">$2</span><span class="p">),</span> <span class="nv">prec: </span><span class="s">'UNARY'</span>
|
||||
<span class="nx">o</span> <span class="s">'+ Expression'</span><span class="p">,</span> <span class="p">(</span><span class="nf">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="s">'+'</span><span class="p">,</span> <span class="nx">$2</span><span class="p">),</span> <span class="nv">prec: </span><span class="s">'UNARY'</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s1">'-- SimpleAssignable'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="s1">'--'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'++ SimpleAssignable'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="s1">'++'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'SimpleAssignable --'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="s1">'--'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s1">'SimpleAssignable ++'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="s1">'++'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">true</span></pre></div> </td> </tr> <tr id="section-62"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-62">¶</a> </div> <p><a href="http://jashkenas.github.com/coffee-script/#existence">The existential operator</a>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">o</span> <span class="s1">'Expression ?'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Existence</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'-- SimpleAssignable'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="s">'--'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'++ SimpleAssignable'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="s">'++'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'SimpleAssignable --'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="s">'--'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s">'SimpleAssignable ++'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="s">'++'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">true</span></pre></div> </td> </tr> <tr id="section-62"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-62">¶</a> </div> <p><a href="http://jashkenas.github.com/coffee-script/#existence">The existential operator</a>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">o</span> <span class="s">'Expression ?'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Existence</span> <span class="nx">$1</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s1">'Expression + Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="s1">'+'</span> <span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression - Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="s1">'-'</span> <span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression + Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="s">'+'</span> <span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression - Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="s">'-'</span> <span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s1">'Expression MATH Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression SHIFT Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression COMPARE Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression LOGIC Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression RELATION Expression'</span><span class="p">,</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">$2</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'!'</span>
|
||||
<span class="k">new</span> <span class="nx">Op</span><span class="p">(</span><span class="nx">$2</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">).</span><span class="nx">invert</span><span class="p">()</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression MATH Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression SHIFT Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression COMPARE Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression LOGIC Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression RELATION Expression'</span><span class="p">,</span> <span class="nf">-></span>
|
||||
<span class="k">if</span> <span class="nx">$2</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">is</span> <span class="s">'!'</span>
|
||||
<span class="k">new</span> <span class="nx">Op</span><span class="p">(</span><span class="nx">$2</span><span class="p">[</span><span class="mi">1</span><span class="p">..],</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">).</span><span class="nx">invert</span><span class="p">()</span>
|
||||
<span class="k">else</span>
|
||||
<span class="k">new</span> <span class="nx">Op</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s1">'SimpleAssignable COMPOUND_ASSIGN</span>
|
||||
<span class="s1"> Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'SimpleAssignable COMPOUND_ASSIGN</span>
|
||||
<span class="s1"> INDENT Expression OUTDENT'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'SimpleAssignable EXTENDS Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Extends</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'SimpleAssignable COMPOUND_ASSIGN</span>
|
||||
<span class="s"> Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'SimpleAssignable COMPOUND_ASSIGN</span>
|
||||
<span class="s"> INDENT Expression OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'SimpleAssignable EXTENDS Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Extends</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-63"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-63">¶</a> </div> <h2>Precedence</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-64">¶</a> </div> <p>Operators at the top of this list have higher precedence than the ones lower
|
||||
down. Following these rules is what makes <code>2 + 3 * 4</code> parse as:</p>
|
||||
|
||||
@@ -365,38 +370,38 @@ down. Following these rules is what makes <code>2 + 3 * 4</code> parse as:</p>
|
||||
|
||||
<pre><code>(2 + 3) * 4
|
||||
</code></pre> </td> <td class="code"> <div class="highlight"><pre><span class="nv">operators = </span><span class="p">[</span>
|
||||
<span class="p">[</span><span class="s1">'left'</span><span class="p">,</span> <span class="s1">'.'</span><span class="p">,</span> <span class="s1">'?.'</span><span class="p">,</span> <span class="s1">'::'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'left'</span><span class="p">,</span> <span class="s1">'CALL_START'</span><span class="p">,</span> <span class="s1">'CALL_END'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'nonassoc'</span><span class="p">,</span> <span class="s1">'++'</span><span class="p">,</span> <span class="s1">'--'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'left'</span><span class="p">,</span> <span class="s1">'?'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'right'</span><span class="p">,</span> <span class="s1">'UNARY'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'left'</span><span class="p">,</span> <span class="s1">'MATH'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'left'</span><span class="p">,</span> <span class="s1">'+'</span><span class="p">,</span> <span class="s1">'-'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'left'</span><span class="p">,</span> <span class="s1">'SHIFT'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'left'</span><span class="p">,</span> <span class="s1">'RELATION'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'left'</span><span class="p">,</span> <span class="s1">'COMPARE'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'left'</span><span class="p">,</span> <span class="s1">'LOGIC'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'nonassoc'</span><span class="p">,</span> <span class="s1">'INDENT'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'right'</span><span class="p">,</span> <span class="s1">'='</span><span class="p">,</span> <span class="s1">':'</span><span class="p">,</span> <span class="s1">'COMPOUND_ASSIGN'</span><span class="p">,</span> <span class="s1">'RETURN'</span><span class="p">,</span> <span class="s1">'THROW'</span><span class="p">,</span> <span class="s1">'EXTENDS'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'right'</span><span class="p">,</span> <span class="s1">'FORIN'</span><span class="p">,</span> <span class="s1">'FOROF'</span><span class="p">,</span> <span class="s1">'BY'</span><span class="p">,</span> <span class="s1">'WHEN'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'right'</span><span class="p">,</span> <span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'ELSE'</span><span class="p">,</span> <span class="s1">'FOR'</span><span class="p">,</span> <span class="s1">'DO'</span><span class="p">,</span> <span class="s1">'WHILE'</span><span class="p">,</span> <span class="s1">'UNTIL'</span><span class="p">,</span> <span class="s1">'LOOP'</span><span class="p">,</span> <span class="s1">'SUPER'</span><span class="p">,</span> <span class="s1">'CLASS'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'right'</span><span class="p">,</span> <span class="s1">'POST_IF'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'left'</span><span class="p">,</span> <span class="s">'.'</span><span class="p">,</span> <span class="s">'?.'</span><span class="p">,</span> <span class="s">'::'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'left'</span><span class="p">,</span> <span class="s">'CALL_START'</span><span class="p">,</span> <span class="s">'CALL_END'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'nonassoc'</span><span class="p">,</span> <span class="s">'++'</span><span class="p">,</span> <span class="s">'--'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'left'</span><span class="p">,</span> <span class="s">'?'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'right'</span><span class="p">,</span> <span class="s">'UNARY'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'left'</span><span class="p">,</span> <span class="s">'MATH'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'left'</span><span class="p">,</span> <span class="s">'+'</span><span class="p">,</span> <span class="s">'-'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'left'</span><span class="p">,</span> <span class="s">'SHIFT'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'left'</span><span class="p">,</span> <span class="s">'RELATION'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'left'</span><span class="p">,</span> <span class="s">'COMPARE'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'left'</span><span class="p">,</span> <span class="s">'LOGIC'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'nonassoc'</span><span class="p">,</span> <span class="s">'INDENT'</span><span class="p">,</span> <span class="s">'OUTDENT'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'right'</span><span class="p">,</span> <span class="s">'='</span><span class="p">,</span> <span class="s">':'</span><span class="p">,</span> <span class="s">'COMPOUND_ASSIGN'</span><span class="p">,</span> <span class="s">'RETURN'</span><span class="p">,</span> <span class="s">'THROW'</span><span class="p">,</span> <span class="s">'EXTENDS'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'right'</span><span class="p">,</span> <span class="s">'FORIN'</span><span class="p">,</span> <span class="s">'FOROF'</span><span class="p">,</span> <span class="s">'BY'</span><span class="p">,</span> <span class="s">'WHEN'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'right'</span><span class="p">,</span> <span class="s">'IF'</span><span class="p">,</span> <span class="s">'ELSE'</span><span class="p">,</span> <span class="s">'FOR'</span><span class="p">,</span> <span class="s">'WHILE'</span><span class="p">,</span> <span class="s">'UNTIL'</span><span class="p">,</span> <span class="s">'LOOP'</span><span class="p">,</span> <span class="s">'SUPER'</span><span class="p">,</span> <span class="s">'CLASS'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'right'</span><span class="p">,</span> <span class="s">'POST_IF'</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-65"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-65">¶</a> </div> <h2>Wrapping Up</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-66"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-66">¶</a> </div> <p>Finally, now that we have our <strong>grammar</strong> and our <strong>operators</strong>, we can create
|
||||
our <strong>Jison.Parser</strong>. We do this by processing all of our rules, recording all
|
||||
terminals (every symbol which does not appear as the name of a rule above)
|
||||
as "tokens".</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">tokens = </span><span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">alternatives</span> <span class="k">of</span> <span class="nx">grammar</span>
|
||||
<span class="nx">grammar</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="k">for</span> <span class="nx">alt</span> <span class="k">in</span> <span class="nx">alternatives</span>
|
||||
<span class="k">for</span> <span class="nx">token</span> <span class="k">in</span> <span class="nx">alt</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">split</span> <span class="s1">' '</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="nx">token</span> <span class="nx">unless</span> <span class="nx">grammar</span><span class="p">[</span><span class="nx">token</span><span class="p">]</span>
|
||||
<span class="nx">alt</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"return #{alt[1]}"</span> <span class="k">if</span> <span class="nx">name</span> <span class="o">is</span> <span class="s1">'Root'</span>
|
||||
<span class="k">for</span> <span class="nx">token</span> <span class="k">in</span> <span class="nx">alt</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">split</span> <span class="s">' '</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="nx">token</span> <span class="k">unless</span> <span class="nx">grammar</span><span class="p">[</span><span class="nx">token</span><span class="p">]</span>
|
||||
<span class="nx">alt</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="s">"return </span><span class="si">#{</span><span class="nx">alt</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="si">}</span><span class="s">"</span> <span class="k">if</span> <span class="nx">name</span> <span class="o">is</span> <span class="s">'Root'</span>
|
||||
<span class="nx">alt</span></pre></div> </td> </tr> <tr id="section-67"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-67">¶</a> </div> <p>Initialize the <strong>Parser</strong> with our list of terminal <strong>tokens</strong>, our <strong>grammar</strong>
|
||||
rules, and the name of the root. Reverse the operators because Jison orders
|
||||
precedence from low to high, and we have it high to low
|
||||
(as in <a href="http://dinosaur.compilertools.net/yacc/index.html">Yacc</a>).</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.parser = </span><span class="k">new</span> <span class="nx">Parser</span>
|
||||
<span class="nx">tokens</span> <span class="o">:</span> <span class="nx">tokens</span><span class="p">.</span><span class="nx">join</span> <span class="s1">' '</span>
|
||||
<span class="nx">bnf</span> <span class="o">:</span> <span class="nx">grammar</span>
|
||||
<span class="nx">operators</span> <span class="o">:</span> <span class="nx">operators</span><span class="p">.</span><span class="nx">reverse</span><span class="p">()</span>
|
||||
<span class="nx">startSymbol</span> <span class="o">:</span> <span class="s1">'Root'</span>
|
||||
<span class="nv">tokens : </span><span class="nx">tokens</span><span class="p">.</span><span class="nx">join</span> <span class="s">' '</span>
|
||||
<span class="nv">bnf : </span><span class="nx">grammar</span>
|
||||
<span class="nv">operators : </span><span class="nx">operators</span><span class="p">.</span><span class="nx">reverse</span><span class="p">()</span>
|
||||
<span class="nv">startSymbol : </span><span class="s">'Root'</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -1,21 +1,21 @@
|
||||
<!DOCTYPE html> <html> <head> <title>helpers.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> helpers.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> <p>This file contains the common helper functions that we'd like to share among
|
||||
the <strong>Lexer</strong>, <strong>Rewriter</strong>, and the <strong>Nodes</strong>. Merge objects, flatten
|
||||
arrays, count characters, that sort of thing.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>Peek at the beginning of a given string to see if it matches a sequence.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.starts = </span><span class="p">(</span><span class="nx">string</span><span class="p">,</span> <span class="nx">literal</span><span class="p">,</span> <span class="nx">start</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">literal</span> <span class="o">is</span> <span class="nx">string</span><span class="p">.</span><span class="nx">substr</span> <span class="nx">start</span><span class="p">,</span> <span class="nx">literal</span><span class="p">.</span><span class="nx">length</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Peek at the end of a given string to see if it matches a sequence.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ends = </span><span class="p">(</span><span class="nx">string</span><span class="p">,</span> <span class="nx">literal</span><span class="p">,</span> <span class="nx">back</span><span class="p">)</span> <span class="o">-></span>
|
||||
arrays, count characters, that sort of thing.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>Peek at the beginning of a given string to see if it matches a sequence.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.starts = </span><span class="nf">(string, literal, start) -></span>
|
||||
<span class="nx">literal</span> <span class="o">is</span> <span class="nx">string</span><span class="p">.</span><span class="nx">substr</span> <span class="nx">start</span><span class="p">,</span> <span class="nx">literal</span><span class="p">.</span><span class="nx">length</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Peek at the end of a given string to see if it matches a sequence.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ends = </span><span class="nf">(string, literal, back) -></span>
|
||||
<span class="nv">len = </span><span class="nx">literal</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nx">literal</span> <span class="o">is</span> <span class="nx">string</span><span class="p">.</span><span class="nx">substr</span> <span class="nx">string</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="nx">len</span> <span class="o">-</span> <span class="p">(</span><span class="nx">back</span> <span class="o">or</span> <span class="mi">0</span><span class="p">),</span> <span class="nx">len</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Trim out all falsy values from an array.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.compact = </span><span class="p">(</span><span class="nx">array</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">item</span> <span class="k">for</span> <span class="nx">item</span> <span class="k">in</span> <span class="nx">array</span> <span class="k">when</span> <span class="nx">item</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Count the number of occurrences of a string in a string.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.count = </span><span class="p">(</span><span class="nx">string</span><span class="p">,</span> <span class="nx">substr</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">literal</span> <span class="o">is</span> <span class="nx">string</span><span class="p">.</span><span class="nx">substr</span> <span class="nx">string</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="nx">len</span> <span class="o">-</span> <span class="p">(</span><span class="nx">back</span> <span class="o">or</span> <span class="mi">0</span><span class="p">),</span> <span class="nx">len</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Trim out all falsy values from an array.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.compact = </span><span class="nf">(array) -></span>
|
||||
<span class="nx">item</span> <span class="k">for</span> <span class="nx">item</span> <span class="k">in</span> <span class="nx">array</span> <span class="k">when</span> <span class="nx">item</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Count the number of occurrences of a string in a string.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.count = </span><span class="nf">(string, substr) -></span>
|
||||
<span class="nv">num = pos = </span><span class="mi">0</span>
|
||||
<span class="k">return</span> <span class="mi">1</span><span class="o">/</span><span class="mi">0</span> <span class="nx">unless</span> <span class="nx">substr</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="k">return</span> <span class="mi">1</span><span class="o">/</span><span class="mi">0</span> <span class="k">unless</span> <span class="nx">substr</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nx">num</span><span class="o">++</span> <span class="k">while</span> <span class="nv">pos = </span><span class="mi">1</span> <span class="o">+</span> <span class="nx">string</span><span class="p">.</span><span class="nx">indexOf</span> <span class="nx">substr</span><span class="p">,</span> <span class="nx">pos</span>
|
||||
<span class="nx">num</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Merge objects, returning a fresh copy with attributes from both sides.
|
||||
Used every time <code>Base#compile</code> is called, to allow properties in the
|
||||
options hash to propagate down the tree without polluting other branches.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.merge = </span><span class="p">(</span><span class="nx">options</span><span class="p">,</span> <span class="nx">overrides</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">extend</span> <span class="p">(</span><span class="nx">extend</span> <span class="p">{},</span> <span class="nx">options</span><span class="p">),</span> <span class="nx">overrides</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Extend a source object with the properties of another object (shallow copy).</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">extend = exports.extend = </span><span class="p">(</span><span class="nx">object</span><span class="p">,</span> <span class="nx">properties</span><span class="p">)</span> <span class="o">-></span>
|
||||
options hash to propagate down the tree without polluting other branches.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.merge = </span><span class="nf">(options, overrides) -></span>
|
||||
<span class="nx">extend</span> <span class="p">(</span><span class="nx">extend</span> <span class="p">{},</span> <span class="nx">options</span><span class="p">),</span> <span class="nx">overrides</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Extend a source object with the properties of another object (shallow copy).</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">extend = exports.extend = </span><span class="nf">(object, properties) -></span>
|
||||
<span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">properties</span>
|
||||
<span class="nx">object</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">val</span>
|
||||
<span class="nx">object</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>Return a flattened version of an array.
|
||||
Handy for getting a list of <code>children</code> from the nodes.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.flatten = flatten = </span><span class="p">(</span><span class="nx">array</span><span class="p">)</span> <span class="o">-></span>
|
||||
Handy for getting a list of <code>children</code> from the nodes.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.flatten = flatten = </span><span class="nf">(array) -></span>
|
||||
<span class="nv">flattened = </span><span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="nx">element</span> <span class="k">in</span> <span class="nx">array</span>
|
||||
<span class="k">if</span> <span class="nx">element</span> <span class="k">instanceof</span> <span class="nb">Array</span>
|
||||
@@ -23,9 +23,11 @@ Handy for getting a list of <code>children</code> from the nodes.</p>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">flattened</span><span class="p">.</span><span class="nx">push</span> <span class="nx">element</span>
|
||||
<span class="nx">flattened</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Delete a key from an object, returning the value. Useful when a node is
|
||||
looking for a particular method in an options hash.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.del = </span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">key</span><span class="p">)</span> <span class="o">-></span>
|
||||
looking for a particular method in an options hash.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.del = </span><span class="nf">(obj, key) -></span>
|
||||
<span class="nv">val = </span> <span class="nx">obj</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span>
|
||||
<span class="k">delete</span> <span class="nx">obj</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span>
|
||||
<span class="nx">val</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Gets the last item of an array(-like) object.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.last = </span><span class="p">(</span><span class="nx">array</span><span class="p">,</span> <span class="nx">back</span><span class="p">)</span> <span class="o">-></span> <span class="nx">array</span><span class="p">[</span><span class="nx">array</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="p">(</span><span class="nx">back</span> <span class="o">or</span> <span class="mi">0</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nx">val</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Gets the last item of an array(-like) object.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.last = </span><span class="nf">(array, back) -></span> <span class="nx">array</span><span class="p">[</span><span class="nx">array</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="p">(</span><span class="nx">back</span> <span class="o">or</span> <span class="mi">0</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Typical Array::some</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.some = </span><span class="nb">Array</span><span class="o">::</span><span class="nx">some</span> <span class="o">?</span> <span class="nf">(fn) -></span>
|
||||
<span class="k">return</span> <span class="kc">true</span> <span class="k">for</span> <span class="nx">e</span> <span class="k">in</span> <span class="k">this</span> <span class="k">when</span> <span class="nx">fn</span> <span class="nx">e</span>
|
||||
<span class="kc">false</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -1,3 +1,3 @@
|
||||
<!DOCTYPE html> <html> <head> <title>index.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> index.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> <p>Loader for CoffeeScript as a Node.js library.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">exports</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">val</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">require</span> <span class="s1">'./coffee-script'</span>
|
||||
<!DOCTYPE html> <html> <head> <title>index.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> index.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> <p>Loader for CoffeeScript as a Node.js library.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">exports</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">val</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">require</span> <span class="s">'./coffee-script'</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -6,74 +6,80 @@ options = parser.parse process.argv
|
||||
</code></pre>
|
||||
|
||||
<p>The first non-option is considered to be the start of the file (and file
|
||||
option) list, and all subsequent arguments are left unparsed.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.OptionParser = </span><span class="nx">class</span> <span class="nx">OptionParser</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>Initialize with a list of valid options, in the form:</p>
|
||||
option) list, and all subsequent arguments are left unparsed.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.OptionParser = </span><span class="k">class</span> <span class="nx">OptionParser</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>Initialize with a list of valid options, in the form:</p>
|
||||
|
||||
<pre><code>[short-flag, long-flag, description]
|
||||
</code></pre>
|
||||
|
||||
<p>Along with an an optional banner for the usage help.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">rules</span><span class="p">,</span> <span class="nx">@banner</span><span class="p">)</span> <span class="o">-></span>
|
||||
<p>Along with an an optional banner for the usage help.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">constructor: </span><span class="nf">(rules, @banner) -></span>
|
||||
<span class="vi">@rules = </span><span class="nx">buildRules</span> <span class="nx">rules</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Parse the list of arguments, populating an <code>options</code> object with all of the
|
||||
specified options, and return it. <code>options.arguments</code> will be an array
|
||||
containing the remaining non-option arguments. <code>options.literals</code> will be
|
||||
an array of options that are meant to be passed through directly to the
|
||||
executing script. This is a simpler API than many option parsers that allow
|
||||
you to attach callback actions for every flag. Instead, you're responsible
|
||||
for interpreting the options object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">parse</span><span class="o">:</span> <span class="p">(</span><span class="nx">args</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">options = </span><span class="nx">arguments</span><span class="o">:</span> <span class="p">[],</span> <span class="nx">literals</span><span class="o">:</span> <span class="p">[]</span>
|
||||
specified options, and return it. Options after the first non-option
|
||||
argument are treated as arguments. <code>options.arguments</code> will be an array
|
||||
containing the remaining arguments. This is a simpler API than many option
|
||||
parsers that allow you to attach callback actions for every flag. Instead,
|
||||
you're responsible for interpreting the options object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">parse: </span><span class="nf">(args) -></span>
|
||||
<span class="nv">options = arguments: </span><span class="p">[]</span>
|
||||
<span class="nv">skippingArgument = </span><span class="kc">no</span>
|
||||
<span class="nv">originalArgs = </span><span class="nx">args</span>
|
||||
<span class="nv">args = </span><span class="nx">normalizeArguments</span> <span class="nx">args</span>
|
||||
<span class="k">for</span> <span class="nx">arg</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">args</span>
|
||||
<span class="k">if</span> <span class="nx">arg</span> <span class="o">is</span> <span class="s1">'--'</span>
|
||||
<span class="nv">pos = </span><span class="nx">originalArgs</span><span class="p">.</span><span class="nx">indexOf</span> <span class="s1">'--'</span>
|
||||
<span class="nv">options.arguments = </span><span class="p">[</span><span class="nx">originalArgs</span><span class="p">[</span><span class="mi">1</span> <span class="o">+</span> <span class="nx">pos</span><span class="p">]]</span>
|
||||
<span class="nv">options.literals = </span><span class="nx">originalArgs</span><span class="p">[(</span><span class="mi">2</span> <span class="o">+</span> <span class="nx">pos</span><span class="p">)..]</span>
|
||||
<span class="k">if</span> <span class="nx">skippingArgument</span>
|
||||
<span class="nv">skippingArgument = </span><span class="kc">no</span>
|
||||
<span class="k">continue</span>
|
||||
<span class="k">if</span> <span class="nx">arg</span> <span class="o">is</span> <span class="s">'--'</span>
|
||||
<span class="nv">pos = </span><span class="nx">originalArgs</span><span class="p">.</span><span class="nx">indexOf</span> <span class="s">'--'</span>
|
||||
<span class="nv">options.arguments = </span><span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">originalArgs</span><span class="p">[(</span><span class="nx">pos</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)..]</span>
|
||||
<span class="k">break</span>
|
||||
<span class="nv">isOption = </span><span class="o">!!</span><span class="p">(</span><span class="nx">arg</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">LONG_FLAG</span><span class="p">)</span> <span class="o">or</span> <span class="nx">arg</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">SHORT_FLAG</span><span class="p">))</span>
|
||||
<span class="nv">matchedRule = </span><span class="kc">no</span>
|
||||
<span class="k">for</span> <span class="nx">rule</span> <span class="k">in</span> <span class="nx">@rules</span>
|
||||
<span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">shortFlag</span> <span class="o">is</span> <span class="nx">arg</span> <span class="o">or</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">longFlag</span> <span class="o">is</span> <span class="nx">arg</span>
|
||||
<span class="nv">value = </span><span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">hasArgument</span> <span class="k">then</span> <span class="nx">args</span><span class="p">[</span><span class="nx">i</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">]</span> <span class="k">else</span> <span class="kc">true</span>
|
||||
<span class="nx">options</span><span class="p">[</span><span class="nx">rule</span><span class="p">.</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">isList</span> <span class="k">then</span> <span class="p">(</span><span class="nx">options</span><span class="p">[</span><span class="nx">rule</span><span class="p">.</span><span class="nx">name</span><span class="p">]</span> <span class="o">or</span> <span class="p">[]).</span><span class="nx">concat</span> <span class="nx">value</span> <span class="k">else</span> <span class="nx">value</span>
|
||||
<span class="nv">matchedRule = </span><span class="kc">yes</span>
|
||||
<span class="k">break</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"unrecognized option: #{arg}"</span> <span class="k">if</span> <span class="nx">isOption</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">matchedRule</span>
|
||||
<span class="k">if</span> <span class="o">not</span> <span class="nx">isOption</span>
|
||||
<span class="nv">options.arguments = </span><span class="nx">originalArgs</span><span class="p">[(</span><span class="nx">originalArgs</span><span class="p">.</span><span class="nx">indexOf</span> <span class="nx">arg</span><span class="p">)..]</span>
|
||||
<span class="k">break</span>
|
||||
<span class="nx">options</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Return the help text for this <strong>OptionParser</strong>, listing and describing all
|
||||
of the valid options, for <code>--help</code> and such.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">help</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nv">isOption = </span><span class="o">!!</span><span class="p">(</span><span class="nx">arg</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">LONG_FLAG</span><span class="p">)</span> <span class="o">or</span> <span class="nx">arg</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">SHORT_FLAG</span><span class="p">))</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>the CS option parser is a little odd; options after the first
|
||||
non-option argument are treated as non-option arguments themselves</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">seenNonOptionArg = </span><span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">0</span>
|
||||
<span class="k">unless</span> <span class="nx">seenNonOptionArg</span>
|
||||
<span class="nv">matchedRule = </span><span class="kc">no</span>
|
||||
<span class="k">for</span> <span class="nx">rule</span> <span class="k">in</span> <span class="nx">@rules</span>
|
||||
<span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">shortFlag</span> <span class="o">is</span> <span class="nx">arg</span> <span class="o">or</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">longFlag</span> <span class="o">is</span> <span class="nx">arg</span>
|
||||
<span class="nv">value = </span><span class="kc">true</span>
|
||||
<span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">hasArgument</span>
|
||||
<span class="nv">skippingArgument = </span><span class="kc">yes</span>
|
||||
<span class="nv">value = </span><span class="nx">args</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nx">options</span><span class="p">[</span><span class="nx">rule</span><span class="p">.</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">isList</span> <span class="k">then</span> <span class="p">(</span><span class="nx">options</span><span class="p">[</span><span class="nx">rule</span><span class="p">.</span><span class="nx">name</span><span class="p">]</span> <span class="o">or</span> <span class="p">[]).</span><span class="nx">concat</span> <span class="nx">value</span> <span class="k">else</span> <span class="nx">value</span>
|
||||
<span class="nv">matchedRule = </span><span class="kc">yes</span>
|
||||
<span class="k">break</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">"unrecognized option: </span><span class="si">#{</span><span class="nx">arg</span><span class="si">}</span><span class="s">"</span> <span class="k">if</span> <span class="nx">isOption</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">matchedRule</span>
|
||||
<span class="k">if</span> <span class="nx">seenNonOptionArg</span> <span class="o">or</span> <span class="o">not</span> <span class="nx">isOption</span>
|
||||
<span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span><span class="p">.</span><span class="nx">push</span> <span class="nx">arg</span>
|
||||
<span class="nx">options</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Return the help text for this <strong>OptionParser</strong>, listing and describing all
|
||||
of the valid options, for <code>--help</code> and such.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">help: </span><span class="nf">-></span>
|
||||
<span class="nv">lines = </span><span class="p">[]</span>
|
||||
<span class="nx">lines</span><span class="p">.</span><span class="nx">unshift</span> <span class="s2">"#{@banner}\n"</span> <span class="k">if</span> <span class="nx">@banner</span>
|
||||
<span class="nx">lines</span><span class="p">.</span><span class="nx">unshift</span> <span class="s">"</span><span class="si">#{</span><span class="nx">@banner</span><span class="si">}</span><span class="s">\n"</span> <span class="k">if</span> <span class="nx">@banner</span>
|
||||
<span class="k">for</span> <span class="nx">rule</span> <span class="k">in</span> <span class="nx">@rules</span>
|
||||
<span class="nv">spaces = </span><span class="mi">15</span> <span class="o">-</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">longFlag</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">spaces = </span><span class="k">if</span> <span class="nx">spaces</span> <span class="o">></span> <span class="mi">0</span> <span class="k">then</span> <span class="nb">Array</span><span class="p">(</span><span class="nx">spaces</span> <span class="o">+</span> <span class="mi">1</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s1">' '</span><span class="p">)</span> <span class="k">else</span> <span class="s1">''</span>
|
||||
<span class="nv">letPart = </span><span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">shortFlag</span> <span class="k">then</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">shortFlag</span> <span class="o">+</span> <span class="s1">', '</span> <span class="k">else</span> <span class="s1">' '</span>
|
||||
<span class="nx">lines</span><span class="p">.</span><span class="nx">push</span> <span class="s1">' '</span> <span class="o">+</span> <span class="nx">letPart</span> <span class="o">+</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">longFlag</span> <span class="o">+</span> <span class="nx">spaces</span> <span class="o">+</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">description</span>
|
||||
<span class="s2">"\n#{ lines.join('\n') }\n"</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <h2>Helpers</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Regex matchers for option flags.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">LONG_FLAG = </span><span class="sr">/^(--\w[\w\-]+)/</span>
|
||||
<span class="nv">SHORT_FLAG = </span><span class="sr">/^(-\w)/</span>
|
||||
<span class="nv">spaces = </span><span class="k">if</span> <span class="nx">spaces</span> <span class="o">></span> <span class="mi">0</span> <span class="k">then</span> <span class="nb">Array</span><span class="p">(</span><span class="nx">spaces</span> <span class="o">+</span> <span class="mi">1</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s">' '</span><span class="p">)</span> <span class="k">else</span> <span class="s">''</span>
|
||||
<span class="nv">letPart = </span><span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">shortFlag</span> <span class="k">then</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">shortFlag</span> <span class="o">+</span> <span class="s">', '</span> <span class="k">else</span> <span class="s">' '</span>
|
||||
<span class="nx">lines</span><span class="p">.</span><span class="nx">push</span> <span class="s">' '</span> <span class="o">+</span> <span class="nx">letPart</span> <span class="o">+</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">longFlag</span> <span class="o">+</span> <span class="nx">spaces</span> <span class="o">+</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">description</span>
|
||||
<span class="s">"\n</span><span class="si">#{</span> <span class="nx">lines</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s">'\n'</span><span class="p">)</span> <span class="si">}</span><span class="s">\n"</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <h2>Helpers</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Regex matchers for option flags.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">LONG_FLAG = </span><span class="sr">/^(--\w[\w\-]*)/</span>
|
||||
<span class="nv">SHORT_FLAG = </span><span class="sr">/^(-\w)$/</span>
|
||||
<span class="nv">MULTI_FLAG = </span><span class="sr">/^-(\w{2,})/</span>
|
||||
<span class="nv">OPTIONAL = </span><span class="sr">/\[(\w+(\*?))\]/</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Build and return the list of option rules. If the optional <em>short-flag</em> is
|
||||
unspecified, leave it out by padding with <code>null</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">buildRules = </span><span class="p">(</span><span class="nx">rules</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">OPTIONAL = </span><span class="sr">/\[(\w+(\*?))\]/</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>Build and return the list of option rules. If the optional <em>short-flag</em> is
|
||||
unspecified, leave it out by padding with <code>null</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">buildRules = </span><span class="nf">(rules) -></span>
|
||||
<span class="k">for</span> <span class="nx">tuple</span> <span class="k">in</span> <span class="nx">rules</span>
|
||||
<span class="nx">tuple</span><span class="p">.</span><span class="nx">unshift</span> <span class="kc">null</span> <span class="k">if</span> <span class="nx">tuple</span><span class="p">.</span><span class="nx">length</span> <span class="o"><</span> <span class="mi">3</span>
|
||||
<span class="nx">buildRule</span> <span class="nx">tuple</span><span class="p">...</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>Build a rule from a <code>-o</code> short flag, a <code>--output [DIR]</code> long flag, and the
|
||||
description of what the option does.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">buildRule = </span><span class="p">(</span><span class="nx">shortFlag</span><span class="p">,</span> <span class="nx">longFlag</span><span class="p">,</span> <span class="nx">description</span><span class="p">,</span> <span class="nv">options = </span><span class="p">{})</span> <span class="o">-></span>
|
||||
<span class="nx">buildRule</span> <span class="nx">tuple</span><span class="p">...</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Build a rule from a <code>-o</code> short flag, a <code>--output [DIR]</code> long flag, and the
|
||||
description of what the option does.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">buildRule = </span><span class="nf">(shortFlag, longFlag, description, options = {}) -></span>
|
||||
<span class="nv">match = </span><span class="nx">longFlag</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">OPTIONAL</span><span class="p">)</span>
|
||||
<span class="nv">longFlag = </span><span class="nx">longFlag</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">LONG_FLAG</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="p">{</span>
|
||||
<span class="nx">name</span><span class="o">:</span> <span class="nx">longFlag</span><span class="p">.</span><span class="nx">substr</span> <span class="mi">2</span>
|
||||
<span class="nx">shortFlag</span><span class="o">:</span> <span class="nx">shortFlag</span>
|
||||
<span class="nx">longFlag</span><span class="o">:</span> <span class="nx">longFlag</span>
|
||||
<span class="nx">description</span><span class="o">:</span> <span class="nx">description</span>
|
||||
<span class="nx">hasArgument</span><span class="o">:</span> <span class="o">!!</span><span class="p">(</span><span class="nx">match</span> <span class="o">and</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
|
||||
<span class="nx">isList</span><span class="o">:</span> <span class="o">!!</span><span class="p">(</span><span class="nx">match</span> <span class="o">and</span> <span class="nx">match</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Normalize arguments by expanding merged flags into multiple flags. This allows
|
||||
you to have <code>-wl</code> be the same as <code>--watch --lint</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">normalizeArguments = </span><span class="p">(</span><span class="nx">args</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">args = </span><span class="nx">args</span><span class="p">.</span><span class="nx">slice</span> <span class="mi">0</span>
|
||||
<span class="nv">name: </span> <span class="nx">longFlag</span><span class="p">.</span><span class="nx">substr</span> <span class="mi">2</span>
|
||||
<span class="nv">shortFlag: </span> <span class="nx">shortFlag</span>
|
||||
<span class="nv">longFlag: </span> <span class="nx">longFlag</span>
|
||||
<span class="nv">description: </span> <span class="nx">description</span>
|
||||
<span class="nv">hasArgument: </span> <span class="o">!!</span><span class="p">(</span><span class="nx">match</span> <span class="o">and</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
|
||||
<span class="nv">isList: </span> <span class="o">!!</span><span class="p">(</span><span class="nx">match</span> <span class="o">and</span> <span class="nx">match</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Normalize arguments by expanding merged flags into multiple flags. This allows
|
||||
you to have <code>-wl</code> be the same as <code>--watch --lint</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">normalizeArguments = </span><span class="nf">(args) -></span>
|
||||
<span class="nv">args = </span><span class="nx">args</span><span class="p">[..]</span>
|
||||
<span class="nv">result = </span><span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="nx">arg</span> <span class="k">in</span> <span class="nx">args</span>
|
||||
<span class="k">if</span> <span class="nv">match = </span><span class="nx">arg</span><span class="p">.</span><span class="nx">match</span> <span class="nx">MULTI_FLAG</span>
|
||||
<span class="nx">result</span><span class="p">.</span><span class="nx">push</span> <span class="s1">'-'</span> <span class="o">+</span> <span class="nx">l</span> <span class="k">for</span> <span class="nx">l</span> <span class="k">in</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">split</span> <span class="s1">''</span>
|
||||
<span class="nx">result</span><span class="p">.</span><span class="nx">push</span> <span class="s">'-'</span> <span class="o">+</span> <span class="nx">l</span> <span class="k">for</span> <span class="nx">l</span> <span class="k">in</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">split</span> <span class="s">''</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">result</span><span class="p">.</span><span class="nx">push</span> <span class="nx">arg</span>
|
||||
<span class="nx">result</span>
|
||||
|
||||
@@ -3,79 +3,138 @@ and evaluates it. Good for simple tests, or poking around the <strong>Node.js</s
|
||||
Using it looks like this:</p>
|
||||
|
||||
<pre><code>coffee> console.log "#{num} bottles of beer" for num in [99..1]
|
||||
</code></pre> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>Require the <strong>coffee-script</strong> module to get access to the compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s1">'./coffee-script'</span>
|
||||
<span class="nv">readline = </span><span class="nx">require</span> <span class="s1">'readline'</span>
|
||||
<span class="p">{</span><span class="nx">inspect</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'util'</span>
|
||||
<span class="p">{</span><span class="nx">Script</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'vm'</span>
|
||||
<span class="nv">Module = </span><span class="nx">require</span> <span class="s1">'module'</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>REPL Setup</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Config</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">REPL_PROMPT = </span><span class="s1">'coffee> '</span>
|
||||
<span class="nv">REPL_PROMPT_CONTINUATION = </span><span class="s1">'......> '</span>
|
||||
</code></pre> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>Start by opening up <code>stdin</code> and <code>stdout</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">stdin = </span><span class="nx">process</span><span class="p">.</span><span class="nx">openStdin</span><span class="p">()</span>
|
||||
<span class="nv">stdout = </span><span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Require the <strong>coffee-script</strong> module to get access to the compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s">'./coffee-script'</span>
|
||||
<span class="nv">readline = </span><span class="nx">require</span> <span class="s">'readline'</span>
|
||||
<span class="p">{</span><span class="nx">inspect</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">'util'</span>
|
||||
<span class="p">{</span><span class="nx">Script</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">'vm'</span>
|
||||
<span class="nv">Module = </span><span class="nx">require</span> <span class="s">'module'</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>REPL Setup</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Config</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">REPL_PROMPT = </span><span class="s">'coffee> '</span>
|
||||
<span class="nv">REPL_PROMPT_MULTILINE = </span><span class="s">'------> '</span>
|
||||
<span class="nv">REPL_PROMPT_CONTINUATION = </span><span class="s">'......> '</span>
|
||||
<span class="nv">enableColours = </span><span class="kc">no</span>
|
||||
<span class="nx">unless</span> <span class="nx">process</span><span class="p">.</span><span class="nx">platform</span> <span class="o">is</span> <span class="s1">'win32'</span>
|
||||
<span class="nv">enableColours = </span><span class="o">not</span> <span class="nx">process</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">NODE_DISABLE_COLORS</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Start by opening up <code>stdin</code> and <code>stdout</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">stdin = </span><span class="nx">process</span><span class="p">.</span><span class="nx">openStdin</span><span class="p">()</span>
|
||||
<span class="nv">stdout = </span><span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Log an error.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">error = </span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="p">(</span><span class="nx">err</span><span class="p">.</span><span class="nx">stack</span> <span class="o">or</span> <span class="nx">err</span><span class="p">.</span><span class="nx">toString</span><span class="p">())</span> <span class="o">+</span> <span class="s1">'\n'</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>The current backlog of multi-line code.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">backlog = </span><span class="s1">''</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>The main REPL function. <strong>run</strong> is called every time a line of code is entered.
|
||||
<span class="k">unless</span> <span class="nx">process</span><span class="p">.</span><span class="nx">platform</span> <span class="o">is</span> <span class="s">'win32'</span>
|
||||
<span class="nv">enableColours = </span><span class="o">not</span> <span class="nx">process</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">NODE_DISABLE_COLORS</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Log an error.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">error = </span><span class="nf">(err) -></span>
|
||||
<span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="p">(</span><span class="nx">err</span><span class="p">.</span><span class="nx">stack</span> <span class="o">or</span> <span class="nx">err</span><span class="p">.</span><span class="nx">toString</span><span class="p">())</span> <span class="o">+</span> <span class="s">'\n'</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <h1>Autocompletion</h1> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>Regexes to match complete-able bits of text.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">ACCESSOR = </span><span class="sr">/\s*([\w\.]+)(?:\.(\w*))$/</span>
|
||||
<span class="nv">SIMPLEVAR = </span><span class="sr">/(\w+)$/i</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Returns a list of completions, and the completed text.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">autocomplete = </span><span class="nf">(text) -></span>
|
||||
<span class="nx">completeAttribute</span><span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="o">or</span> <span class="nx">completeVariable</span><span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="o">or</span> <span class="p">[[],</span> <span class="nx">text</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Attempt to autocomplete a chained dotted attribute: <code>one.two.three</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">completeAttribute = </span><span class="nf">(text) -></span>
|
||||
<span class="k">if</span> <span class="nv">match = </span><span class="nx">text</span><span class="p">.</span><span class="nx">match</span> <span class="nx">ACCESSOR</span>
|
||||
<span class="p">[</span><span class="nx">all</span><span class="p">,</span> <span class="nx">obj</span><span class="p">,</span> <span class="nx">prefix</span><span class="p">]</span> <span class="o">=</span> <span class="nx">match</span>
|
||||
<span class="k">try</span> <span class="nv">obj = </span><span class="nx">Script</span><span class="p">.</span><span class="nx">runInThisContext</span> <span class="nx">obj</span>
|
||||
<span class="k">catch</span> <span class="nx">e</span>
|
||||
<span class="k">return</span>
|
||||
<span class="k">return</span> <span class="k">unless</span> <span class="nx">obj</span><span class="o">?</span>
|
||||
<span class="nv">obj = </span><span class="nb">Object</span> <span class="nx">obj</span>
|
||||
<span class="nv">candidates = </span><span class="nb">Object</span><span class="p">.</span><span class="nx">getOwnPropertyNames</span> <span class="nx">obj</span>
|
||||
<span class="k">while</span> <span class="nv">obj = </span><span class="nb">Object</span><span class="p">.</span><span class="nx">getPrototypeOf</span> <span class="nx">obj</span>
|
||||
<span class="k">for</span> <span class="nx">key</span> <span class="k">in</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">getOwnPropertyNames</span> <span class="nx">obj</span> <span class="k">when</span> <span class="nx">key</span> <span class="o">not</span> <span class="k">in</span> <span class="nx">candidates</span>
|
||||
<span class="nx">candidates</span><span class="p">.</span><span class="nx">push</span> <span class="nx">key</span>
|
||||
<span class="nv">completions = </span><span class="nx">getCompletions</span> <span class="nx">prefix</span><span class="p">,</span> <span class="nx">candidates</span>
|
||||
<span class="p">[</span><span class="nx">completions</span><span class="p">,</span> <span class="nx">prefix</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Attempt to autocomplete an in-scope free variable: <code>one</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">completeVariable = </span><span class="nf">(text) -></span>
|
||||
<span class="nv">free = </span><span class="nx">text</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">SIMPLEVAR</span><span class="p">)</span><span class="o">?</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nv">free = </span><span class="s">""</span> <span class="k">if</span> <span class="nx">text</span> <span class="o">is</span> <span class="s">""</span>
|
||||
<span class="k">if</span> <span class="nx">free</span><span class="o">?</span>
|
||||
<span class="nv">vars = </span><span class="nx">Script</span><span class="p">.</span><span class="nx">runInThisContext</span> <span class="s">'Object.getOwnPropertyNames(Object(this))'</span>
|
||||
<span class="nv">keywords = </span><span class="p">(</span><span class="nx">r</span> <span class="k">for</span> <span class="nx">r</span> <span class="k">in</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">RESERVED</span> <span class="k">when</span> <span class="nx">r</span><span class="p">[..</span><span class="mi">1</span><span class="p">]</span> <span class="o">isnt</span> <span class="s">'__'</span><span class="p">)</span>
|
||||
<span class="nv">candidates = </span><span class="nx">vars</span>
|
||||
<span class="k">for</span> <span class="nx">key</span> <span class="k">in</span> <span class="nx">keywords</span> <span class="k">when</span> <span class="nx">key</span> <span class="o">not</span> <span class="k">in</span> <span class="nx">candidates</span>
|
||||
<span class="nx">candidates</span><span class="p">.</span><span class="nx">push</span> <span class="nx">key</span>
|
||||
<span class="nv">completions = </span><span class="nx">getCompletions</span> <span class="nx">free</span><span class="p">,</span> <span class="nx">candidates</span>
|
||||
<span class="p">[</span><span class="nx">completions</span><span class="p">,</span> <span class="nx">free</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Return elements of candidates for which <code>prefix</code> is a prefix.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">getCompletions = </span><span class="nf">(prefix, candidates) -></span>
|
||||
<span class="nx">el</span> <span class="k">for</span> <span class="nx">el</span> <span class="k">in</span> <span class="nx">candidates</span> <span class="k">when</span> <span class="mi">0</span> <span class="o">is</span> <span class="nx">el</span><span class="p">.</span><span class="nx">indexOf</span> <span class="nx">prefix</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Make sure that uncaught exceptions don't kill the REPL.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">process</span><span class="p">.</span><span class="nx">on</span> <span class="s">'uncaughtException'</span><span class="p">,</span> <span class="nx">error</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>The current backlog of multi-line code.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">backlog = </span><span class="s">''</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>The main REPL function. <strong>run</strong> is called every time a line of code is entered.
|
||||
Attempt to evaluate the command. If there's an exception, print it out instead
|
||||
of exiting.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">run = </span><span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-></span>
|
||||
of exiting.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">run = </span><span class="nf">(buffer) -></span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>remove single-line comments</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">buffer = </span><span class="nx">buffer</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/(^|[\r\n]+)(\s*)##?(?:[^#\r\n][^\r\n]*|)($|[\r\n])/</span><span class="p">,</span> <span class="s">"$1$2$3"</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <p>remove trailing newlines</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">buffer = </span><span class="nx">buffer</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/[\r\n]+$/</span><span class="p">,</span> <span class="s">""</span>
|
||||
<span class="k">if</span> <span class="nx">multilineMode</span>
|
||||
<span class="nx">backlog</span> <span class="o">+=</span> <span class="s">"</span><span class="si">#{</span><span class="nx">buffer</span><span class="si">}</span><span class="s">\n"</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="nx">REPL_PROMPT_CONTINUATION</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">()</span>
|
||||
<span class="k">return</span>
|
||||
<span class="k">if</span> <span class="o">!</span><span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">().</span><span class="nx">trim</span><span class="p">()</span> <span class="o">and</span> <span class="o">!</span><span class="nx">backlog</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">()</span>
|
||||
<span class="k">return</span>
|
||||
<span class="nv">code = </span><span class="nx">backlog</span> <span class="o">+=</span> <span class="nx">buffer</span>
|
||||
<span class="k">if</span> <span class="nx">code</span><span class="p">[</span><span class="nx">code</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'\\'</span>
|
||||
<span class="nv">backlog = </span><span class="s2">"#{backlog[...-1]}\n"</span>
|
||||
<span class="k">if</span> <span class="nx">code</span><span class="p">[</span><span class="nx">code</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">is</span> <span class="s">'\\'</span>
|
||||
<span class="nv">backlog = </span><span class="s">"</span><span class="si">#{</span><span class="nx">backlog</span><span class="p">[...</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="si">}</span><span class="s">\n"</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="nx">REPL_PROMPT_CONTINUATION</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">()</span>
|
||||
<span class="k">return</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="nx">REPL_PROMPT</span>
|
||||
<span class="nv">backlog = </span><span class="s1">''</span>
|
||||
<span class="nv">backlog = </span><span class="s">''</span>
|
||||
<span class="k">try</span>
|
||||
<span class="nv">_ = </span><span class="nx">global</span><span class="p">.</span><span class="nx">_</span>
|
||||
<span class="nv">returnValue = </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nb">eval</span> <span class="s2">"_=(#{code}\n)"</span><span class="p">,</span> <span class="p">{</span>
|
||||
<span class="nx">filename</span><span class="o">:</span> <span class="s1">'repl'</span>
|
||||
<span class="nx">modulename</span><span class="o">:</span> <span class="s1">'repl'</span>
|
||||
<span class="nv">returnValue = </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nb">eval</span> <span class="s">"_=(</span><span class="si">#{</span><span class="nx">code</span><span class="si">}</span><span class="s">\n)"</span><span class="p">,</span> <span class="p">{</span>
|
||||
<span class="nv">filename: </span><span class="s">'repl'</span>
|
||||
<span class="nv">modulename: </span><span class="s">'repl'</span>
|
||||
<span class="p">}</span>
|
||||
<span class="k">if</span> <span class="nx">returnValue</span> <span class="o">is</span> <span class="kc">undefined</span>
|
||||
<span class="nv">global._ = </span><span class="nx">_</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="nx">inspect</span><span class="p">(</span><span class="nx">returnValue</span><span class="p">,</span> <span class="kc">no</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">enableColours</span><span class="p">)</span> <span class="o">+</span> <span class="s1">'\n'</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">output</span><span class="p">.</span><span class="nx">write</span> <span class="s">"</span><span class="si">#{</span><span class="nx">inspect</span> <span class="nx">returnValue</span><span class="p">,</span> <span class="kc">no</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">enableColours</span><span class="si">}</span><span class="s">\n"</span>
|
||||
<span class="k">catch</span> <span class="nx">err</span>
|
||||
<span class="nx">error</span> <span class="nx">err</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <h1>Autocompletion</h1> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Regexes to match complete-able bits of text.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">ACCESSOR = </span><span class="sr">/\s*([\w\.]+)(?:\.(\w*))$/</span>
|
||||
<span class="nv">SIMPLEVAR = </span><span class="sr">/\s*(\w*)$/i</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Returns a list of completions, and the completed text.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">autocomplete = </span><span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">completeAttribute</span><span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="o">or</span> <span class="nx">completeVariable</span><span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="o">or</span> <span class="p">[[],</span> <span class="nx">text</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Attempt to autocomplete a chained dotted attribute: <code>one.two.three</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">completeAttribute = </span><span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nv">match = </span><span class="nx">text</span><span class="p">.</span><span class="nx">match</span> <span class="nx">ACCESSOR</span>
|
||||
<span class="p">[</span><span class="nx">all</span><span class="p">,</span> <span class="nx">obj</span><span class="p">,</span> <span class="nx">prefix</span><span class="p">]</span> <span class="o">=</span> <span class="nx">match</span>
|
||||
<span class="k">try</span>
|
||||
<span class="nv">val = </span><span class="nx">Script</span><span class="p">.</span><span class="nx">runInThisContext</span> <span class="nx">obj</span>
|
||||
<span class="k">catch</span> <span class="nx">error</span>
|
||||
<span class="k">return</span>
|
||||
<span class="nv">completions = </span><span class="nx">getCompletions</span> <span class="nx">prefix</span><span class="p">,</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">getOwnPropertyNames</span> <span class="nx">val</span>
|
||||
<span class="p">[</span><span class="nx">completions</span><span class="p">,</span> <span class="nx">prefix</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Attempt to autocomplete an in-scope free variable: <code>one</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">completeVariable = </span><span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">free = </span><span class="p">(</span><span class="nx">text</span><span class="p">.</span><span class="nx">match</span> <span class="nx">SIMPLEVAR</span><span class="p">)</span><span class="o">?</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="nx">free</span><span class="o">?</span>
|
||||
<span class="nv">vars = </span><span class="nx">Script</span><span class="p">.</span><span class="nx">runInThisContext</span> <span class="s1">'Object.getOwnPropertyNames(this)'</span>
|
||||
<span class="nv">keywords = </span><span class="p">(</span><span class="nx">r</span> <span class="k">for</span> <span class="nx">r</span> <span class="k">in</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">RESERVED</span> <span class="k">when</span> <span class="nx">r</span><span class="p">[</span><span class="mi">0</span><span class="p">..</span><span class="mi">1</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">'__'</span><span class="p">)</span>
|
||||
<span class="nv">possibilities = </span><span class="nx">vars</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">keywords</span>
|
||||
<span class="nv">completions = </span><span class="nx">getCompletions</span> <span class="nx">free</span><span class="p">,</span> <span class="nx">possibilities</span>
|
||||
<span class="p">[</span><span class="nx">completions</span><span class="p">,</span> <span class="nx">free</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Return elements of candidates for which <code>prefix</code> is a prefix.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">getCompletions = </span><span class="p">(</span><span class="nx">prefix</span><span class="p">,</span> <span class="nx">candidates</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="p">(</span><span class="nx">el</span> <span class="k">for</span> <span class="nx">el</span> <span class="k">in</span> <span class="nx">candidates</span> <span class="k">when</span> <span class="nx">el</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">prefix</span><span class="p">)</span> <span class="o">is</span> <span class="mi">0</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>Make sure that uncaught exceptions don't kill the REPL.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">process</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'uncaughtException'</span><span class="p">,</span> <span class="nx">error</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>Create the REPL by listening to <strong>stdin</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">if</span> <span class="nx">readline</span><span class="p">.</span><span class="nx">createInterface</span><span class="p">.</span><span class="nx">length</span> <span class="o"><</span> <span class="mi">3</span>
|
||||
<span class="nv">repl = </span><span class="nx">readline</span><span class="p">.</span><span class="nx">createInterface</span> <span class="nx">stdin</span><span class="p">,</span> <span class="nx">autocomplete</span>
|
||||
<span class="nx">stdin</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'data'</span><span class="p">,</span> <span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-></span> <span class="nx">repl</span><span class="p">.</span><span class="nx">write</span> <span class="nx">buffer</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">repl = </span><span class="nx">readline</span><span class="p">.</span><span class="nx">createInterface</span> <span class="nx">stdin</span><span class="p">,</span> <span class="nx">stdout</span><span class="p">,</span> <span class="nx">autocomplete</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">()</span>
|
||||
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'attemptClose'</span><span class="p">,</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">backlog</span>
|
||||
<span class="nv">backlog = </span><span class="s1">''</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="s1">'\n'</span>
|
||||
<span class="k">if</span> <span class="nx">stdin</span><span class="p">.</span><span class="nx">readable</span> <span class="o">and</span> <span class="nx">stdin</span><span class="p">.</span><span class="nx">isRaw</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <p>handle piped input</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">pipedInput = </span><span class="s">''</span>
|
||||
<span class="nv">repl =</span>
|
||||
<span class="nv">prompt: </span><span class="nf">-></span> <span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="nx">@_prompt</span>
|
||||
<span class="nv">setPrompt: </span><span class="nf">(p) -></span> <span class="vi">@_prompt = </span><span class="nx">p</span>
|
||||
<span class="nv">input: </span><span class="nx">stdin</span>
|
||||
<span class="nv">output: </span><span class="nx">stdout</span>
|
||||
<span class="kc">on</span><span class="o">:</span> <span class="nf">-></span>
|
||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">on</span> <span class="s">'data'</span><span class="p">,</span> <span class="nf">(chunk) -></span>
|
||||
<span class="nx">pipedInput</span> <span class="o">+=</span> <span class="nx">chunk</span>
|
||||
<span class="k">return</span> <span class="k">unless</span> <span class="sr">/\n/</span><span class="p">.</span><span class="nx">test</span> <span class="nx">pipedInput</span>
|
||||
<span class="nv">lines = </span><span class="nx">pipedInput</span><span class="p">.</span><span class="nx">split</span> <span class="s">"\n"</span>
|
||||
<span class="nv">pipedInput = </span><span class="nx">lines</span><span class="p">[</span><span class="nx">lines</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
|
||||
<span class="k">for</span> <span class="nx">line</span> <span class="k">in</span> <span class="nx">lines</span><span class="p">[...</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="k">when</span> <span class="nx">line</span>
|
||||
<span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="s">"</span><span class="si">#{</span><span class="nx">line</span><span class="si">}</span><span class="s">\n"</span>
|
||||
<span class="nx">run</span> <span class="nx">line</span>
|
||||
<span class="k">return</span>
|
||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">on</span> <span class="s">'end'</span><span class="p">,</span> <span class="nf">-></span>
|
||||
<span class="k">for</span> <span class="nx">line</span> <span class="k">in</span> <span class="nx">pipedInput</span><span class="p">.</span><span class="nx">trim</span><span class="p">().</span><span class="nx">split</span> <span class="s">"\n"</span> <span class="k">when</span> <span class="nx">line</span>
|
||||
<span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="s">"</span><span class="si">#{</span><span class="nx">line</span><span class="si">}</span><span class="s">\n"</span>
|
||||
<span class="nx">run</span> <span class="nx">line</span>
|
||||
<span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="s">'\n'</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">0</span>
|
||||
<span class="k">else</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</a> </div> <p>Create the REPL by listening to <strong>stdin</strong>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">readline</span><span class="p">.</span><span class="nx">createInterface</span><span class="p">.</span><span class="nx">length</span> <span class="o"><</span> <span class="mi">3</span>
|
||||
<span class="nv">repl = </span><span class="nx">readline</span><span class="p">.</span><span class="nx">createInterface</span> <span class="nx">stdin</span><span class="p">,</span> <span class="nx">autocomplete</span>
|
||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">on</span> <span class="s">'data'</span><span class="p">,</span> <span class="nf">(buffer) -></span> <span class="nx">repl</span><span class="p">.</span><span class="nx">write</span> <span class="nx">buffer</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">repl = </span><span class="nx">readline</span><span class="p">.</span><span class="nx">createInterface</span> <span class="nx">stdin</span><span class="p">,</span> <span class="nx">stdout</span><span class="p">,</span> <span class="nx">autocomplete</span>
|
||||
|
||||
<span class="nv">multilineMode = </span><span class="kc">off</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">¶</a> </div> <p>Handle multi-line mode switch</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">repl</span><span class="p">.</span><span class="nx">input</span><span class="p">.</span><span class="nx">on</span> <span class="s">'keypress'</span><span class="p">,</span> <span class="nf">(char, key) -></span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">¶</a> </div> <p>test for Ctrl-v</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">return</span> <span class="k">unless</span> <span class="nx">key</span> <span class="o">and</span> <span class="nx">key</span><span class="p">.</span><span class="nx">ctrl</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">key</span><span class="p">.</span><span class="nx">meta</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">key</span><span class="p">.</span><span class="nx">shift</span> <span class="o">and</span> <span class="nx">key</span><span class="p">.</span><span class="nx">name</span> <span class="o">is</span> <span class="s">'v'</span>
|
||||
<span class="nv">cursorPos = </span><span class="nx">repl</span><span class="p">.</span><span class="nx">cursor</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">output</span><span class="p">.</span><span class="nx">cursorTo</span> <span class="mi">0</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">output</span><span class="p">.</span><span class="nx">clearLine</span> <span class="mi">1</span>
|
||||
<span class="nv">multilineMode = </span><span class="o">not</span> <span class="nx">multilineMode</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">_line</span><span class="p">()</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">multilineMode</span> <span class="o">and</span> <span class="nx">backlog</span>
|
||||
<span class="nv">backlog = </span><span class="s">''</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="p">(</span><span class="nv">newPrompt = </span><span class="k">if</span> <span class="nx">multilineMode</span> <span class="k">then</span> <span class="nx">REPL_PROMPT_MULTILINE</span> <span class="k">else</span> <span class="nx">REPL_PROMPT</span><span class="p">)</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">()</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">output</span><span class="p">.</span><span class="nx">cursorTo</span> <span class="nx">newPrompt</span><span class="p">.</span><span class="nx">length</span> <span class="o">+</span> <span class="p">(</span><span class="nv">repl.cursor = </span><span class="nx">cursorPos</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">¶</a> </div> <p>Handle Ctrl-d press at end of last line in multiline mode</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">repl</span><span class="p">.</span><span class="nx">input</span><span class="p">.</span><span class="nx">on</span> <span class="s">'keypress'</span><span class="p">,</span> <span class="nf">(char, key) -></span>
|
||||
<span class="k">return</span> <span class="k">unless</span> <span class="nx">multilineMode</span> <span class="o">and</span> <span class="nx">repl</span><span class="p">.</span><span class="nx">line</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">¶</a> </div> <p>test for Ctrl-d</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">return</span> <span class="k">unless</span> <span class="nx">key</span> <span class="o">and</span> <span class="nx">key</span><span class="p">.</span><span class="nx">ctrl</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">key</span><span class="p">.</span><span class="nx">meta</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">key</span><span class="p">.</span><span class="nx">shift</span> <span class="o">and</span> <span class="nx">key</span><span class="p">.</span><span class="nx">name</span> <span class="o">is</span> <span class="s">'d'</span>
|
||||
<span class="nv">multilineMode = </span><span class="kc">off</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">_line</span><span class="p">()</span>
|
||||
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">on</span> <span class="s">'attemptClose'</span><span class="p">,</span> <span class="nf">-></span>
|
||||
<span class="k">if</span> <span class="nx">multilineMode</span>
|
||||
<span class="nv">multilineMode = </span><span class="kc">off</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">output</span><span class="p">.</span><span class="nx">cursorTo</span> <span class="mi">0</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">output</span><span class="p">.</span><span class="nx">clearLine</span> <span class="mi">1</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">_onLine</span> <span class="nx">repl</span><span class="p">.</span><span class="nx">line</span>
|
||||
<span class="k">return</span>
|
||||
<span class="k">if</span> <span class="nx">backlog</span> <span class="o">or</span> <span class="nx">repl</span><span class="p">.</span><span class="nx">line</span>
|
||||
<span class="nv">backlog = </span><span class="s">''</span>
|
||||
<span class="nv">repl.historyIndex = </span><span class="o">-</span><span class="mi">1</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="nx">REPL_PROMPT</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">()</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">output</span><span class="p">.</span><span class="nx">write</span> <span class="s">'\n(^C again to quit)'</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">_line</span> <span class="p">(</span><span class="nv">repl.line = </span><span class="s">''</span><span class="p">)</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">close</span><span class="p">()</span>
|
||||
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'close'</span><span class="p">,</span> <span class="o">-></span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="s1">'\n'</span>
|
||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">destroy</span><span class="p">()</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">on</span> <span class="s">'close'</span><span class="p">,</span> <span class="nf">-></span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">output</span><span class="p">.</span><span class="nx">write</span> <span class="s">'\n'</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">input</span><span class="p">.</span><span class="nx">destroy</span><span class="p">()</span>
|
||||
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'line'</span><span class="p">,</span> <span class="nx">run</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">on</span> <span class="s">'line'</span><span class="p">,</span> <span class="nx">run</span>
|
||||
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="nx">REPL_PROMPT</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">()</span>
|
||||
|
||||
@@ -4,12 +4,12 @@ the resulting parse table. Instead of making the parser handle it all, we take
|
||||
a series of passes over the token stream, using this <strong>Rewriter</strong> to convert
|
||||
shorthand into the unambiguous long form, add implicit indentation and
|
||||
parentheses, and generally clean things up.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>The <strong>Rewriter</strong> class is used by the <a href="lexer.html">Lexer</a>, directly against
|
||||
its internal array of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">class</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">Rewriter</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Helpful snippet for debugging:
|
||||
its internal array of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">class</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">Rewriter</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Helpful snippet for debugging:
|
||||
console.log (t[0] + '/' + t[1] for t in @tokens).join ' '</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Rewrite the token stream in multiple passes, one logical filter at
|
||||
a time. This could certainly be changed into a single pass through the
|
||||
stream, with a big ol' efficient switch, but it's much nicer to work with
|
||||
like this. The order of these passes matters -- indentation must be
|
||||
corrected before implicit parentheses can be wrapped around blocks of code.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">rewrite</span><span class="o">:</span> <span class="p">(</span><span class="nx">@tokens</span><span class="p">)</span> <span class="o">-></span>
|
||||
corrected before implicit parentheses can be wrapped around blocks of code.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">rewrite: </span><span class="nf">(@tokens) -></span>
|
||||
<span class="nx">@removeLeadingNewlines</span><span class="p">()</span>
|
||||
<span class="nx">@removeMidExpressionNewlines</span><span class="p">()</span>
|
||||
<span class="nx">@closeOpenCalls</span><span class="p">()</span>
|
||||
@@ -22,13 +22,13 @@ corrected before implicit parentheses can be wrapped around blocks of code.</p>
|
||||
Allow the return value of the block to tell us how many tokens to move
|
||||
forwards (or backwards) in the stream, to make sure we don't miss anything
|
||||
as tokens are inserted and removed, and the stream changes length under
|
||||
our feet.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">scanTokens</span><span class="o">:</span> <span class="p">(</span><span class="nx">block</span><span class="p">)</span> <span class="o">-></span>
|
||||
our feet.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">scanTokens: </span><span class="nf">(block) -></span>
|
||||
<span class="p">{</span><span class="nx">tokens</span><span class="p">}</span> <span class="o">=</span> <span class="k">this</span>
|
||||
<span class="nv">i = </span><span class="mi">0</span>
|
||||
<span class="nx">i</span> <span class="o">+=</span> <span class="nx">block</span><span class="p">.</span><span class="nx">call</span> <span class="k">this</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">,</span> <span class="nx">tokens</span> <span class="k">while</span> <span class="nv">token = </span><span class="nx">tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>
|
||||
<span class="kc">true</span>
|
||||
|
||||
<span class="nx">detectEnd</span><span class="o">:</span> <span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">detectEnd: </span><span class="nf">(i, condition, action) -></span>
|
||||
<span class="p">{</span><span class="nx">tokens</span><span class="p">}</span> <span class="o">=</span> <span class="k">this</span>
|
||||
<span class="nv">levels = </span><span class="mi">0</span>
|
||||
<span class="k">while</span> <span class="nv">token = </span><span class="nx">tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>
|
||||
@@ -40,159 +40,204 @@ our feet.</p> </td> <td class="code"> <div
|
||||
<span class="nx">levels</span> <span class="o">-=</span> <span class="mi">1</span>
|
||||
<span class="nx">i</span> <span class="o">+=</span> <span class="mi">1</span>
|
||||
<span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Leading newlines would introduce an ambiguity in the grammar, so we
|
||||
dispatch them here.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">removeLeadingNewlines</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="k">break</span> <span class="k">for</span> <span class="p">[</span><span class="nx">tag</span><span class="p">],</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">@tokens</span> <span class="k">when</span> <span class="nx">tag</span> <span class="o">isnt</span> <span class="s1">'TERMINATOR'</span>
|
||||
dispatch them here.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">removeLeadingNewlines: </span><span class="nf">-></span>
|
||||
<span class="k">break</span> <span class="k">for</span> <span class="p">[</span><span class="nx">tag</span><span class="p">],</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">@tokens</span> <span class="k">when</span> <span class="nx">tag</span> <span class="o">isnt</span> <span class="s">'TERMINATOR'</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">i</span> <span class="k">if</span> <span class="nx">i</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Some blocks occur in the middle of expressions -- when we're expecting
|
||||
this, remove their trailing newlines.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">removeMidExpressionNewlines</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">,</span> <span class="nx">tokens</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'TERMINATOR'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="k">in</span> <span class="nx">EXPRESSION_CLOSE</span>
|
||||
this, remove their trailing newlines.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">removeMidExpressionNewlines: </span><span class="nf">-></span>
|
||||
<span class="nx">@scanTokens</span> <span class="nf">(token, i, tokens) -></span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="k">unless</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">'TERMINATOR'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="k">in</span> <span class="nx">EXPRESSION_CLOSE</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="mi">0</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>The lexer has tagged the opening parenthesis of a method call. Match it with
|
||||
its paired close. We have the mis-nested outdent case included here for
|
||||
calls that close on the same line, just before their outdent.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">closeOpenCalls</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s1">')'</span><span class="p">,</span> <span class="s1">'CALL_END'</span><span class="p">]</span> <span class="o">or</span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'OUTDENT'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s1">')'</span>
|
||||
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@tokens</span><span class="p">[</span><span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'OUTDENT'</span> <span class="k">then</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">else</span> <span class="nx">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'CALL_END'</span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span> <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'CALL_START'</span>
|
||||
calls that close on the same line, just before their outdent.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">closeOpenCalls: </span><span class="nf">-></span>
|
||||
|
||||
<span class="nv">condition = </span><span class="nf">(token, i) -></span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s">')'</span><span class="p">,</span> <span class="s">'CALL_END'</span><span class="p">]</span> <span class="o">or</span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">'OUTDENT'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s">')'</span>
|
||||
|
||||
<span class="nv">action = </span><span class="nf">(token, i) -></span>
|
||||
<span class="nx">@tokens</span><span class="p">[</span><span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">'OUTDENT'</span> <span class="k">then</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">else</span> <span class="nx">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s">'CALL_END'</span>
|
||||
|
||||
<span class="nx">@scanTokens</span> <span class="nf">(token, i) -></span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span> <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">'CALL_START'</span>
|
||||
<span class="mi">1</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>The lexer has tagged the opening parenthesis of an indexing operation call.
|
||||
Match it with its paired close.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">closeOpenIndexes</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s1">']'</span><span class="p">,</span> <span class="s1">'INDEX_END'</span><span class="p">]</span>
|
||||
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'INDEX_END'</span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span> <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'INDEX_START'</span>
|
||||
Match it with its paired close.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">closeOpenIndexes: </span><span class="nf">-></span>
|
||||
|
||||
<span class="nv">condition = </span><span class="nf">(token, i) -></span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s">']'</span><span class="p">,</span> <span class="s">'INDEX_END'</span><span class="p">]</span>
|
||||
|
||||
<span class="nv">action = </span><span class="nf">(token, i) -></span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s">'INDEX_END'</span>
|
||||
|
||||
<span class="nx">@scanTokens</span> <span class="nf">(token, i) -></span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span> <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">'INDEX_START'</span>
|
||||
<span class="mi">1</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Object literals may be written with implicit braces, for simple cases.
|
||||
Insert the missing braces here, so that the parser doesn't have to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">addImplicitBraces</span><span class="o">:</span> <span class="o">-></span>
|
||||
Insert the missing braces here, so that the parser doesn't have to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">addImplicitBraces: </span><span class="nf">-></span>
|
||||
|
||||
<span class="nv">stack = </span><span class="p">[]</span>
|
||||
<span class="nv">start = </span><span class="kc">null</span>
|
||||
<span class="nv">startsLine = </span><span class="kc">null</span>
|
||||
<span class="nv">sameLine = </span><span class="kc">yes</span>
|
||||
<span class="nv">startIndent = </span><span class="mi">0</span>
|
||||
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">startIndex = </span><span class="mi">0</span>
|
||||
|
||||
<span class="nv">condition = </span><span class="nf">(token, i) -></span>
|
||||
<span class="p">[</span><span class="nx">one</span><span class="p">,</span> <span class="nx">two</span><span class="p">,</span> <span class="nx">three</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span> <span class="p">..</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">3</span><span class="p">]</span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="k">if</span> <span class="s1">'HERECOMMENT'</span> <span class="o">is</span> <span class="nx">one</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="k">return</span> <span class="kc">no</span> <span class="k">if</span> <span class="s">'HERECOMMENT'</span> <span class="o">is</span> <span class="nx">one</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="nx">tag</span><span class="p">]</span> <span class="o">=</span> <span class="nx">token</span>
|
||||
<span class="p">(</span><span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">]</span> <span class="o">and</span>
|
||||
<span class="o">not</span> <span class="p">(</span><span class="nx">two</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">':'</span> <span class="o">or</span> <span class="nx">one</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'@'</span> <span class="o">and</span> <span class="nx">three</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">':'</span><span class="p">))</span> <span class="o">or</span>
|
||||
<span class="p">(</span><span class="nx">tag</span> <span class="o">is</span> <span class="s1">','</span> <span class="o">and</span> <span class="nx">one</span> <span class="o">and</span>
|
||||
<span class="nx">one</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">not</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'NUMBER'</span><span class="p">,</span> <span class="s1">'STRING'</span><span class="p">,</span> <span class="s1">'@'</span><span class="p">,</span> <span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">])</span>
|
||||
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">tok = </span><span class="p">[</span><span class="s1">'}'</span><span class="p">,</span> <span class="s1">'}'</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="nv">tok.generated = </span><span class="kc">yes</span>
|
||||
<span class="nv">sameLine = </span><span class="kc">no</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">LINEBREAKS</span>
|
||||
<span class="k">return</span> <span class="p">(</span>
|
||||
<span class="p">(</span><span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s">'TERMINATOR'</span><span class="p">,</span> <span class="s">'OUTDENT'</span><span class="p">]</span> <span class="o">or</span>
|
||||
<span class="p">(</span><span class="nx">tag</span> <span class="k">in</span> <span class="nx">IMPLICIT_END</span> <span class="o">and</span> <span class="nx">sameLine</span> <span class="o">and</span> <span class="o">not</span> <span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="nx">startIndex</span> <span class="o">is</span> <span class="mi">1</span><span class="p">)))</span> <span class="o">and</span>
|
||||
<span class="p">((</span><span class="o">!</span><span class="nx">startsLine</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">isnt</span> <span class="s">','</span><span class="p">)</span> <span class="o">or</span>
|
||||
<span class="o">not</span> <span class="p">(</span><span class="nx">two</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">':'</span> <span class="o">or</span> <span class="nx">one</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">'@'</span> <span class="o">and</span> <span class="nx">three</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">':'</span><span class="p">)))</span> <span class="o">or</span>
|
||||
<span class="p">(</span><span class="nx">tag</span> <span class="o">is</span> <span class="s">','</span> <span class="o">and</span> <span class="nx">one</span> <span class="o">and</span>
|
||||
<span class="nx">one</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">not</span> <span class="k">in</span> <span class="p">[</span><span class="s">'IDENTIFIER'</span><span class="p">,</span> <span class="s">'NUMBER'</span><span class="p">,</span> <span class="s">'STRING'</span><span class="p">,</span> <span class="s">'@'</span><span class="p">,</span> <span class="s">'TERMINATOR'</span><span class="p">,</span> <span class="s">'OUTDENT'</span><span class="p">]</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="nv">action = </span><span class="nf">(token, i) -></span>
|
||||
<span class="nv">tok = </span><span class="nx">@generate</span> <span class="s">'}'</span><span class="p">,</span> <span class="s">'}'</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">tok</span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">,</span> <span class="nx">tokens</span><span class="p">)</span> <span class="o">-></span>
|
||||
|
||||
<span class="nx">@scanTokens</span> <span class="nf">(token, i, tokens) -></span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nv">tag = </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="k">in</span> <span class="nx">EXPRESSION_START</span>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="p">[(</span><span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'INDENT'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'{'</span> <span class="k">then</span> <span class="s1">'{'</span> <span class="k">else</span> <span class="nx">tag</span><span class="p">),</span> <span class="nx">i</span><span class="p">]</span>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="p">[(</span><span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">'INDENT'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s">'{'</span> <span class="k">then</span> <span class="s">'{'</span> <span class="k">else</span> <span class="nx">tag</span><span class="p">),</span> <span class="nx">i</span><span class="p">]</span>
|
||||
<span class="k">return</span> <span class="mi">1</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">EXPRESSION_END</span>
|
||||
<span class="nv">start = </span><span class="nx">stack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="mi">1</span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">':'</span> <span class="o">and</span>
|
||||
<span class="p">((</span><span class="nv">ago = </span><span class="nx">@tag</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s1">':'</span> <span class="o">or</span> <span class="nx">stack</span><span class="p">[</span><span class="nx">stack</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">'{'</span><span class="p">)</span>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">'{'</span><span class="p">]</span>
|
||||
<span class="nv">idx = </span> <span class="k">if</span> <span class="nx">ago</span> <span class="o">is</span> <span class="s1">'@'</span> <span class="k">then</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span> <span class="k">else</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nx">idx</span> <span class="o">-=</span> <span class="mi">2</span> <span class="k">while</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">idx</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'HERECOMMENT'</span>
|
||||
<span class="nv">value = </span><span class="k">new</span> <span class="nb">String</span><span class="p">(</span><span class="s1">'{'</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="k">unless</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">':'</span> <span class="o">and</span>
|
||||
<span class="p">((</span><span class="nv">ago = </span><span class="nx">@tag</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s">':'</span> <span class="o">or</span> <span class="nx">stack</span><span class="p">[</span><span class="nx">stack</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s">'{'</span><span class="p">)</span>
|
||||
<span class="nv">sameLine = </span><span class="kc">yes</span>
|
||||
<span class="nv">startIndex = </span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s">'{'</span><span class="p">]</span>
|
||||
<span class="nv">idx = </span> <span class="k">if</span> <span class="nx">ago</span> <span class="o">is</span> <span class="s">'@'</span> <span class="k">then</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span> <span class="k">else</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nx">idx</span> <span class="o">-=</span> <span class="mi">2</span> <span class="k">while</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">idx</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s">'HERECOMMENT'</span>
|
||||
<span class="nv">prevTag = </span><span class="nx">@tag</span><span class="p">(</span><span class="nx">idx</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
|
||||
<span class="nv">startsLine = </span><span class="o">not</span> <span class="nx">prevTag</span> <span class="o">or</span> <span class="p">(</span><span class="nx">prevTag</span> <span class="k">in</span> <span class="nx">LINEBREAKS</span><span class="p">)</span>
|
||||
<span class="nv">value = </span><span class="k">new</span> <span class="nb">String</span><span class="p">(</span><span class="s">'{'</span><span class="p">)</span>
|
||||
<span class="nv">value.generated = </span><span class="kc">yes</span>
|
||||
<span class="nv">tok = </span><span class="p">[</span><span class="s1">'{'</span><span class="p">,</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="nv">tok.generated = </span><span class="kc">yes</span>
|
||||
<span class="nv">tok = </span><span class="nx">@generate</span> <span class="s">'{'</span><span class="p">,</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">idx</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">tok</span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
|
||||
<span class="mi">2</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Methods may be optionally called without parentheses, for simple cases.
|
||||
Insert the implicit parentheses here, so that the parser doesn't have to
|
||||
deal with them.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">addImplicitParentheses</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nv">noCall = </span><span class="kc">no</span>
|
||||
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span> <span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">'CALL_END'</span><span class="p">,</span> <span class="s1">')'</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">,</span> <span class="nx">tokens</span><span class="p">)</span> <span class="o">-></span>
|
||||
deal with them.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">addImplicitParentheses: </span><span class="nf">-></span>
|
||||
|
||||
<span class="nv">noCall = seenSingle = seenControl = </span><span class="kc">no</span>
|
||||
|
||||
<span class="nv">condition = </span><span class="nf">(token, i) -></span>
|
||||
<span class="p">[</span><span class="nx">tag</span><span class="p">]</span> <span class="o">=</span> <span class="nx">token</span>
|
||||
<span class="k">return</span> <span class="kc">yes</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">seenSingle</span> <span class="o">and</span> <span class="nx">token</span><span class="p">.</span><span class="nx">fromThen</span>
|
||||
<span class="nv">seenSingle = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s">'IF'</span><span class="p">,</span> <span class="s">'ELSE'</span><span class="p">,</span> <span class="s">'CATCH'</span><span class="p">,</span> <span class="s">'->'</span><span class="p">,</span> <span class="s">'=>'</span><span class="p">,</span> <span class="s">'CLASS'</span><span class="p">]</span>
|
||||
<span class="nv">seenControl = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s">'IF'</span><span class="p">,</span> <span class="s">'ELSE'</span><span class="p">,</span> <span class="s">'SWITCH'</span><span class="p">,</span> <span class="s">'TRY'</span><span class="p">,</span> <span class="s">'='</span><span class="p">]</span>
|
||||
<span class="k">return</span> <span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s">'.'</span><span class="p">,</span> <span class="s">'?.'</span><span class="p">,</span> <span class="s">'::'</span><span class="p">]</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s">'OUTDENT'</span>
|
||||
<span class="o">not</span> <span class="nx">token</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">isnt</span> <span class="s">','</span> <span class="o">and</span> <span class="p">(</span><span class="nx">tag</span> <span class="k">in</span> <span class="nx">IMPLICIT_END</span> <span class="o">or</span>
|
||||
<span class="p">(</span><span class="nx">tag</span> <span class="o">is</span> <span class="s">'INDENT'</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">seenControl</span><span class="p">))</span> <span class="o">and</span>
|
||||
<span class="p">(</span><span class="nx">tag</span> <span class="o">isnt</span> <span class="s">'INDENT'</span> <span class="o">or</span>
|
||||
<span class="p">(</span><span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">not</span> <span class="k">in</span> <span class="p">[</span><span class="s">'CLASS'</span><span class="p">,</span> <span class="s">'EXTENDS'</span><span class="p">]</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">not</span> <span class="k">in</span> <span class="nx">IMPLICIT_BLOCK</span> <span class="o">and</span>
|
||||
<span class="o">not</span> <span class="p">((</span><span class="nv">post = </span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="o">and</span> <span class="nx">post</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">post</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">'{'</span><span class="p">)))</span>
|
||||
|
||||
<span class="nv">action = </span><span class="nf">(token, i) -></span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">@generate</span> <span class="s">'CALL_END'</span><span class="p">,</span> <span class="s">')'</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
|
||||
<span class="nx">@scanTokens</span> <span class="nf">(token, i, tokens) -></span>
|
||||
<span class="nv">tag = </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nv">noCall = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'CLASS'</span><span class="p">,</span> <span class="s1">'IF'</span><span class="p">]</span>
|
||||
<span class="nv">noCall = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s">'CLASS'</span><span class="p">,</span> <span class="s">'IF'</span><span class="p">,</span> <span class="s">'FOR'</span><span class="p">,</span> <span class="s">'WHILE'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="nx">prev</span><span class="p">,</span> <span class="nx">current</span><span class="p">,</span> <span class="nx">next</span><span class="p">]</span> <span class="o">=</span> <span class="nx">tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span> <span class="p">..</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nv">callObject = </span><span class="o">not</span> <span class="nx">noCall</span> <span class="o">and</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'INDENT'</span> <span class="o">and</span>
|
||||
<span class="nx">next</span> <span class="o">and</span> <span class="nx">next</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'{'</span> <span class="o">and</span>
|
||||
<span class="nv">callObject = </span><span class="o">not</span> <span class="nx">noCall</span> <span class="o">and</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">'INDENT'</span> <span class="o">and</span>
|
||||
<span class="nx">next</span> <span class="o">and</span> <span class="nx">next</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">'{'</span> <span class="o">and</span>
|
||||
<span class="nx">prev</span> <span class="o">and</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="nx">IMPLICIT_FUNC</span>
|
||||
<span class="nv">seenSingle = </span><span class="kc">no</span>
|
||||
<span class="nv">seenControl = </span><span class="kc">no</span>
|
||||
<span class="nv">noCall = </span><span class="kc">no</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">LINEBREAKS</span>
|
||||
<span class="nv">token.call = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">prev</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">prev</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">and</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'?'</span>
|
||||
<span class="nv">token.call = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">prev</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">prev</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">and</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">'?'</span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">token</span><span class="p">.</span><span class="nx">fromThen</span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">callObject</span> <span class="o">or</span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="k">unless</span> <span class="nx">callObject</span> <span class="o">or</span>
|
||||
<span class="nx">prev</span><span class="o">?</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">and</span> <span class="p">(</span><span class="nx">prev</span><span class="p">.</span><span class="nx">call</span> <span class="o">or</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="nx">IMPLICIT_FUNC</span><span class="p">)</span> <span class="o">and</span>
|
||||
<span class="p">(</span><span class="nx">tag</span> <span class="k">in</span> <span class="nx">IMPLICIT_CALL</span> <span class="o">or</span> <span class="o">not</span> <span class="p">(</span><span class="nx">token</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">or</span> <span class="nx">token</span><span class="p">.</span><span class="nx">newLine</span><span class="p">)</span> <span class="o">and</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">IMPLICIT_UNSPACED_CALL</span><span class="p">)</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">'CALL_START'</span><span class="p">,</span> <span class="s1">'('</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="p">[</span><span class="nx">tag</span><span class="p">]</span> <span class="o">=</span> <span class="nx">token</span>
|
||||
<span class="k">return</span> <span class="kc">yes</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">seenSingle</span> <span class="o">and</span> <span class="nx">token</span><span class="p">.</span><span class="nx">fromThen</span>
|
||||
<span class="nv">seenSingle = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'ELSE'</span><span class="p">,</span> <span class="s1">'CATCH'</span><span class="p">,</span> <span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">]</span>
|
||||
<span class="nv">seenControl = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'ELSE'</span><span class="p">,</span> <span class="s1">'SWITCH'</span><span class="p">,</span> <span class="s1">'TRY'</span><span class="p">]</span>
|
||||
<span class="k">return</span> <span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'.'</span><span class="p">,</span> <span class="s1">'?.'</span><span class="p">,</span> <span class="s1">'::'</span><span class="p">]</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'OUTDENT'</span>
|
||||
<span class="o">not</span> <span class="nx">token</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">isnt</span> <span class="s1">','</span> <span class="o">and</span> <span class="p">(</span><span class="nx">tag</span> <span class="k">in</span> <span class="nx">IMPLICIT_END</span> <span class="o">or</span>
|
||||
<span class="p">(</span><span class="nx">tag</span> <span class="o">is</span> <span class="s1">'INDENT'</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">seenControl</span><span class="p">))</span> <span class="o">and</span>
|
||||
<span class="p">(</span><span class="nx">tag</span> <span class="o">isnt</span> <span class="s1">'INDENT'</span> <span class="o">or</span>
|
||||
<span class="p">(</span><span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">isnt</span> <span class="s1">'CLASS'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">not</span> <span class="k">in</span> <span class="nx">IMPLICIT_BLOCK</span> <span class="o">and</span>
|
||||
<span class="o">not</span> <span class="p">((</span><span class="nv">post = </span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="o">and</span> <span class="nx">post</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">post</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'{'</span><span class="p">)))</span>
|
||||
<span class="p">,</span> <span class="nx">action</span>
|
||||
<span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'FUNC_EXIST'</span> <span class="k">if</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'?'</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">@generate</span> <span class="s">'CALL_START'</span><span class="p">,</span> <span class="s">'('</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
|
||||
<span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s">'FUNC_EXIST'</span> <span class="k">if</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">'?'</span>
|
||||
<span class="mi">2</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Because our grammar is LALR(1), it can't handle some single-line
|
||||
expressions that lack ending delimiters. The <strong>Rewriter</strong> adds the implicit
|
||||
blocks, so it doesn't need to. ')' can close a single-line block,
|
||||
but we need to make sure it's balanced.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">addImplicitIndentation</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">,</span> <span class="nx">tokens</span><span class="p">)</span> <span class="o">-></span>
|
||||
but we need to make sure it's balanced.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">addImplicitIndentation: </span><span class="nf">-></span>
|
||||
|
||||
<span class="nv">starter = indent = outdent = </span><span class="kc">null</span>
|
||||
|
||||
<span class="nv">condition = </span><span class="nf">(token, i) -></span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">isnt</span> <span class="s">';'</span> <span class="o">and</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="nx">SINGLE_CLOSERS</span> <span class="o">and</span>
|
||||
<span class="o">not</span> <span class="p">(</span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">'ELSE'</span> <span class="o">and</span> <span class="nx">starter</span> <span class="o">not</span> <span class="k">in</span> <span class="p">[</span><span class="s">'IF'</span><span class="p">,</span> <span class="s">'THEN'</span><span class="p">])</span>
|
||||
|
||||
<span class="nv">action = </span><span class="nf">(token, i) -></span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="p">(</span><span class="k">if</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s">','</span> <span class="k">then</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">else</span> <span class="nx">i</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">outdent</span>
|
||||
|
||||
<span class="nx">@scanTokens</span> <span class="nf">(token, i, tokens) -></span>
|
||||
<span class="p">[</span><span class="nx">tag</span><span class="p">]</span> <span class="o">=</span> <span class="nx">token</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'TERMINATOR'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'THEN'</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">'TERMINATOR'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s">'THEN'</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="k">return</span> <span class="mi">0</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'ELSE'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">isnt</span> <span class="s1">'OUTDENT'</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">'ELSE'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">isnt</span> <span class="s">'OUTDENT'</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">@indentation</span><span class="p">(</span><span class="nx">token</span><span class="p">)...</span>
|
||||
<span class="k">return</span> <span class="mi">2</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'CATCH'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">)</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'FINALLY'</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">'CATCH'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">)</span> <span class="k">in</span> <span class="p">[</span><span class="s">'OUTDENT'</span><span class="p">,</span> <span class="s">'TERMINATOR'</span><span class="p">,</span> <span class="s">'FINALLY'</span><span class="p">]</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">@indentation</span><span class="p">(</span><span class="nx">token</span><span class="p">)...</span>
|
||||
<span class="k">return</span> <span class="mi">4</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">SINGLE_LINERS</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">isnt</span> <span class="s1">'INDENT'</span> <span class="o">and</span>
|
||||
<span class="o">not</span> <span class="p">(</span><span class="nx">tag</span> <span class="o">is</span> <span class="s1">'ELSE'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'IF'</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">SINGLE_LINERS</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">isnt</span> <span class="s">'INDENT'</span> <span class="o">and</span>
|
||||
<span class="o">not</span> <span class="p">(</span><span class="nx">tag</span> <span class="o">is</span> <span class="s">'ELSE'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s">'IF'</span><span class="p">)</span>
|
||||
<span class="nv">starter = </span><span class="nx">tag</span>
|
||||
<span class="p">[</span><span class="nx">indent</span><span class="p">,</span> <span class="nx">outdent</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@indentation</span> <span class="nx">token</span>
|
||||
<span class="nv">indent.fromThen = </span><span class="kc">true</span> <span class="k">if</span> <span class="nx">starter</span> <span class="o">is</span> <span class="s1">'THEN'</span>
|
||||
<span class="nv">indent.generated = outdent.generated = </span><span class="kc">true</span>
|
||||
<span class="p">[</span><span class="nx">indent</span><span class="p">,</span> <span class="nx">outdent</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@indentation</span> <span class="nx">token</span><span class="p">,</span> <span class="kc">yes</span>
|
||||
<span class="nv">indent.fromThen = </span><span class="kc">true</span> <span class="k">if</span> <span class="nx">starter</span> <span class="o">is</span> <span class="s">'THEN'</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">indent</span>
|
||||
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">';'</span> <span class="o">and</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="nx">SINGLE_CLOSERS</span> <span class="o">and</span>
|
||||
<span class="o">not</span> <span class="p">(</span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'ELSE'</span> <span class="o">and</span> <span class="nx">starter</span> <span class="o">not</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'THEN'</span><span class="p">])</span>
|
||||
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="p">(</span><span class="k">if</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s1">','</span> <span class="k">then</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">else</span> <span class="nx">i</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">outdent</span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'THEN'</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">'THEN'</span>
|
||||
<span class="k">return</span> <span class="mi">1</span>
|
||||
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Tag postfix conditionals as such, so that we can parse them with a
|
||||
different precedence.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">tagPostfixConditionals</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'INDENT'</span><span class="p">]</span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'IF'</span>
|
||||
different precedence.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tagPostfixConditionals: </span><span class="nf">-></span>
|
||||
|
||||
<span class="nv">original = </span><span class="kc">null</span>
|
||||
|
||||
<span class="nv">condition = </span><span class="nf">(token, i) -></span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s">'TERMINATOR'</span><span class="p">,</span> <span class="s">'INDENT'</span><span class="p">]</span>
|
||||
|
||||
<span class="nv">action = </span><span class="nf">(token, i) -></span>
|
||||
<span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s">'INDENT'</span> <span class="o">or</span> <span class="p">(</span><span class="nx">token</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">token</span><span class="p">.</span><span class="nx">fromThen</span><span class="p">)</span>
|
||||
<span class="nx">original</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s">'POST_'</span> <span class="o">+</span> <span class="nx">original</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
|
||||
<span class="nx">@scanTokens</span> <span class="nf">(token, i) -></span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="k">unless</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">'IF'</span>
|
||||
<span class="nv">original = </span><span class="nx">token</span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">original</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'POST_'</span> <span class="o">+</span> <span class="nx">original</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">'INDENT'</span>
|
||||
<span class="mi">1</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Generate the indentation tokens, based on another token on the same line.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">indentation</span><span class="o">:</span> <span class="p">(</span><span class="nx">token</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="p">[[</span><span class="s1">'INDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]],</span> <span class="p">[</span><span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]]</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>Look up a tag by token index.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">tag</span><span class="o">:</span> <span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="o">-></span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <p>List of the token pairs that must be balanced.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BALANCED_PAIRS = </span><span class="p">[</span>
|
||||
<span class="p">[</span><span class="s1">'('</span><span class="p">,</span> <span class="s1">')'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'['</span><span class="p">,</span> <span class="s1">']'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'{'</span><span class="p">,</span> <span class="s1">'}'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'INDENT'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">],</span>
|
||||
<span class="p">[</span><span class="s1">'CALL_START'</span><span class="p">,</span> <span class="s1">'CALL_END'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'PARAM_START'</span><span class="p">,</span> <span class="s1">'PARAM_END'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'INDEX_START'</span><span class="p">,</span> <span class="s1">'INDEX_END'</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <p>The inverse mappings of <code>BALANCED_PAIRS</code> we're trying to fix up, so we can
|
||||
look things up from either end.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.INVERSES = INVERSES = </span><span class="p">{}</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</a> </div> <p>The tokens that signal the start/end of a balanced pair.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_START = </span><span class="p">[]</span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
|
||||
<span class="mi">1</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Generate the indentation tokens, based on another token on the same line.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">indentation: </span><span class="nf">(token, implicit = no) -></span>
|
||||
<span class="nv">indent = </span><span class="p">[</span><span class="s">'INDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="nv">outdent = </span><span class="p">[</span><span class="s">'OUTDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="nv">indent.generated = outdent.generated = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">implicit</span>
|
||||
<span class="p">[</span><span class="nx">indent</span><span class="p">,</span> <span class="nx">outdent</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>Create a generated token: one that exists due to a use of implicit syntax.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">generate: </span><span class="nf">(tag, value, line) -></span>
|
||||
<span class="nv">tok = </span><span class="p">[</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">line</span><span class="p">]</span>
|
||||
<span class="nv">tok.generated = </span><span class="kc">yes</span>
|
||||
<span class="nx">tok</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>Look up a tag by token index.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tag: </span><span class="nf">(i) -></span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <p>List of the token pairs that must be balanced.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BALANCED_PAIRS = </span><span class="p">[</span>
|
||||
<span class="p">[</span><span class="s">'('</span><span class="p">,</span> <span class="s">')'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'['</span><span class="p">,</span> <span class="s">']'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'{'</span><span class="p">,</span> <span class="s">'}'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'INDENT'</span><span class="p">,</span> <span class="s">'OUTDENT'</span><span class="p">],</span>
|
||||
<span class="p">[</span><span class="s">'CALL_START'</span><span class="p">,</span> <span class="s">'CALL_END'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'PARAM_START'</span><span class="p">,</span> <span class="s">'PARAM_END'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'INDEX_START'</span><span class="p">,</span> <span class="s">'INDEX_END'</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</a> </div> <p>The inverse mappings of <code>BALANCED_PAIRS</code> we're trying to fix up, so we can
|
||||
look things up from either end.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.INVERSES = INVERSES = </span><span class="p">{}</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">¶</a> </div> <p>The tokens that signal the start/end of a balanced pair.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_START = </span><span class="p">[]</span>
|
||||
<span class="nv">EXPRESSION_END = </span><span class="p">[]</span>
|
||||
|
||||
<span class="k">for</span> <span class="p">[</span><span class="nx">left</span><span class="p">,</span> <span class="nx">rite</span><span class="p">]</span> <span class="k">in</span> <span class="nx">BALANCED_PAIRS</span>
|
||||
<span class="nx">EXPRESSION_START</span><span class="p">.</span><span class="nx">push</span> <span class="nx">INVERSES</span><span class="p">[</span><span class="nx">rite</span><span class="p">]</span> <span class="o">=</span> <span class="nx">left</span>
|
||||
<span class="nx">EXPRESSION_END</span> <span class="p">.</span><span class="nx">push</span> <span class="nx">INVERSES</span><span class="p">[</span><span class="nx">left</span><span class="p">]</span> <span class="o">=</span> <span class="nx">rite</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">¶</a> </div> <p>Tokens that indicate the close of a clause of an expression.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_CLOSE = </span><span class="p">[</span><span class="s1">'CATCH'</span><span class="p">,</span> <span class="s1">'WHEN'</span><span class="p">,</span> <span class="s1">'ELSE'</span><span class="p">,</span> <span class="s1">'FINALLY'</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">EXPRESSION_END</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">¶</a> </div> <p>Tokens that, if followed by an <code>IMPLICIT_CALL</code>, indicate a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_FUNC = </span><span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'SUPER'</span><span class="p">,</span> <span class="s1">')'</span><span class="p">,</span> <span class="s1">'CALL_END'</span><span class="p">,</span> <span class="s1">']'</span><span class="p">,</span> <span class="s1">'INDEX_END'</span><span class="p">,</span> <span class="s1">'@'</span><span class="p">,</span> <span class="s1">'THIS'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">¶</a> </div> <p>If preceded by an <code>IMPLICIT_FUNC</code>, indicates a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_CALL = </span><span class="p">[</span>
|
||||
<span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'NUMBER'</span><span class="p">,</span> <span class="s1">'STRING'</span><span class="p">,</span> <span class="s1">'JS'</span><span class="p">,</span> <span class="s1">'REGEX'</span><span class="p">,</span> <span class="s1">'NEW'</span><span class="p">,</span> <span class="s1">'PARAM_START'</span><span class="p">,</span> <span class="s1">'CLASS'</span>
|
||||
<span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'TRY'</span><span class="p">,</span> <span class="s1">'SWITCH'</span><span class="p">,</span> <span class="s1">'THIS'</span><span class="p">,</span> <span class="s1">'BOOL'</span><span class="p">,</span> <span class="s1">'UNARY'</span><span class="p">,</span> <span class="s1">'SUPER'</span>
|
||||
<span class="s1">'@'</span><span class="p">,</span> <span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">,</span> <span class="s1">'['</span><span class="p">,</span> <span class="s1">'('</span><span class="p">,</span> <span class="s1">'{'</span><span class="p">,</span> <span class="s1">'--'</span><span class="p">,</span> <span class="s1">'++'</span>
|
||||
<span class="nx">EXPRESSION_END</span> <span class="p">.</span><span class="nx">push</span> <span class="nx">INVERSES</span><span class="p">[</span><span class="nx">left</span><span class="p">]</span> <span class="o">=</span> <span class="nx">rite</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">¶</a> </div> <p>Tokens that indicate the close of a clause of an expression.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_CLOSE = </span><span class="p">[</span><span class="s">'CATCH'</span><span class="p">,</span> <span class="s">'WHEN'</span><span class="p">,</span> <span class="s">'ELSE'</span><span class="p">,</span> <span class="s">'FINALLY'</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">EXPRESSION_END</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">¶</a> </div> <p>Tokens that, if followed by an <code>IMPLICIT_CALL</code>, indicate a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_FUNC = </span><span class="p">[</span><span class="s">'IDENTIFIER'</span><span class="p">,</span> <span class="s">'SUPER'</span><span class="p">,</span> <span class="s">')'</span><span class="p">,</span> <span class="s">'CALL_END'</span><span class="p">,</span> <span class="s">']'</span><span class="p">,</span> <span class="s">'INDEX_END'</span><span class="p">,</span> <span class="s">'@'</span><span class="p">,</span> <span class="s">'THIS'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">¶</a> </div> <p>If preceded by an <code>IMPLICIT_FUNC</code>, indicates a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_CALL = </span><span class="p">[</span>
|
||||
<span class="s">'IDENTIFIER'</span><span class="p">,</span> <span class="s">'NUMBER'</span><span class="p">,</span> <span class="s">'STRING'</span><span class="p">,</span> <span class="s">'JS'</span><span class="p">,</span> <span class="s">'REGEX'</span><span class="p">,</span> <span class="s">'NEW'</span><span class="p">,</span> <span class="s">'PARAM_START'</span><span class="p">,</span> <span class="s">'CLASS'</span>
|
||||
<span class="s">'IF'</span><span class="p">,</span> <span class="s">'TRY'</span><span class="p">,</span> <span class="s">'SWITCH'</span><span class="p">,</span> <span class="s">'THIS'</span><span class="p">,</span> <span class="s">'BOOL'</span><span class="p">,</span> <span class="s">'NULL'</span><span class="p">,</span> <span class="s">'UNDEFINED'</span><span class="p">,</span> <span class="s">'UNARY'</span><span class="p">,</span> <span class="s">'SUPER'</span>
|
||||
<span class="s">'@'</span><span class="p">,</span> <span class="s">'->'</span><span class="p">,</span> <span class="s">'=>'</span><span class="p">,</span> <span class="s">'['</span><span class="p">,</span> <span class="s">'('</span><span class="p">,</span> <span class="s">'{'</span><span class="p">,</span> <span class="s">'--'</span><span class="p">,</span> <span class="s">'++'</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nv">IMPLICIT_UNSPACED_CALL = </span><span class="p">[</span><span class="s1">'+'</span><span class="p">,</span> <span class="s1">'-'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">¶</a> </div> <p>Tokens indicating that the implicit call must enclose a block of expressions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_BLOCK = </span><span class="p">[</span><span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">,</span> <span class="s1">'{'</span><span class="p">,</span> <span class="s1">'['</span><span class="p">,</span> <span class="s1">','</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">¶</a> </div> <p>Tokens that always mark the end of an implicit call for single-liners.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_END = </span><span class="p">[</span><span class="s1">'POST_IF'</span><span class="p">,</span> <span class="s1">'FOR'</span><span class="p">,</span> <span class="s1">'WHILE'</span><span class="p">,</span> <span class="s1">'UNTIL'</span><span class="p">,</span> <span class="s1">'WHEN'</span><span class="p">,</span> <span class="s1">'BY'</span><span class="p">,</span> <span class="s1">'LOOP'</span><span class="p">,</span> <span class="s1">'TERMINATOR'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">¶</a> </div> <p>Single-line flavors of block expressions that have unclosed endings.
|
||||
The grammar can't disambiguate them, so we insert the implicit indentation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">SINGLE_LINERS = </span><span class="p">[</span><span class="s1">'ELSE'</span><span class="p">,</span> <span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">,</span> <span class="s1">'TRY'</span><span class="p">,</span> <span class="s1">'FINALLY'</span><span class="p">,</span> <span class="s1">'THEN'</span><span class="p">]</span>
|
||||
<span class="nv">SINGLE_CLOSERS = </span><span class="p">[</span><span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'CATCH'</span><span class="p">,</span> <span class="s1">'FINALLY'</span><span class="p">,</span> <span class="s1">'ELSE'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="s1">'LEADING_WHEN'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">¶</a> </div> <p>Tokens that end a line.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">LINEBREAKS = </span><span class="p">[</span><span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'INDENT'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">]</span>
|
||||
<span class="nv">IMPLICIT_UNSPACED_CALL = </span><span class="p">[</span><span class="s">'+'</span><span class="p">,</span> <span class="s">'-'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">¶</a> </div> <p>Tokens indicating that the implicit call must enclose a block of expressions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_BLOCK = </span><span class="p">[</span><span class="s">'->'</span><span class="p">,</span> <span class="s">'=>'</span><span class="p">,</span> <span class="s">'{'</span><span class="p">,</span> <span class="s">'['</span><span class="p">,</span> <span class="s">','</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">¶</a> </div> <p>Tokens that always mark the end of an implicit call for single-liners.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_END = </span><span class="p">[</span><span class="s">'POST_IF'</span><span class="p">,</span> <span class="s">'FOR'</span><span class="p">,</span> <span class="s">'WHILE'</span><span class="p">,</span> <span class="s">'UNTIL'</span><span class="p">,</span> <span class="s">'WHEN'</span><span class="p">,</span> <span class="s">'BY'</span><span class="p">,</span> <span class="s">'LOOP'</span><span class="p">,</span> <span class="s">'TERMINATOR'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">¶</a> </div> <p>Single-line flavors of block expressions that have unclosed endings.
|
||||
The grammar can't disambiguate them, so we insert the implicit indentation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">SINGLE_LINERS = </span><span class="p">[</span><span class="s">'ELSE'</span><span class="p">,</span> <span class="s">'->'</span><span class="p">,</span> <span class="s">'=>'</span><span class="p">,</span> <span class="s">'TRY'</span><span class="p">,</span> <span class="s">'FINALLY'</span><span class="p">,</span> <span class="s">'THEN'</span><span class="p">]</span>
|
||||
<span class="nv">SINGLE_CLOSERS = </span><span class="p">[</span><span class="s">'TERMINATOR'</span><span class="p">,</span> <span class="s">'CATCH'</span><span class="p">,</span> <span class="s">'FINALLY'</span><span class="p">,</span> <span class="s">'ELSE'</span><span class="p">,</span> <span class="s">'OUTDENT'</span><span class="p">,</span> <span class="s">'LEADING_WHEN'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">¶</a> </div> <p>Tokens that end a line.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">LINEBREAKS = </span><span class="p">[</span><span class="s">'TERMINATOR'</span><span class="p">,</span> <span class="s">'INDENT'</span><span class="p">,</span> <span class="s">'OUTDENT'</span><span class="p">]</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -3,52 +3,56 @@ generate code, you create a tree of scopes in the same shape as the nested
|
||||
function bodies. Each scope knows about the variables declared within it,
|
||||
and has a reference to its parent enclosing scope. In this way, we know which
|
||||
variables are new and need to be declared with <code>var</code>, and which are shared
|
||||
with the outside.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>Import the helpers we plan to use.</p> </td> <td class="code"> <div class="highlight"><pre><span class="p">{</span><span class="nx">extend</span><span class="p">,</span> <span class="nx">last</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'./helpers'</span>
|
||||
with the outside.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>Import the helpers we plan to use.</p> </td> <td class="code"> <div class="highlight"><pre><span class="p">{</span><span class="nx">extend</span><span class="p">,</span> <span class="nx">last</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">'./helpers'</span>
|
||||
|
||||
<span class="nv">exports.Scope = </span><span class="nx">class</span> <span class="nx">Scope</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>The top-level <strong>Scope</strong> object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">@root</span><span class="o">:</span> <span class="kc">null</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Initialize a scope with its parent, for lookups up the chain,
|
||||
<span class="nv">exports.Scope = </span><span class="k">class</span> <span class="nx">Scope</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>The top-level <strong>Scope</strong> object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="vi">@root: </span><span class="kc">null</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Initialize a scope with its parent, for lookups up the chain,
|
||||
as well as a reference to the <strong>Block</strong> node it belongs to, which is
|
||||
where it should declare its variables, and a reference to the function that
|
||||
it wraps.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@parent</span><span class="p">,</span> <span class="nx">@expressions</span><span class="p">,</span> <span class="nx">@method</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="vi">@variables = </span><span class="p">[{</span><span class="nx">name</span><span class="o">:</span> <span class="s1">'arguments'</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="s1">'arguments'</span><span class="p">}]</span>
|
||||
it wraps.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">constructor: </span><span class="nf">(@parent, @expressions, @method) -></span>
|
||||
<span class="vi">@variables = </span><span class="p">[{</span><span class="nv">name: </span><span class="s">'arguments'</span><span class="p">,</span> <span class="nv">type: </span><span class="s">'arguments'</span><span class="p">}]</span>
|
||||
<span class="vi">@positions = </span><span class="p">{}</span>
|
||||
<span class="nv">Scope.root = </span><span class="k">this</span> <span class="nx">unless</span> <span class="nx">@parent</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Adds a new variable or overrides an existing one.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">add</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">type</span><span class="p">,</span> <span class="nx">immediate</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">Scope.root = </span><span class="k">this</span> <span class="k">unless</span> <span class="nx">@parent</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Adds a new variable or overrides an existing one.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">add: </span><span class="nf">(name, type, immediate) -></span>
|
||||
<span class="k">return</span> <span class="nx">@parent</span><span class="p">.</span><span class="nx">add</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">type</span><span class="p">,</span> <span class="nx">immediate</span> <span class="k">if</span> <span class="nx">@shared</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">immediate</span>
|
||||
<span class="k">if</span> <span class="k">typeof</span> <span class="p">(</span><span class="nv">pos = </span><span class="nx">@positions</span><span class="p">[</span><span class="nx">name</span><span class="p">])</span> <span class="o">is</span> <span class="s1">'number'</span>
|
||||
<span class="nx">@variables</span><span class="p">[</span><span class="nx">pos</span><span class="p">].</span><span class="nv">type = </span><span class="nx">type</span>
|
||||
<span class="k">if</span> <span class="nb">Object</span><span class="o">::</span><span class="nx">hasOwnProperty</span><span class="p">.</span><span class="nx">call</span> <span class="nx">@positions</span><span class="p">,</span> <span class="nx">name</span>
|
||||
<span class="nx">@variables</span><span class="p">[</span><span class="nx">@positions</span><span class="p">[</span><span class="nx">name</span><span class="p">]].</span><span class="nv">type = </span><span class="nx">type</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">@positions</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@variables</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="nx">name</span><span class="p">,</span> <span class="nx">type</span><span class="p">})</span> <span class="o">-</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Look up a variable name in lexical scope, and declare it if it does not
|
||||
already exist.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">find</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">yes</span> <span class="k">if</span> <span class="nx">@check</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">options</span>
|
||||
<span class="nx">@add</span> <span class="nx">name</span><span class="p">,</span> <span class="s1">'var'</span>
|
||||
<span class="kc">no</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Reserve a variable name as originating from a function parameter for this
|
||||
scope. No <code>var</code> required for internal references.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">parameter</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@positions</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@variables</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="nx">name</span><span class="p">,</span> <span class="nx">type</span><span class="p">})</span> <span class="o">-</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>When <code>super</code> is called, we need to find the name of the current method we're
|
||||
in, so that we know how to invoke the same method of the parent class. This
|
||||
can get complicated if super is being called from an inner function.
|
||||
<code>namedMethod</code> will walk up the scope tree until it either finds the first
|
||||
function object that has a name filled in, or bottoms out.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">namedMethod: </span><span class="nf">-></span>
|
||||
<span class="k">return</span> <span class="nx">@method</span> <span class="k">if</span> <span class="nx">@method</span><span class="p">.</span><span class="nx">name</span> <span class="o">or</span> <span class="o">!</span><span class="nx">@parent</span>
|
||||
<span class="nx">@parent</span><span class="p">.</span><span class="nx">namedMethod</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Look up a variable name in lexical scope, and declare it if it does not
|
||||
already exist.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">find: </span><span class="nf">(name) -></span>
|
||||
<span class="k">return</span> <span class="kc">yes</span> <span class="k">if</span> <span class="nx">@check</span> <span class="nx">name</span>
|
||||
<span class="nx">@add</span> <span class="nx">name</span><span class="p">,</span> <span class="s">'var'</span>
|
||||
<span class="kc">no</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>Reserve a variable name as originating from a function parameter for this
|
||||
scope. No <code>var</code> required for internal references.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">parameter: </span><span class="nf">(name) -></span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@shared</span> <span class="o">and</span> <span class="nx">@parent</span><span class="p">.</span><span class="nx">check</span> <span class="nx">name</span><span class="p">,</span> <span class="kc">yes</span>
|
||||
<span class="nx">@add</span> <span class="nx">name</span><span class="p">,</span> <span class="s1">'param'</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>Just check to see if a variable has already been declared, without reserving,
|
||||
walks up to the root scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">check</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">immediate</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">found = </span><span class="o">!!</span><span class="nx">@type</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="nx">found</span> <span class="k">if</span> <span class="nx">found</span> <span class="o">or</span> <span class="nx">immediate</span>
|
||||
<span class="o">!!</span><span class="nx">@parent</span><span class="o">?</span><span class="p">.</span><span class="nx">check</span> <span class="nx">name</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Generate a temporary variable name at the given index.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">temporary</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">index</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@add</span> <span class="nx">name</span><span class="p">,</span> <span class="s">'param'</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Just check to see if a variable has already been declared, without reserving,
|
||||
walks up to the root scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">check: </span><span class="nf">(name) -></span>
|
||||
<span class="o">!!</span><span class="p">(</span><span class="nx">@type</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">or</span> <span class="nx">@parent</span><span class="o">?</span><span class="p">.</span><span class="nx">check</span><span class="p">(</span><span class="nx">name</span><span class="p">))</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Generate a temporary variable name at the given index.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">temporary: </span><span class="nf">(name, index) -></span>
|
||||
<span class="k">if</span> <span class="nx">name</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">1</span>
|
||||
<span class="s1">'_'</span> <span class="o">+</span> <span class="nx">name</span> <span class="o">+</span> <span class="k">if</span> <span class="nx">index</span> <span class="o">></span> <span class="mi">1</span> <span class="k">then</span> <span class="nx">index</span> <span class="k">else</span> <span class="s1">''</span>
|
||||
<span class="s">'_'</span> <span class="o">+</span> <span class="nx">name</span> <span class="o">+</span> <span class="k">if</span> <span class="nx">index</span> <span class="o">></span> <span class="mi">1</span> <span class="k">then</span> <span class="nx">index</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">else</span> <span class="s">''</span>
|
||||
<span class="k">else</span>
|
||||
<span class="s1">'_'</span> <span class="o">+</span> <span class="p">(</span><span class="nx">index</span> <span class="o">+</span> <span class="nb">parseInt</span> <span class="nx">name</span><span class="p">,</span> <span class="mi">36</span><span class="p">).</span><span class="nx">toString</span><span class="p">(</span><span class="mi">36</span><span class="p">).</span><span class="nx">replace</span> <span class="sr">/\d/g</span><span class="p">,</span> <span class="s1">'a'</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Gets the type of a variable.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">type</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="s">'_'</span> <span class="o">+</span> <span class="p">(</span><span class="nx">index</span> <span class="o">+</span> <span class="nb">parseInt</span> <span class="nx">name</span><span class="p">,</span> <span class="mi">36</span><span class="p">).</span><span class="nx">toString</span><span class="p">(</span><span class="mi">36</span><span class="p">).</span><span class="nx">replace</span> <span class="sr">/\d/g</span><span class="p">,</span> <span class="s">'a'</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Gets the type of a variable.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">type: </span><span class="nf">(name) -></span>
|
||||
<span class="k">return</span> <span class="nx">v</span><span class="p">.</span><span class="nx">type</span> <span class="k">for</span> <span class="nx">v</span> <span class="k">in</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">v</span><span class="p">.</span><span class="nx">name</span> <span class="o">is</span> <span class="nx">name</span>
|
||||
<span class="kc">null</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>If we need to store an intermediate result, find an available name for a
|
||||
compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on...</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">freeVariable</span><span class="o">:</span> <span class="p">(</span><span class="nx">type</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="kc">null</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>If we need to store an intermediate result, find an available name for a
|
||||
compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on...</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">freeVariable: </span><span class="nf">(name, reserve=true) -></span>
|
||||
<span class="nv">index = </span><span class="mi">0</span>
|
||||
<span class="nx">index</span><span class="o">++</span> <span class="k">while</span> <span class="nx">@check</span><span class="p">((</span><span class="nv">temp = </span><span class="nx">@temporary</span> <span class="nx">type</span><span class="p">,</span> <span class="nx">index</span><span class="p">))</span>
|
||||
<span class="nx">@add</span> <span class="nx">temp</span><span class="p">,</span> <span class="s1">'var'</span><span class="p">,</span> <span class="kc">yes</span>
|
||||
<span class="nx">temp</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Ensure that an assignment is made at the top of this scope
|
||||
(or at the top-level scope, if requested).</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">assign</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@add</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">value</span><span class="o">:</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">assigned</span><span class="o">:</span> <span class="kc">true</span>
|
||||
<span class="vi">@hasAssignments = </span><span class="kc">yes</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Does this scope have any declared variables?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">hasDeclarations</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="o">!!</span><span class="nx">@declaredVariables</span><span class="p">().</span><span class="nx">length</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Return the list of variables first declared in this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">declaredVariables</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nx">index</span><span class="o">++</span> <span class="k">while</span> <span class="nx">@check</span><span class="p">((</span><span class="nv">temp = </span><span class="nx">@temporary</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">index</span><span class="p">))</span>
|
||||
<span class="nx">@add</span> <span class="nx">temp</span><span class="p">,</span> <span class="s">'var'</span><span class="p">,</span> <span class="kc">yes</span> <span class="k">if</span> <span class="nx">reserve</span>
|
||||
<span class="nx">temp</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Ensure that an assignment is made at the top of this scope
|
||||
(or at the top-level scope, if requested).</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">assign: </span><span class="nf">(name, value) -></span>
|
||||
<span class="nx">@add</span> <span class="nx">name</span><span class="p">,</span> <span class="p">{</span><span class="nx">value</span><span class="p">,</span> <span class="nv">assigned: </span><span class="kc">yes</span><span class="p">},</span> <span class="kc">yes</span>
|
||||
<span class="vi">@hasAssignments = </span><span class="kc">yes</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Does this scope have any declared variables?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">hasDeclarations: </span><span class="nf">-></span>
|
||||
<span class="o">!!</span><span class="nx">@declaredVariables</span><span class="p">().</span><span class="nx">length</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>Return the list of variables first declared in this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">declaredVariables: </span><span class="nf">-></span>
|
||||
<span class="nv">realVars = </span><span class="p">[]</span>
|
||||
<span class="nv">tempVars = </span><span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="nx">v</span> <span class="k">in</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">v</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s1">'var'</span>
|
||||
<span class="p">(</span><span class="k">if</span> <span class="nx">v</span><span class="p">.</span><span class="nx">name</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'_'</span> <span class="k">then</span> <span class="nx">tempVars</span> <span class="k">else</span> <span class="nx">realVars</span><span class="p">).</span><span class="nx">push</span> <span class="nx">v</span><span class="p">.</span><span class="nx">name</span>
|
||||
<span class="nx">realVars</span><span class="p">.</span><span class="nx">sort</span><span class="p">().</span><span class="nx">concat</span> <span class="nx">tempVars</span><span class="p">.</span><span class="nx">sort</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>Return the list of assignments that are supposed to be made at the top
|
||||
of this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">assignedVariables</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="s2">"#{v.name} = #{v.type.value}"</span> <span class="k">for</span> <span class="nx">v</span> <span class="k">in</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">v</span><span class="p">.</span><span class="nx">type</span><span class="p">.</span><span class="nx">assigned</span>
|
||||
<span class="k">for</span> <span class="nx">v</span> <span class="k">in</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">v</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s">'var'</span>
|
||||
<span class="p">(</span><span class="k">if</span> <span class="nx">v</span><span class="p">.</span><span class="nx">name</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">is</span> <span class="s">'_'</span> <span class="k">then</span> <span class="nx">tempVars</span> <span class="k">else</span> <span class="nx">realVars</span><span class="p">).</span><span class="nx">push</span> <span class="nx">v</span><span class="p">.</span><span class="nx">name</span>
|
||||
<span class="nx">realVars</span><span class="p">.</span><span class="nx">sort</span><span class="p">().</span><span class="nx">concat</span> <span class="nx">tempVars</span><span class="p">.</span><span class="nx">sort</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>Return the list of assignments that are supposed to be made at the top
|
||||
of this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">assignedVariables: </span><span class="nf">-></span>
|
||||
<span class="s">"</span><span class="si">#{</span><span class="nx">v</span><span class="p">.</span><span class="nx">name</span><span class="si">}</span><span class="s"> = </span><span class="si">#{</span><span class="nx">v</span><span class="p">.</span><span class="nx">type</span><span class="p">.</span><span class="nx">value</span><span class="si">}</span><span class="s">"</span> <span class="k">for</span> <span class="nx">v</span> <span class="k">in</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">v</span><span class="p">.</span><span class="nx">type</span><span class="p">.</span><span class="nx">assigned</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
File diff suppressed because one or more lines are too long
@@ -7,6 +7,7 @@
|
||||
return '' unless File.exists?("documentation/js/#{file}.js")
|
||||
cs = File.read("documentation/coffee/#{file}.coffee")
|
||||
js = File.read("documentation/js/#{file}.js")
|
||||
js = js.sub(/^\/\/ generated.*?\n/i, '')
|
||||
cshtml = Uv.parse(cs, 'xhtml', 'coffeescript', false, 'idle', false)
|
||||
jshtml = Uv.parse(js, 'xhtml', 'javascript', false, 'idle', false)
|
||||
append = executable == true ? '' : "alert(#{executable});"
|
||||
@@ -28,6 +29,7 @@
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
|
||||
<title>CoffeeScript</title>
|
||||
<link rel="canonical" href="http://coffeescript.org" />
|
||||
<link rel="stylesheet" type="text/css" href="documentation/css/docs.css" />
|
||||
<link rel="stylesheet" type="text/css" href="documentation/css/idle.css" />
|
||||
<link rel="shortcut icon" href="documentation/images/favicon.ico" />
|
||||
@@ -44,7 +46,8 @@
|
||||
</div>
|
||||
<div class="contents menu">
|
||||
<a href="#overview">Overview</a>
|
||||
<a href="#installation">Installation and Usage</a>
|
||||
<a href="#installation">Installation</a>
|
||||
<a href="#usage">Usage</a>
|
||||
<a href="#language">Language Reference</a>
|
||||
<a href="#literals">Literals: Functions, Objects and Arrays</a>
|
||||
<a href="#lexical_scope">Lexical Scoping and Variable Safety</a>
|
||||
@@ -60,12 +63,12 @@
|
||||
<a href="#embedded">Embedded JavaScript</a>
|
||||
<a href="#switch">Switch and Try/Catch</a>
|
||||
<a href="#comparisons">Chained Comparisons</a>
|
||||
<a href="#strings">String Interpolation, Heredocs, and Block Comments</a>
|
||||
<a href="#regexes">Extended Regular Expressions</a>
|
||||
<a href="#strings">String Interpolation, Block Strings, and Block Comments</a>
|
||||
<a href="#regexes">Block Regular Expressions</a>
|
||||
<a href="#cake">Cake, and Cakefiles</a>
|
||||
<a href="#scripts">"text/coffeescript" Script Tags</a>
|
||||
<a href="#resources">Books, Screencasts, Examples and Resources</a>
|
||||
<a href="#change_log">Change Log</a>
|
||||
<a href="#changelog">Change Log</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navigation try">
|
||||
@@ -127,13 +130,13 @@
|
||||
seamlessly from CoffeeScript (and vice-versa). The compiled output is
|
||||
readable and pretty-printed, passes through
|
||||
<a href="http://www.javascriptlint.com/">JavaScript Lint</a>
|
||||
without warnings, will work in every JavaScript implementation, and tends
|
||||
without warnings, will work in every JavaScript runtime, and tends
|
||||
to run as fast or faster than the equivalent handwritten JavaScript.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Latest Version:</b>
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/1.1.3">1.1.3</a>
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/1.4.0">1.4.0</a>
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
@@ -147,7 +150,7 @@
|
||||
|
||||
<h2>
|
||||
<span id="installation" class="bookmark"></span>
|
||||
Installation and Usage
|
||||
Installation
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
@@ -173,28 +176,31 @@ npm install -g coffee-script</pre>
|
||||
<p>
|
||||
(Leave off the <tt>-g</tt> if you don't wish to install globally.)
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
If you'd prefer to install the latest master version of CoffeeScript, you
|
||||
If you'd prefer to install the latest <b>master</b> version of CoffeeScript, you
|
||||
can clone the CoffeeScript
|
||||
<a href="http://github.com/jashkenas/coffee-script">source repository</a>
|
||||
from GitHub, or download
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/master">the source</a> directly.
|
||||
To install the CoffeeScript compiler system-wide
|
||||
under <tt>/usr/local</tt>, open the directory and run:
|
||||
To install the lastest master CoffeeScript compiler with npm:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
npm install -g http://github.com/jashkenas/coffee-script/tarball/master</pre>
|
||||
|
||||
<p>
|
||||
Or, if you want to install to <tt>/usr/local</tt>, and don't want to use
|
||||
npm to manage it, open the <tt>coffee-script</tt> directory and run:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
sudo bin/cake install</pre>
|
||||
|
||||
<p>
|
||||
If installing on Ubuntu or Debian,
|
||||
<a href="http://opinionated-programmer.com/2010/12/installing-coffeescript-on-debian-or-ubuntu/">be
|
||||
careful not to use the existing out-of-date package</a>. If installing on
|
||||
Windows, your best bet is probably to run Node.js under Cygwin. If you'd
|
||||
just like to experiment, you can try the
|
||||
<a href="https://github.com/alisey/CoffeeScript-Compiler-for-Windows">CoffeeScript Compiler For Windows</a>.
|
||||
</p>
|
||||
<h2>
|
||||
<span id="usage" class="bookmark"></span>
|
||||
Usage
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
Once installed, you should have access to the <tt>coffee</tt> command,
|
||||
@@ -345,7 +351,7 @@ Expressions
|
||||
<tt>coffee -o lib/ -cw src/</tt>
|
||||
</li>
|
||||
<li>
|
||||
Start the CoffeeScript REPL:<br />
|
||||
Start the CoffeeScript REPL (<tt>Ctrl-D</tt> to exit, <tt>Ctrl-V</tt>for multi-line):<br />
|
||||
<tt>coffee</tt>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -377,7 +383,7 @@ Expressions
|
||||
ending the line will do just as well (although semicolons can still
|
||||
be used to fit multiple expressions onto a single line).
|
||||
Instead of using curly braces
|
||||
<tt>{ }</tt> to surround blocks of code in <a href="#functions">functions</a>,
|
||||
<tt>{ }</tt> to surround blocks of code in <a href="#literals">functions</a>,
|
||||
<a href="#conditionals">if-statements</a>,
|
||||
<a href="#switch">switch</a>, and <a href="#try">try/catch</a>,
|
||||
use indentation.
|
||||
@@ -496,7 +502,7 @@ Expressions
|
||||
<%= code_for('array_comprehensions') %>
|
||||
<p>
|
||||
Comprehensions should be able to handle most places where you otherwise
|
||||
would use a loop, <b>each</b>/<b>forEach</b>, <b>map</b>, or <b>select</b>/<b>filter</b>:
|
||||
would use a loop, <b>each</b>/<b>forEach</b>, <b>map</b>, or <b>select</b>/<b>filter</b>, for example:
|
||||
<tt>shortNames = (name for name in list when name.length < 5)</tt><br />
|
||||
If you know the start and end of your loop, or would like to step through
|
||||
in fixed-size increments, you can use a range to specify the start and
|
||||
@@ -526,7 +532,7 @@ Expressions
|
||||
<p>
|
||||
If you would like to iterate over just the keys that are defined on the
|
||||
object itself, by adding a <tt>hasOwnProperty</tt>
|
||||
check to avoid properties that may be interited from the prototype, use<br />
|
||||
check to avoid properties that may be inherited from the prototype, use<br />
|
||||
<tt>for own key, value of object</tt>
|
||||
</p>
|
||||
<p>
|
||||
@@ -555,6 +561,8 @@ Expressions
|
||||
Ranges can also be used to extract slices of arrays.
|
||||
With two dots (<tt>3..6</tt>), the range is inclusive (<tt>3, 4, 5, 6</tt>);
|
||||
with three dots (<tt>3...6</tt>), the range excludes the end (<tt>3, 4, 5</tt>).
|
||||
Slices indices have useful defaults. An omitted first index defaults to
|
||||
zero and an omitted second index defaults to the size of the array.
|
||||
</p>
|
||||
<%= code_for('slices', 'middle') %>
|
||||
<p>
|
||||
@@ -714,6 +722,7 @@ Expressions
|
||||
</p>
|
||||
<p>
|
||||
Constructor functions are named, to better support helpful stack traces.
|
||||
In the first class in the example below, <tt>this.constructor.name is "Animal"</tt>.
|
||||
</p>
|
||||
<%= code_for('classes', true) %>
|
||||
<p>
|
||||
@@ -780,10 +789,15 @@ Expressions
|
||||
</p>
|
||||
<%= code_for('fat_arrow') %>
|
||||
<p>
|
||||
If we had used <tt>-></tt> in the callback above, <tt>@customer</tt> would
|
||||
If we had used <tt>-></tt> in the callback above, <tt>@customer</tt> would
|
||||
have referred to the undefined "customer" property of the DOM element,
|
||||
and trying to call <tt>purchase()</tt> on it would have raised an exception.
|
||||
</p>
|
||||
<p>
|
||||
When used in a class definition, methods declared with the fat arrow will
|
||||
be automatically bound to each instance of the class when the instance is
|
||||
constructed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<span id="embedded" class="bookmark"></span>
|
||||
@@ -831,7 +845,7 @@ Expressions
|
||||
|
||||
<p>
|
||||
<span id="strings" class="bookmark"></span>
|
||||
<b class="header">String Interpolation, Heredocs, and Block Comments</b>
|
||||
<b class="header">String Interpolation, Block Strings, and Block Comments</b>
|
||||
Ruby-style string interpolation is included in CoffeeScript. Double-quoted
|
||||
strings allow for interpolated values, using <tt>#{ ... }</tt>,
|
||||
and single-quoted strings are literal.
|
||||
@@ -842,31 +856,31 @@ Expressions
|
||||
</p>
|
||||
<%= code_for('strings', 'mobyDick') %>
|
||||
<p>
|
||||
Heredocs can be used to hold formatted or indentation-sensitive text
|
||||
Block strings can be used to hold formatted or indentation-sensitive text
|
||||
(or, if you just don't feel like escaping quotes and apostrophes). The
|
||||
indentation level that begins the heredoc is maintained throughout, so
|
||||
indentation level that begins the block is maintained throughout, so
|
||||
you can keep it all aligned with the body of your code.
|
||||
</p>
|
||||
<%= code_for('heredocs', 'html') %>
|
||||
<p>
|
||||
Double-quoted heredocs, like double-quoted strings, allow interpolation.
|
||||
Double-quoted block strings, like other double-quoted strings, allow interpolation.
|
||||
</p>
|
||||
<p>
|
||||
Sometimes you'd like to pass a block comment through to the generated
|
||||
JavaScript. For example, when you need to embed a licensing header at
|
||||
the top of a file. Block comments, which mirror the syntax for heredocs,
|
||||
the top of a file. Block comments, which mirror the syntax for block strings,
|
||||
are preserved in the generated code.
|
||||
</p>
|
||||
<%= code_for('block_comment') %>
|
||||
|
||||
<p>
|
||||
<span id="regexes" class="bookmark"></span>
|
||||
<b class="header">Extended Regular Expressions</b>
|
||||
Similar to "heredocs" and "herecomments", CoffeeScript supports "heregexes" —
|
||||
<b class="header">Block Regular Expressions</b>
|
||||
Similar to block strings and comments, CoffeeScript supports block regexes —
|
||||
extended regular expressions that ignore internal whitespace and can contain
|
||||
comments, after Perl's <tt>/x</tt> modifier, but delimited by <tt>///</tt>.
|
||||
They go a long way towards making complex regular expressions readable.
|
||||
To quote from the CoffeeScript source:
|
||||
comments and interpolation. Modeled after Perl's <tt>/x</tt> modifier, CoffeeSctipt's
|
||||
block regexes are delimited by <tt>///</tt> and go a long way towards making complex
|
||||
regular expressions readable. To quote from the CoffeeScript source:
|
||||
</p>
|
||||
<%= code_for('heregexes') %>
|
||||
|
||||
@@ -935,11 +949,11 @@ Expressions
|
||||
|
||||
<h2>
|
||||
<span id="resources" class="bookmark"></span>
|
||||
Books and Screencasts
|
||||
Books
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
There are a number of excellent books and screencasts to help you get
|
||||
There are a number of excellent resources to help you get
|
||||
started with CoffeeScript, some of which are freely available online.
|
||||
</p>
|
||||
|
||||
@@ -965,6 +979,17 @@ Expressions
|
||||
a fast-paced multiplayer word game, writing both the client-side and Node.js
|
||||
portions in CoffeeScript.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
Screencasts
|
||||
</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="http://coffeescript.codeschool.com">A Sip of CoffeeScript</a> is a <a href="http://www.codeschool.com">Code School Course</a>
|
||||
which combines 6 screencasts with in-browser coding to make learning fun. The first level is free to try out.
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://peepcode.com/products/coffeescript">Meet CoffeeScript</a>
|
||||
is a 75-minute long screencast by <a href="http://peepcode.com/">PeepCode</a>.
|
||||
@@ -1064,6 +1089,11 @@ Expressions
|
||||
<a href="http://github.com/jashkenas/coffee-script/wiki/FAQ">The FAQ</a><br />
|
||||
Perhaps your CoffeeScript-related question has been asked before. Check the FAQ first.
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://github.com/jashkenas/coffee-script/downloads">High-Rez Logo</a><br />
|
||||
The CoffeeScript logo is available in Illustrator, EPS and PSD formats, for use
|
||||
in presentations.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
@@ -1082,10 +1112,137 @@ Expressions
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<span id="change_log" class="bookmark"></span>
|
||||
<span id="changelog" class="bookmark"></span>
|
||||
Change Log
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">
|
||||
<a href="https://github.com/jashkenas/coffee-script/compare/1.3.3...1.4.0">1.4.0</a>
|
||||
<span class="timestamp"> – <small>Oct 23, 2012</small></span>
|
||||
</b>
|
||||
<ul>
|
||||
<li>
|
||||
The CoffeeScript compiler now strips Microsoft's UTF-8 BOM if it
|
||||
exists, allowing you to compile BOM-borked source files.
|
||||
</li>
|
||||
<li>
|
||||
Fix Node/compiler deprecation warnings by removing <tt>registerExtension</tt>,
|
||||
and moving from <tt>path.exists</tt> to <tt>fs.exists</tt>.
|
||||
</li>
|
||||
<li>
|
||||
Small tweaks to splat compilation, backticks, slicing, and the
|
||||
error for duplicate keys in object literals.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">
|
||||
<a href="https://github.com/jashkenas/coffee-script/compare/1.3.1...1.3.3">1.3.3</a>
|
||||
<span class="timestamp"> – <small>May 15, 2012</small></span>
|
||||
</b>
|
||||
<ul>
|
||||
<li>
|
||||
Due to the new semantics of JavaScript's strict mode, CoffeeScript no
|
||||
longer guarantees that constructor functions have names in all runtimes.
|
||||
See <a href="https://github.com/jashkenas/coffee-script/issues/2052">#2052</a>
|
||||
for discussion.
|
||||
</li>
|
||||
<li>
|
||||
Inside of a nested function inside of an instance method, it's now possible
|
||||
to call <tt>super</tt> more reliably (walks recursively up).
|
||||
</li>
|
||||
<li>
|
||||
Named loop variables no longer have different scoping heuristics than
|
||||
other local variables. (Reverts #643)
|
||||
</li>
|
||||
<li>
|
||||
Fix for splats nested within the LHS of destructuring assignment.
|
||||
</li>
|
||||
<li>
|
||||
Corrections to our compile time strict mode forbidding of octal literals.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">
|
||||
<a href="https://github.com/jashkenas/coffee-script/compare/1.2.0...1.3.1">1.3.1</a>
|
||||
<span class="timestamp"> – <small>April 10, 2012</small></span>
|
||||
</b>
|
||||
<ul>
|
||||
<li>
|
||||
CoffeeScript now enforces all of JavaScript's <b>Strict Mode</b> early syntax
|
||||
errors at compile time. This includes old-style octal literals,
|
||||
duplicate property names in object literals, duplicate parameters in
|
||||
a function definition, deleting naked variables, setting the value of
|
||||
<tt>eval</tt> or <tt>arguments</tt>, and more.
|
||||
See a full discussion at
|
||||
<a href="https://github.com/jashkenas/coffee-script/issues/1547">#1547</a>.
|
||||
</li>
|
||||
<li>
|
||||
The REPL now has a handy new multi-line mode for entering large
|
||||
blocks of code. It's useful when copy-and-pasting examples into the
|
||||
REPL. Enter multi-line mode with <tt>Ctrl-V</tt>. You may also now
|
||||
pipe input directly into the REPL.
|
||||
</li>
|
||||
<li>
|
||||
CoffeeScript now prints a <tt>Generated by CoffeeScript VERSION</tt>
|
||||
header at the top of each compiled file.
|
||||
</li>
|
||||
<li>
|
||||
Conditional assignment of previously undefined variables
|
||||
<tt>a or= b</tt> is now considered a syntax error.
|
||||
</li>
|
||||
<li>
|
||||
A tweak to the semantics of <tt>do</tt>, which can now be used to
|
||||
more easily simulate a namespace: <tt>do (x = 1, y = 2) -> ...</tt>
|
||||
</li>
|
||||
<li>
|
||||
Loop indices are now mutable within a loop iteration, and immutable
|
||||
between them.
|
||||
</li>
|
||||
<li>
|
||||
Both endpoints of a slice are now allowed to be omitted for consistency,
|
||||
effectively creating a shallow copy of the list.
|
||||
</li>
|
||||
<li>
|
||||
Additional tweaks and improvments to <tt>coffee --watch</tt> under
|
||||
Node's "new" file watching API. Watch will now beep by default
|
||||
if you introduce a syntax error into a watched script. We also now
|
||||
ignore hidden directories by default when watching recursively.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">
|
||||
<a href="https://github.com/jashkenas/coffee-script/compare/1.1.3...1.2.0">1.2.0</a>
|
||||
<span class="timestamp"> – <small>Dec. 18, 2011</small></span>
|
||||
</b>
|
||||
<ul>
|
||||
<li>
|
||||
Multiple improvements to <tt>coffee --watch</tt> and <tt>--join</tt>.
|
||||
You may now use both together, as well as add and remove
|
||||
files and directories within a <tt>--watch</tt>'d folder.
|
||||
</li>
|
||||
<li>
|
||||
The <tt>throw</tt> statement can now be used as part of an expression.
|
||||
</li>
|
||||
<li>
|
||||
Block comments at the top of the file will now appear outside of the
|
||||
safety closure wrapper.
|
||||
</li>
|
||||
<li>
|
||||
Fixed a number of minor 1.1.3 regressions having to do with trailing
|
||||
operators and unfinished lines, and a more major 1.1.3 regression that
|
||||
caused bound functions <i>within</i> bound class functions to have the incorrect
|
||||
<tt>this</tt>.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">
|
||||
<a href="https://github.com/jashkenas/coffee-script/compare/1.1.2...1.1.3">1.1.3</a>
|
||||
@@ -1675,7 +1832,7 @@ Expressions
|
||||
closeMenus = ->
|
||||
$('.navigation.active').removeClass 'active'
|
||||
|
||||
$('.minibutton.run').click evalJS
|
||||
$('.minibutton.run').click -> evalJS()
|
||||
|
||||
# Bind navigation buttons to open the menus.
|
||||
$('.navigation').click (e) ->
|
||||
|
||||
@@ -1,13 +1,24 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var volume, winner;
|
||||
|
||||
if (ignition === true) launch();
|
||||
if (ignition === true) {
|
||||
launch();
|
||||
}
|
||||
|
||||
if (band !== SpinalTap) volume = 10;
|
||||
if (band !== SpinalTap) {
|
||||
volume = 10;
|
||||
}
|
||||
|
||||
if (answer !== false) letTheWildRumpusBegin();
|
||||
if (answer !== false) {
|
||||
letTheWildRumpusBegin();
|
||||
}
|
||||
|
||||
if (car.speed < limit) accelerate();
|
||||
if (car.speed < limit) {
|
||||
accelerate();
|
||||
}
|
||||
|
||||
if (pick === 47 || pick === 92 || pick === 13) winner = true;
|
||||
if (pick === 47 || pick === 92 || pick === 13) {
|
||||
winner = true;
|
||||
}
|
||||
|
||||
print(inspect("My name is " + this.name));
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
var course, courses, dish, food, foods, _i, _j, _len, _len2, _len3, _ref;
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var courses, dish, food, foods, i, _i, _j, _k, _len, _len1, _len2, _ref;
|
||||
|
||||
_ref = ['toast', 'cheese', 'wine'];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
@@ -6,16 +7,18 @@ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
eat(food);
|
||||
}
|
||||
|
||||
courses = ['salad', 'entree', 'dessert'];
|
||||
courses = ['greens', 'caviar', 'truffles', 'roast', 'cake'];
|
||||
|
||||
for (course = 0, _len2 = courses.length; course < _len2; course++) {
|
||||
dish = courses[course];
|
||||
menu(course + 1, dish);
|
||||
for (i = _j = 0, _len1 = courses.length; _j < _len1; i = ++_j) {
|
||||
dish = courses[i];
|
||||
menu(i + 1, dish);
|
||||
}
|
||||
|
||||
foods = ['broccoli', 'spinach', 'chocolate'];
|
||||
|
||||
for (_j = 0, _len3 = foods.length; _j < _len3; _j++) {
|
||||
food = foods[_j];
|
||||
if (food !== 'chocolate') eat(food);
|
||||
for (_k = 0, _len2 = foods.length; _k < _len2; _k++) {
|
||||
food = foods[_k];
|
||||
if (food !== 'chocolate') {
|
||||
eat(food);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
/*
|
||||
CoffeeScript Compiler v1.1.3
|
||||
CoffeeScript Compiler v1.4.0
|
||||
Released under the MIT License
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var fs;
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
var Animal, Horse, Snake, sam, tom;
|
||||
var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var Animal, Horse, Snake, sam, tom,
|
||||
__hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
Animal = (function() {
|
||||
|
||||
@@ -15,12 +17,12 @@ Animal = (function() {
|
||||
|
||||
})();
|
||||
|
||||
Snake = (function() {
|
||||
Snake = (function(_super) {
|
||||
|
||||
__extends(Snake, Animal);
|
||||
__extends(Snake, _super);
|
||||
|
||||
function Snake() {
|
||||
Snake.__super__.constructor.apply(this, arguments);
|
||||
return Snake.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
Snake.prototype.move = function() {
|
||||
@@ -30,14 +32,14 @@ Snake = (function() {
|
||||
|
||||
return Snake;
|
||||
|
||||
})();
|
||||
})(Animal);
|
||||
|
||||
Horse = (function() {
|
||||
Horse = (function(_super) {
|
||||
|
||||
__extends(Horse, Animal);
|
||||
__extends(Horse, _super);
|
||||
|
||||
function Horse() {
|
||||
Horse.__super__.constructor.apply(this, arguments);
|
||||
return Horse.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
Horse.prototype.move = function() {
|
||||
@@ -47,7 +49,7 @@ Horse = (function() {
|
||||
|
||||
return Horse;
|
||||
|
||||
})();
|
||||
})(Animal);
|
||||
|
||||
sam = new Snake("Sammy the Python");
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var cholesterol, healthy;
|
||||
|
||||
cholesterol = 127;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var date, mood;
|
||||
|
||||
if (singing) mood = greatlyImproved;
|
||||
if (singing) {
|
||||
mood = greatlyImproved;
|
||||
}
|
||||
|
||||
if (happy && knowsIt) {
|
||||
clapsHands();
|
||||
@@ -10,5 +13,3 @@ if (happy && knowsIt) {
|
||||
}
|
||||
|
||||
date = friday ? sue : jill;
|
||||
|
||||
options || (options = defaults);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var fill;
|
||||
|
||||
fill = function(container, liquid) {
|
||||
if (liquid == null) liquid = "coffee";
|
||||
if (liquid == null) {
|
||||
liquid = "coffee";
|
||||
}
|
||||
return "Filling the " + container + " with " + liquid + "...";
|
||||
};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var filename, _fn, _i, _len;
|
||||
|
||||
_fn = function(filename) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var hi;
|
||||
|
||||
hi = function() {
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
var footprints, solipsism;
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var footprints, solipsism, speed;
|
||||
|
||||
if ((typeof mind !== "undefined" && mind !== null) && !(typeof world !== "undefined" && world !== null)) {
|
||||
solipsism = true;
|
||||
}
|
||||
|
||||
if (typeof speed === "undefined" || speed === null) speed = 75;
|
||||
speed = 0;
|
||||
|
||||
if (speed == null) {
|
||||
speed = 15;
|
||||
}
|
||||
|
||||
footprints = typeof yeti !== "undefined" && yeti !== null ? yeti : "bear";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var eldest, grade;
|
||||
|
||||
grade = function(student) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var one, six, three, two;
|
||||
|
||||
six = (one = 1) + (two = 2) + (three = 3);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var globals, name;
|
||||
|
||||
globals = ((function() {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
|
||||
alert((function() {
|
||||
try {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var Account;
|
||||
|
||||
Account = function(customer, cart) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var cube, square;
|
||||
|
||||
square = function(x) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var html;
|
||||
|
||||
html = '<strong>\n cup of coffeescript\n</strong>';
|
||||
html = "<strong>\n cup of coffeescript\n</strong>";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var OPERATOR;
|
||||
|
||||
OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var author, quote, sentence;
|
||||
|
||||
author = "Wittgenstein";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var city, forecast, temp, weatherReport, _ref;
|
||||
|
||||
weatherReport = function(location) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var age, ages, child, yearsOld;
|
||||
|
||||
yearsOld = {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
var city, futurists, name, street, _ref, _ref2;
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var city, futurists, name, street, _ref, _ref1;
|
||||
|
||||
futurists = {
|
||||
sculptor: "Umberto Boccioni",
|
||||
@@ -9,4 +10,4 @@ futurists = {
|
||||
}
|
||||
};
|
||||
|
||||
_ref = futurists.poet, name = _ref.name, (_ref2 = _ref.address, street = _ref2[0], city = _ref2[1]);
|
||||
_ref = futurists.poet, name = _ref.name, (_ref1 = _ref.address, street = _ref1[0], city = _ref1[1]);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var bitlist, kids, singers, song;
|
||||
|
||||
song = ["do", "re", "mi", "fa", "so"];
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
|
||||
$('.account').attr({
|
||||
"class": 'active'
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
var cubes, list, math, num, number, opposite, race, square;
|
||||
var __slice = Array.prototype.slice;
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var cubes, list, math, num, number, opposite, race, square,
|
||||
__slice = [].slice;
|
||||
|
||||
number = 42;
|
||||
|
||||
opposite = true;
|
||||
|
||||
if (opposite) number = -42;
|
||||
if (opposite) {
|
||||
number = -42;
|
||||
}
|
||||
|
||||
square = function(x) {
|
||||
return x * x;
|
||||
@@ -27,7 +30,9 @@ race = function() {
|
||||
return print(winner, runners);
|
||||
};
|
||||
|
||||
if (typeof elvis !== "undefined" && elvis !== null) alert("I knew it!");
|
||||
if (typeof elvis !== "undefined" && elvis !== null) {
|
||||
alert("I knew it!");
|
||||
}
|
||||
|
||||
cubes = (function() {
|
||||
var _i, _len, _results;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var theBait, theSwitch, _ref;
|
||||
|
||||
theBait = 1000;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
var close, contents, open, tag, _i, _ref;
|
||||
var __slice = Array.prototype.slice;
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var close, contents, open, tag, _i, _ref,
|
||||
__slice = [].slice;
|
||||
|
||||
tag = "<impossible>";
|
||||
|
||||
|
||||
1
documentation/js/prototypes.js
vendored
1
documentation/js/prototypes.js
vendored
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
|
||||
String.prototype.dasherize = function() {
|
||||
return this.replace(/_/g, "-");
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var countdown, num;
|
||||
|
||||
countdown = (function() {
|
||||
var _results;
|
||||
var _i, _results;
|
||||
_results = [];
|
||||
for (num = 10; num >= 1; num--) {
|
||||
for (num = _i = 10; _i >= 1; num = --_i) {
|
||||
_results.push(num);
|
||||
}
|
||||
return _results;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var changeNumbers, inner, outer;
|
||||
|
||||
outer = 1;
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
var copy, middle, numbers;
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var copy, end, middle, numbers, start;
|
||||
|
||||
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
|
||||
copy = numbers.slice(0, numbers.length);
|
||||
start = numbers.slice(0, 3);
|
||||
|
||||
middle = copy.slice(3, 7);
|
||||
middle = numbers.slice(3, 6);
|
||||
|
||||
end = numbers.slice(6);
|
||||
|
||||
copy = numbers.slice(0);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var zip, _ref;
|
||||
|
||||
zip = typeof lottery.drawWinner === "function" ? (_ref = lottery.drawWinner().address) != null ? _ref.zipcode : void 0 : void 0;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
var awardMedals, contenders, gold, rest, silver;
|
||||
var __slice = Array.prototype.slice;
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var awardMedals, contenders, gold, rest, silver,
|
||||
__slice = [].slice;
|
||||
|
||||
gold = silver = rest = "unknown";
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var numbers, _ref;
|
||||
|
||||
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var mobyDick;
|
||||
|
||||
mobyDick = "Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
|
||||
switch (day) {
|
||||
case "Mon":
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
|
||||
try {
|
||||
allHellBreaksLoose();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
var lyrics, num;
|
||||
|
||||
if (this.studyingEconomics) {
|
||||
|
||||
@@ -8,7 +8,7 @@ get '/hello', ->
|
||||
# Append.
|
||||
append = (location, data) ->
|
||||
path = new Pathname location
|
||||
throw new Error("Location does not exist") unless path.exists()
|
||||
throw new Error "Location does not exist" unless fs.existsSync(location)
|
||||
|
||||
File.open path, 'a', (file) ->
|
||||
file.console.log YAML.dump data
|
||||
@@ -31,7 +31,7 @@ File.open = (path, mode, block) ->
|
||||
# Write.
|
||||
write = (location, data) ->
|
||||
path = new Pathname location
|
||||
raise "Location does not exist" unless path.exists()
|
||||
throw new Error "Location does not exist" unless fs.existsSync(location)
|
||||
|
||||
File.open path, 'w', (file) ->
|
||||
return false if Digest.MD5.hexdigest(file.read()) is data.hash()
|
||||
|
||||
File diff suppressed because one or more lines are too long
484
index.html
484
index.html
@@ -6,6 +6,7 @@
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
|
||||
<title>CoffeeScript</title>
|
||||
<link rel="canonical" href="http://coffeescript.org" />
|
||||
<link rel="stylesheet" type="text/css" href="documentation/css/docs.css" />
|
||||
<link rel="stylesheet" type="text/css" href="documentation/css/idle.css" />
|
||||
<link rel="shortcut icon" href="documentation/images/favicon.ico" />
|
||||
@@ -22,7 +23,8 @@
|
||||
</div>
|
||||
<div class="contents menu">
|
||||
<a href="#overview">Overview</a>
|
||||
<a href="#installation">Installation and Usage</a>
|
||||
<a href="#installation">Installation</a>
|
||||
<a href="#usage">Usage</a>
|
||||
<a href="#language">Language Reference</a>
|
||||
<a href="#literals">Literals: Functions, Objects and Arrays</a>
|
||||
<a href="#lexical_scope">Lexical Scoping and Variable Safety</a>
|
||||
@@ -38,12 +40,12 @@
|
||||
<a href="#embedded">Embedded JavaScript</a>
|
||||
<a href="#switch">Switch and Try/Catch</a>
|
||||
<a href="#comparisons">Chained Comparisons</a>
|
||||
<a href="#strings">String Interpolation, Heredocs, and Block Comments</a>
|
||||
<a href="#regexes">Extended Regular Expressions</a>
|
||||
<a href="#strings">String Interpolation, Block Strings, and Block Comments</a>
|
||||
<a href="#regexes">Block Regular Expressions</a>
|
||||
<a href="#cake">Cake, and Cakefiles</a>
|
||||
<a href="#scripts">"text/coffeescript" Script Tags</a>
|
||||
<a href="#resources">Books, Screencasts, Examples and Resources</a>
|
||||
<a href="#change_log">Change Log</a>
|
||||
<a href="#changelog">Change Log</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navigation try">
|
||||
@@ -105,13 +107,13 @@
|
||||
seamlessly from CoffeeScript (and vice-versa). The compiled output is
|
||||
readable and pretty-printed, passes through
|
||||
<a href="http://www.javascriptlint.com/">JavaScript Lint</a>
|
||||
without warnings, will work in every JavaScript implementation, and tends
|
||||
without warnings, will work in every JavaScript runtime, and tends
|
||||
to run as fast or faster than the equivalent handwritten JavaScript.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Latest Version:</b>
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/1.1.3">1.1.3</a>
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/1.4.0">1.4.0</a>
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
@@ -149,14 +151,16 @@ alert <span class="String"><span class="String">"</span>I knew it!<span cla
|
||||
|
||||
<span class="Comment"><span class="Comment">#</span> Array comprehensions:</span>
|
||||
cubes <span class="Keyword">=</span> (math.cube num <span class="Keyword">for</span> num <span class="Keyword">in</span> list)
|
||||
</pre><pre class="idle"><span class="Storage">var</span> cubes, list, math, num, number, opposite, race, square;
|
||||
<span class="Storage">var</span> __slice <span class="Keyword">=</span> <span class="LibraryClassType">Array</span>.<span class="LibraryConstant">prototype</span>.slice;
|
||||
</pre><pre class="idle"><span class="Storage">var</span> cubes, list, math, num, number, opposite, race, square,
|
||||
__slice <span class="Keyword">=</span> [].slice;
|
||||
|
||||
number <span class="Keyword">=</span> <span class="Number">42</span>;
|
||||
|
||||
opposite <span class="Keyword">=</span> <span class="BuiltInConstant">true</span>;
|
||||
|
||||
<span class="Keyword">if</span> (opposite) number <span class="Keyword">=</span> <span class="Keyword">-</span><span class="Number">42</span>;
|
||||
<span class="Keyword">if</span> (opposite) {
|
||||
number <span class="Keyword">=</span> <span class="Keyword">-</span><span class="Number">42</span>;
|
||||
}
|
||||
|
||||
<span class="FunctionName">square</span> = <span class="Storage">function</span>(<span class="FunctionArgument">x</span>) {
|
||||
<span class="Keyword">return</span> x <span class="Keyword">*</span> x;
|
||||
@@ -178,7 +182,9 @@ math <span class="Keyword">=</span> {
|
||||
<span class="Keyword">return</span> <span class="LibraryFunction">print</span>(winner, runners);
|
||||
};
|
||||
|
||||
<span class="Keyword">if</span> (<span class="Keyword">typeof</span> elvis <span class="Keyword">!</span><span class="Keyword">==</span> <span class="String"><span class="String">"</span>undefined<span class="String">"</span></span> <span class="Keyword">&</span><span class="Keyword">&</span> elvis <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">null</span>) <span class="LibraryFunction">alert</span>(<span class="String"><span class="String">"</span>I knew it!<span class="String">"</span></span>);
|
||||
<span class="Keyword">if</span> (<span class="Keyword">typeof</span> elvis <span class="Keyword">!</span><span class="Keyword">==</span> <span class="String"><span class="String">"</span>undefined<span class="String">"</span></span> <span class="Keyword">&</span><span class="Keyword">&</span> elvis <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">null</span>) {
|
||||
<span class="LibraryFunction">alert</span>(<span class="String"><span class="String">"</span>I knew it!<span class="String">"</span></span>);
|
||||
}
|
||||
|
||||
cubes <span class="Keyword">=</span> (<span class="Storage">function</span>() {
|
||||
<span class="Storage">var</span> _i, _len, _results;
|
||||
@@ -189,14 +195,16 @@ cubes <span class="Keyword">=</span> (<span class="Storage">function</span>() {
|
||||
}
|
||||
<span class="Keyword">return</span> _results;
|
||||
})();
|
||||
</pre><script>window.example1 = "# Assignment:\nnumber = 42\nopposite = true\n\n# Conditions:\nnumber = -42 if opposite\n\n# Functions:\nsquare = (x) -> x * x\n\n# Arrays:\nlist = [1, 2, 3, 4, 5]\n\n# Objects:\nmath =\n root: Math.sqrt\n square: square\n cube: (x) -> x * square x\n\n# Splats:\nrace = (winner, runners...) ->\n print winner, runners\n\n# Existence:\nalert \"I knew it!\" if elvis?\n\n# Array comprehensions:\ncubes = (math.cube num for num in list)\n\nalert cubes"</script><div class='minibutton ok' onclick='javascript: var cubes, list, math, num, number, opposite, race, square;
|
||||
var __slice = Array.prototype.slice;
|
||||
</pre><script>window.example1 = "# Assignment:\nnumber = 42\nopposite = true\n\n# Conditions:\nnumber = -42 if opposite\n\n# Functions:\nsquare = (x) -> x * x\n\n# Arrays:\nlist = [1, 2, 3, 4, 5]\n\n# Objects:\nmath =\n root: Math.sqrt\n square: square\n cube: (x) -> x * square x\n\n# Splats:\nrace = (winner, runners...) ->\n print winner, runners\n\n# Existence:\nalert \"I knew it!\" if elvis?\n\n# Array comprehensions:\ncubes = (math.cube num for num in list)\n\nalert cubes"</script><div class='minibutton ok' onclick='javascript: var cubes, list, math, num, number, opposite, race, square,
|
||||
__slice = [].slice;
|
||||
|
||||
number = 42;
|
||||
|
||||
opposite = true;
|
||||
|
||||
if (opposite) number = -42;
|
||||
if (opposite) {
|
||||
number = -42;
|
||||
}
|
||||
|
||||
square = function(x) {
|
||||
return x * x;
|
||||
@@ -218,7 +226,9 @@ race = function() {
|
||||
return print(winner, runners);
|
||||
};
|
||||
|
||||
if (typeof elvis !== "undefined" && elvis !== null) alert("I knew it!");
|
||||
if (typeof elvis !== "undefined" && elvis !== null) {
|
||||
alert("I knew it!");
|
||||
}
|
||||
|
||||
cubes = (function() {
|
||||
var _i, _len, _results;
|
||||
@@ -233,7 +243,7 @@ cubes = (function() {
|
||||
|
||||
<h2>
|
||||
<span id="installation" class="bookmark"></span>
|
||||
Installation and Usage
|
||||
Installation
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
@@ -259,28 +269,31 @@ npm install -g coffee-script</pre>
|
||||
<p>
|
||||
(Leave off the <tt>-g</tt> if you don't wish to install globally.)
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
If you'd prefer to install the latest master version of CoffeeScript, you
|
||||
If you'd prefer to install the latest <b>master</b> version of CoffeeScript, you
|
||||
can clone the CoffeeScript
|
||||
<a href="http://github.com/jashkenas/coffee-script">source repository</a>
|
||||
from GitHub, or download
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/master">the source</a> directly.
|
||||
To install the CoffeeScript compiler system-wide
|
||||
under <tt>/usr/local</tt>, open the directory and run:
|
||||
To install the lastest master CoffeeScript compiler with npm:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
npm install -g http://github.com/jashkenas/coffee-script/tarball/master</pre>
|
||||
|
||||
<p>
|
||||
Or, if you want to install to <tt>/usr/local</tt>, and don't want to use
|
||||
npm to manage it, open the <tt>coffee-script</tt> directory and run:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
sudo bin/cake install</pre>
|
||||
|
||||
<p>
|
||||
If installing on Ubuntu or Debian,
|
||||
<a href="http://opinionated-programmer.com/2010/12/installing-coffeescript-on-debian-or-ubuntu/">be
|
||||
careful not to use the existing out-of-date package</a>. If installing on
|
||||
Windows, your best bet is probably to run Node.js under Cygwin. If you'd
|
||||
just like to experiment, you can try the
|
||||
<a href="https://github.com/alisey/CoffeeScript-Compiler-for-Windows">CoffeeScript Compiler For Windows</a>.
|
||||
</p>
|
||||
<h2>
|
||||
<span id="usage" class="bookmark"></span>
|
||||
Usage
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
Once installed, you should have access to the <tt>coffee</tt> command,
|
||||
@@ -431,7 +444,7 @@ Expressions
|
||||
<tt>coffee -o lib/ -cw src/</tt>
|
||||
</li>
|
||||
<li>
|
||||
Start the CoffeeScript REPL:<br />
|
||||
Start the CoffeeScript REPL (<tt>Ctrl-D</tt> to exit, <tt>Ctrl-V</tt>for multi-line):<br />
|
||||
<tt>coffee</tt>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -463,7 +476,7 @@ Expressions
|
||||
ending the line will do just as well (although semicolons can still
|
||||
be used to fit multiple expressions onto a single line).
|
||||
Instead of using curly braces
|
||||
<tt>{ }</tt> to surround blocks of code in <a href="#functions">functions</a>,
|
||||
<tt>{ }</tt> to surround blocks of code in <a href="#literals">functions</a>,
|
||||
<a href="#conditionals">if-statements</a>,
|
||||
<a href="#switch">switch</a>, and <a href="#try">try/catch</a>,
|
||||
use indentation.
|
||||
@@ -518,13 +531,17 @@ cube = function(x) {
|
||||
</pre><pre class="idle"><span class="Storage">var</span> fill;
|
||||
|
||||
<span class="FunctionName">fill</span> = <span class="Storage">function</span>(<span class="FunctionArgument">container, liquid</span>) {
|
||||
<span class="Keyword">if</span> (liquid <span class="Keyword">==</span> <span class="BuiltInConstant">null</span>) liquid <span class="Keyword">=</span> <span class="String"><span class="String">"</span>coffee<span class="String">"</span></span>;
|
||||
<span class="Keyword">if</span> (liquid <span class="Keyword">==</span> <span class="BuiltInConstant">null</span>) {
|
||||
liquid <span class="Keyword">=</span> <span class="String"><span class="String">"</span>coffee<span class="String">"</span></span>;
|
||||
}
|
||||
<span class="Keyword">return</span> <span class="String"><span class="String">"</span>Filling the <span class="String">"</span></span> <span class="Keyword">+</span> container <span class="Keyword">+</span> <span class="String"><span class="String">"</span> with <span class="String">"</span></span> <span class="Keyword">+</span> liquid <span class="Keyword">+</span> <span class="String"><span class="String">"</span>...<span class="String">"</span></span>;
|
||||
};
|
||||
</pre><script>window.example3 = "fill = (container, liquid = \"coffee\") ->\n \"Filling the #{container} with #{liquid}...\"\n\nalert fill(\"cup\")"</script><div class='minibutton load' onclick='javascript: loadConsole(example3);'>load</div><div class='minibutton ok' onclick='javascript: var fill;
|
||||
|
||||
fill = function(container, liquid) {
|
||||
if (liquid == null) liquid = "coffee";
|
||||
if (liquid == null) {
|
||||
liquid = "coffee";
|
||||
}
|
||||
return "Filling the " + container + " with " + liquid + "...";
|
||||
};
|
||||
;alert(fill("cup"));'>run: fill("cup")</div><br class='clear' /></div>
|
||||
@@ -707,12 +724,13 @@ inner = changeNumbers();
|
||||
|
||||
date <span class="Keyword">=</span> <span class="Keyword">if</span> friday <span class="Keyword">then</span> sue <span class="Keyword">else</span> jill
|
||||
|
||||
options <span class="Keyword">or=</span> defaults
|
||||
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> date, mood;
|
||||
|
||||
<span class="Keyword">if</span> (singing) mood <span class="Keyword">=</span> greatlyImproved;
|
||||
<span class="Keyword">if</span> (singing) {
|
||||
mood <span class="Keyword">=</span> greatlyImproved;
|
||||
}
|
||||
|
||||
<span class="Keyword">if</span> (happy <span class="Keyword">&</span><span class="Keyword">&</span> knowsIt) {
|
||||
clapsHands();
|
||||
@@ -722,9 +740,7 @@ options <span class="Keyword">or=</span> defaults
|
||||
}
|
||||
|
||||
date <span class="Keyword">=</span> friday ? sue : jill;
|
||||
|
||||
options <span class="Keyword">||</span> (options <span class="Keyword">=</span> defaults);
|
||||
</pre><script>window.example7 = "mood = greatlyImproved if singing\n\nif happy and knowsIt\n clapsHands()\n chaChaCha()\nelse\n showIt()\n\ndate = if friday then sue else jill\n\noptions or= defaults\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example7);'>load</div><br class='clear' /></div>
|
||||
</pre><script>window.example7 = "mood = greatlyImproved if singing\n\nif happy and knowsIt\n clapsHands()\n chaChaCha()\nelse\n showIt()\n\ndate = if friday then sue else jill\n\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example7);'>load</div><br class='clear' /></div>
|
||||
|
||||
<p>
|
||||
<span id="splats" class="bookmark"></span>
|
||||
@@ -761,8 +777,8 @@ alert <span class="String"><span class="String">"</span>Silver: <span class
|
||||
alert <span class="String"><span class="String">"</span>The Field: <span class="String">"</span></span> <span class="Keyword">+</span> rest
|
||||
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> awardMedals, contenders, gold, rest, silver;
|
||||
<span class="Storage">var</span> __slice <span class="Keyword">=</span> <span class="LibraryClassType">Array</span>.<span class="LibraryConstant">prototype</span>.slice;
|
||||
</pre><pre class="idle"><span class="Storage">var</span> awardMedals, contenders, gold, rest, silver,
|
||||
__slice <span class="Keyword">=</span> [].slice;
|
||||
|
||||
gold <span class="Keyword">=</span> silver <span class="Keyword">=</span> rest <span class="Keyword">=</span> <span class="String"><span class="String">"</span>unknown<span class="String">"</span></span>;
|
||||
|
||||
@@ -783,8 +799,8 @@ awardMedals.<span class="LibraryFunction">apply</span>(<span class="BuiltInConst
|
||||
<span class="LibraryFunction">alert</span>(<span class="String"><span class="String">"</span>Silver: <span class="String">"</span></span> <span class="Keyword">+</span> silver);
|
||||
|
||||
<span class="LibraryFunction">alert</span>(<span class="String"><span class="String">"</span>The Field: <span class="String">"</span></span> <span class="Keyword">+</span> rest);
|
||||
</pre><script>window.example8 = "gold = silver = rest = \"unknown\"\n\nawardMedals = (first, second, others...) ->\n gold = first\n silver = second\n rest = others\n\ncontenders = [\n \"Michael Phelps\"\n \"Liu Xiang\"\n \"Yao Ming\"\n \"Allyson Felix\"\n \"Shawn Johnson\"\n \"Roman Sebrle\"\n \"Guo Jingjing\"\n \"Tyson Gay\"\n \"Asafa Powell\"\n \"Usain Bolt\"\n]\n\nawardMedals contenders...\n\nalert \"Gold: \" + gold\nalert \"Silver: \" + silver\nalert \"The Field: \" + rest\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example8);'>load</div><div class='minibutton ok' onclick='javascript: var awardMedals, contenders, gold, rest, silver;
|
||||
var __slice = Array.prototype.slice;
|
||||
</pre><script>window.example8 = "gold = silver = rest = \"unknown\"\n\nawardMedals = (first, second, others...) ->\n gold = first\n silver = second\n rest = others\n\ncontenders = [\n \"Michael Phelps\"\n \"Liu Xiang\"\n \"Yao Ming\"\n \"Allyson Felix\"\n \"Shawn Johnson\"\n \"Roman Sebrle\"\n \"Guo Jingjing\"\n \"Tyson Gay\"\n \"Asafa Powell\"\n \"Usain Bolt\"\n]\n\nawardMedals contenders...\n\nalert \"Gold: \" + gold\nalert \"Silver: \" + silver\nalert \"The Field: \" + rest\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example8);'>load</div><div class='minibutton ok' onclick='javascript: var awardMedals, contenders, gold, rest, silver,
|
||||
__slice = [].slice;
|
||||
|
||||
gold = silver = rest = "unknown";
|
||||
|
||||
@@ -819,14 +835,14 @@ alert("The Field: " + rest);
|
||||
<div class='code'><pre class="idle"><span class="Comment"><span class="Comment">#</span> Eat lunch.</span>
|
||||
eat food <span class="Keyword">for</span> food <span class="Keyword">in</span> [<span class="String"><span class="String">'</span>toast<span class="String">'</span></span>, <span class="String"><span class="String">'</span>cheese<span class="String">'</span></span>, <span class="String"><span class="String">'</span>wine<span class="String">'</span></span>]
|
||||
|
||||
<span class="Comment"><span class="Comment">#</span> Fine dining</span>
|
||||
courses <span class="Keyword">=</span> [<span class="String"><span class="String">'</span>salad<span class="String">'</span></span>, <span class="String"><span class="String">'</span>entree<span class="String">'</span></span>, <span class="String"><span class="String">'</span>dessert<span class="String">'</span></span>]
|
||||
menu course <span class="Keyword">+</span> <span class="Number">1</span>, dish <span class="Keyword">for</span> dish, course <span class="Keyword">in</span> courses
|
||||
<span class="Comment"><span class="Comment">#</span> Fine five course dining.</span>
|
||||
courses <span class="Keyword">=</span> [<span class="String"><span class="String">'</span>greens<span class="String">'</span></span>, <span class="String"><span class="String">'</span>caviar<span class="String">'</span></span>, <span class="String"><span class="String">'</span>truffles<span class="String">'</span></span>, <span class="String"><span class="String">'</span>roast<span class="String">'</span></span>, <span class="String"><span class="String">'</span>cake<span class="String">'</span></span>]
|
||||
menu i <span class="Keyword">+</span> <span class="Number">1</span>, dish <span class="Keyword">for</span> dish, i <span class="Keyword">in</span> courses
|
||||
|
||||
<span class="Comment"><span class="Comment">#</span> Health conscious meal</span>
|
||||
<span class="Comment"><span class="Comment">#</span> Health conscious meal.</span>
|
||||
foods <span class="Keyword">=</span> [<span class="String"><span class="String">'</span>broccoli<span class="String">'</span></span>, <span class="String"><span class="String">'</span>spinach<span class="String">'</span></span>, <span class="String"><span class="String">'</span>chocolate<span class="String">'</span></span>]
|
||||
eat food <span class="Keyword">for</span> food <span class="Keyword">in</span> foods <span class="Keyword">when</span> food <span class="Keyword">isnt</span> <span class="String"><span class="String">'</span>chocolate<span class="String">'</span></span>
|
||||
</pre><pre class="idle"><span class="Storage">var</span> course, courses, dish, food, foods, _i, _j, _len, _len2, _len3, _ref;
|
||||
</pre><pre class="idle"><span class="Storage">var</span> courses, dish, food, foods, i, _i, _j, _k, _len, _len1, _len2, _ref;
|
||||
|
||||
_ref <span class="Keyword">=</span> [<span class="String"><span class="String">'</span>toast<span class="String">'</span></span>, <span class="String"><span class="String">'</span>cheese<span class="String">'</span></span>, <span class="String"><span class="String">'</span>wine<span class="String">'</span></span>];
|
||||
<span class="Keyword">for</span> (_i <span class="Keyword">=</span> <span class="Number">0</span>, _len <span class="Keyword">=</span> _ref.<span class="LibraryConstant">length</span>; _i <span class="Keyword"><</span> _len; _i<span class="Keyword">++</span>) {
|
||||
@@ -834,23 +850,25 @@ _ref <span class="Keyword">=</span> [<span class="String"><span class="String">'
|
||||
eat(food);
|
||||
}
|
||||
|
||||
courses <span class="Keyword">=</span> [<span class="String"><span class="String">'</span>salad<span class="String">'</span></span>, <span class="String"><span class="String">'</span>entree<span class="String">'</span></span>, <span class="String"><span class="String">'</span>dessert<span class="String">'</span></span>];
|
||||
courses <span class="Keyword">=</span> [<span class="String"><span class="String">'</span>greens<span class="String">'</span></span>, <span class="String"><span class="String">'</span>caviar<span class="String">'</span></span>, <span class="String"><span class="String">'</span>truffles<span class="String">'</span></span>, <span class="String"><span class="String">'</span>roast<span class="String">'</span></span>, <span class="String"><span class="String">'</span>cake<span class="String">'</span></span>];
|
||||
|
||||
<span class="Keyword">for</span> (course <span class="Keyword">=</span> <span class="Number">0</span>, _len2 <span class="Keyword">=</span> courses.<span class="LibraryConstant">length</span>; course <span class="Keyword"><</span> _len2; course<span class="Keyword">++</span>) {
|
||||
dish <span class="Keyword">=</span> courses[course];
|
||||
menu(course <span class="Keyword">+</span> <span class="Number">1</span>, dish);
|
||||
<span class="Keyword">for</span> (i <span class="Keyword">=</span> _j <span class="Keyword">=</span> <span class="Number">0</span>, _len1 <span class="Keyword">=</span> courses.<span class="LibraryConstant">length</span>; _j <span class="Keyword"><</span> _len1; i <span class="Keyword">=</span> <span class="Keyword">++</span>_j) {
|
||||
dish <span class="Keyword">=</span> courses[i];
|
||||
menu(i <span class="Keyword">+</span> <span class="Number">1</span>, dish);
|
||||
}
|
||||
|
||||
foods <span class="Keyword">=</span> [<span class="String"><span class="String">'</span>broccoli<span class="String">'</span></span>, <span class="String"><span class="String">'</span>spinach<span class="String">'</span></span>, <span class="String"><span class="String">'</span>chocolate<span class="String">'</span></span>];
|
||||
|
||||
<span class="Keyword">for</span> (_j <span class="Keyword">=</span> <span class="Number">0</span>, _len3 <span class="Keyword">=</span> foods.<span class="LibraryConstant">length</span>; _j <span class="Keyword"><</span> _len3; _j<span class="Keyword">++</span>) {
|
||||
food <span class="Keyword">=</span> foods[_j];
|
||||
<span class="Keyword">if</span> (food <span class="Keyword">!</span><span class="Keyword">==</span> <span class="String"><span class="String">'</span>chocolate<span class="String">'</span></span>) eat(food);
|
||||
<span class="Keyword">for</span> (_k <span class="Keyword">=</span> <span class="Number">0</span>, _len2 <span class="Keyword">=</span> foods.<span class="LibraryConstant">length</span>; _k <span class="Keyword"><</span> _len2; _k<span class="Keyword">++</span>) {
|
||||
food <span class="Keyword">=</span> foods[_k];
|
||||
<span class="Keyword">if</span> (food <span class="Keyword">!</span><span class="Keyword">==</span> <span class="String"><span class="String">'</span>chocolate<span class="String">'</span></span>) {
|
||||
eat(food);
|
||||
}
|
||||
}
|
||||
</pre><script>window.example9 = "# Eat lunch.\neat food for food in ['toast', 'cheese', 'wine']\n\n# Fine dining\ncourses = ['salad', 'entree', 'dessert']\nmenu course + 1, dish for dish, course in courses\n\n# Health conscious meal\nfoods = ['broccoli', 'spinach', 'chocolate']\neat food for food in foods when food isnt 'chocolate'\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example9);'>load</div><br class='clear' /></div>
|
||||
</pre><script>window.example9 = "# Eat lunch.\neat food for food in ['toast', 'cheese', 'wine']\n\n# Fine five course dining.\ncourses = ['greens', 'caviar', 'truffles', 'roast', 'cake']\nmenu i + 1, dish for dish, i in courses\n\n# Health conscious meal.\nfoods = ['broccoli', 'spinach', 'chocolate']\neat food for food in foods when food isnt 'chocolate'\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example9);'>load</div><br class='clear' /></div>
|
||||
<p>
|
||||
Comprehensions should be able to handle most places where you otherwise
|
||||
would use a loop, <b>each</b>/<b>forEach</b>, <b>map</b>, or <b>select</b>/<b>filter</b>:
|
||||
would use a loop, <b>each</b>/<b>forEach</b>, <b>map</b>, or <b>select</b>/<b>filter</b>, for example:
|
||||
<tt>shortNames = (name for name in list when name.length < 5)</tt><br />
|
||||
If you know the start and end of your loop, or would like to step through
|
||||
in fixed-size increments, you can use a range to specify the start and
|
||||
@@ -861,9 +879,9 @@ foods <span class="Keyword">=</span> [<span class="String"><span class="String">
|
||||
</pre><pre class="idle"><span class="Storage">var</span> countdown, num;
|
||||
|
||||
countdown <span class="Keyword">=</span> (<span class="Storage">function</span>() {
|
||||
<span class="Storage">var</span> _results;
|
||||
<span class="Storage">var</span> _i, _results;
|
||||
_results <span class="Keyword">=</span> [];
|
||||
<span class="Keyword">for</span> (num <span class="Keyword">=</span> <span class="Number">10</span>; num <span class="Keyword">>=</span> <span class="Number">1</span>; num<span class="Keyword">--</span>) {
|
||||
<span class="Keyword">for</span> (num <span class="Keyword">=</span> _i <span class="Keyword">=</span> <span class="Number">10</span>; _i <span class="Keyword">>=</span> <span class="Number">1</span>; num <span class="Keyword">=</span> <span class="Keyword">--</span>_i) {
|
||||
_results.<span class="LibraryFunction">push</span>(num);
|
||||
}
|
||||
<span class="Keyword">return</span> _results;
|
||||
@@ -871,9 +889,9 @@ countdown <span class="Keyword">=</span> (<span class="Storage">function</span>(
|
||||
</pre><script>window.example10 = "countdown = (num for num in [10..1])\n\nalert countdown"</script><div class='minibutton load' onclick='javascript: loadConsole(example10);'>load</div><div class='minibutton ok' onclick='javascript: var countdown, num;
|
||||
|
||||
countdown = (function() {
|
||||
var _results;
|
||||
var _i, _results;
|
||||
_results = [];
|
||||
for (num = 10; num >= 1; num--) {
|
||||
for (num = _i = 10; _i >= 1; num = --_i) {
|
||||
_results.push(num);
|
||||
}
|
||||
return _results;
|
||||
@@ -940,7 +958,7 @@ ages = (function() {
|
||||
<p>
|
||||
If you would like to iterate over just the keys that are defined on the
|
||||
object itself, by adding a <tt>hasOwnProperty</tt>
|
||||
check to avoid properties that may be interited from the prototype, use<br />
|
||||
check to avoid properties that may be inherited from the prototype, use<br />
|
||||
<tt>for own key, value of object</tt>
|
||||
</p>
|
||||
<p>
|
||||
@@ -1036,28 +1054,40 @@ lyrics = (function() {
|
||||
Ranges can also be used to extract slices of arrays.
|
||||
With two dots (<tt>3..6</tt>), the range is inclusive (<tt>3, 4, 5, 6</tt>);
|
||||
with three dots (<tt>3...6</tt>), the range excludes the end (<tt>3, 4, 5</tt>).
|
||||
Slices indices have useful defaults. An omitted first index defaults to
|
||||
zero and an omitted second index defaults to the size of the array.
|
||||
</p>
|
||||
<div class='code'><pre class="idle">numbers <span class="Keyword">=</span> [<span class="Number">0</span>, <span class="Number">1</span>, <span class="Number">2</span>, <span class="Number">3</span>, <span class="Number">4</span>, <span class="Number">5</span>, <span class="Number">6</span>, <span class="Number">7</span>, <span class="Number">8</span>, <span class="Number">9</span>]
|
||||
<div class='code'><pre class="idle">numbers <span class="Keyword">=</span> [<span class="Number">1</span>, <span class="Number">2</span>, <span class="Number">3</span>, <span class="Number">4</span>, <span class="Number">5</span>, <span class="Number">6</span>, <span class="Number">7</span>, <span class="Number">8</span>, <span class="Number">9</span>]
|
||||
|
||||
copy <span class="Keyword">=</span> numbers[<span class="Number">0</span>...numbers.length]
|
||||
start <span class="Keyword">=</span> numbers[<span class="Number">0</span>..<span class="Number">2</span>]
|
||||
|
||||
middle <span class="Keyword">=</span> copy[<span class="Number">3</span>..<span class="Number">6</span>]
|
||||
middle <span class="Keyword">=</span> numbers[<span class="Number">3</span>...<span class="Number">6</span>]
|
||||
|
||||
end <span class="Keyword">=</span> numbers[<span class="Number">6</span>..]
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> copy, middle, numbers;
|
||||
copy <span class="Keyword">=</span> numbers[..]
|
||||
</pre><pre class="idle"><span class="Storage">var</span> copy, end, middle, numbers, start;
|
||||
|
||||
numbers <span class="Keyword">=</span> [<span class="Number">0</span>, <span class="Number">1</span>, <span class="Number">2</span>, <span class="Number">3</span>, <span class="Number">4</span>, <span class="Number">5</span>, <span class="Number">6</span>, <span class="Number">7</span>, <span class="Number">8</span>, <span class="Number">9</span>];
|
||||
numbers <span class="Keyword">=</span> [<span class="Number">1</span>, <span class="Number">2</span>, <span class="Number">3</span>, <span class="Number">4</span>, <span class="Number">5</span>, <span class="Number">6</span>, <span class="Number">7</span>, <span class="Number">8</span>, <span class="Number">9</span>];
|
||||
|
||||
copy <span class="Keyword">=</span> numbers.<span class="LibraryFunction">slice</span>(<span class="Number">0</span>, numbers.<span class="LibraryConstant">length</span>);
|
||||
start <span class="Keyword">=</span> numbers.<span class="LibraryFunction">slice</span>(<span class="Number">0</span>, <span class="Number">3</span>);
|
||||
|
||||
middle <span class="Keyword">=</span> copy.<span class="LibraryFunction">slice</span>(<span class="Number">3</span>, <span class="Number">7</span>);
|
||||
</pre><script>window.example14 = "numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n\ncopy = numbers[0...numbers.length]\n\nmiddle = copy[3..6]\n\nalert middle"</script><div class='minibutton load' onclick='javascript: loadConsole(example14);'>load</div><div class='minibutton ok' onclick='javascript: var copy, middle, numbers;
|
||||
middle <span class="Keyword">=</span> numbers.<span class="LibraryFunction">slice</span>(<span class="Number">3</span>, <span class="Number">6</span>);
|
||||
|
||||
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
end <span class="Keyword">=</span> numbers.<span class="LibraryFunction">slice</span>(<span class="Number">6</span>);
|
||||
|
||||
copy = numbers.slice(0, numbers.length);
|
||||
copy <span class="Keyword">=</span> numbers.<span class="LibraryFunction">slice</span>(<span class="Number">0</span>);
|
||||
</pre><script>window.example14 = "numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]\n\nstart = numbers[0..2]\n\nmiddle = numbers[3...6]\n\nend = numbers[6..]\n\ncopy = numbers[..]\n\nalert middle"</script><div class='minibutton load' onclick='javascript: loadConsole(example14);'>load</div><div class='minibutton ok' onclick='javascript: var copy, end, middle, numbers, start;
|
||||
|
||||
middle = copy.slice(3, 7);
|
||||
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
|
||||
start = numbers.slice(0, 3);
|
||||
|
||||
middle = numbers.slice(3, 6);
|
||||
|
||||
end = numbers.slice(6);
|
||||
|
||||
copy = numbers.slice(0);
|
||||
;alert(middle);'>run: middle</div><br class='clear' /></div>
|
||||
<p>
|
||||
The same syntax can be used with assignment to replace a segment of an array
|
||||
@@ -1068,6 +1098,8 @@ middle = copy.slice(3, 7);
|
||||
numbers[<span class="Number">3</span>..<span class="Number">6</span>] <span class="Keyword">=</span> [<span class="Keyword">-</span><span class="Number">3</span>, <span class="Keyword">-</span><span class="Number">4</span>, <span class="Keyword">-</span><span class="Number">5</span>, <span class="Keyword">-</span><span class="Number">6</span>]
|
||||
|
||||
|
||||
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> numbers, _ref;
|
||||
|
||||
numbers <span class="Keyword">=</span> [<span class="Number">0</span>, <span class="Number">1</span>, <span class="Number">2</span>, <span class="Number">3</span>, <span class="Number">4</span>, <span class="Number">5</span>, <span class="Number">6</span>, <span class="Number">7</span>, <span class="Number">8</span>, <span class="Number">9</span>];
|
||||
@@ -1288,15 +1320,25 @@ winner <span class="Keyword">=</span> <span class="BuiltInConstant">yes</span> <
|
||||
print inspect <span class="String"><span class="String">"</span>My name is <span class="String"><span class="String">#{</span><span class="Variable">@name</span><span class="String">}</span></span><span class="String">"</span></span>
|
||||
</pre><pre class="idle"><span class="Storage">var</span> volume, winner;
|
||||
|
||||
<span class="Keyword">if</span> (ignition <span class="Keyword">===</span> <span class="BuiltInConstant">true</span>) launch();
|
||||
<span class="Keyword">if</span> (ignition <span class="Keyword">===</span> <span class="BuiltInConstant">true</span>) {
|
||||
launch();
|
||||
}
|
||||
|
||||
<span class="Keyword">if</span> (band <span class="Keyword">!</span><span class="Keyword">==</span> SpinalTap) volume <span class="Keyword">=</span> <span class="Number">10</span>;
|
||||
<span class="Keyword">if</span> (band <span class="Keyword">!</span><span class="Keyword">==</span> SpinalTap) {
|
||||
volume <span class="Keyword">=</span> <span class="Number">10</span>;
|
||||
}
|
||||
|
||||
<span class="Keyword">if</span> (answer <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">false</span>) letTheWildRumpusBegin();
|
||||
<span class="Keyword">if</span> (answer <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">false</span>) {
|
||||
letTheWildRumpusBegin();
|
||||
}
|
||||
|
||||
<span class="Keyword">if</span> (car.speed <span class="Keyword"><</span> limit) accelerate();
|
||||
<span class="Keyword">if</span> (car.speed <span class="Keyword"><</span> limit) {
|
||||
accelerate();
|
||||
}
|
||||
|
||||
<span class="Keyword">if</span> (pick <span class="Keyword">===</span> <span class="Number">47</span> <span class="Keyword">||</span> pick <span class="Keyword">===</span> <span class="Number">92</span> <span class="Keyword">||</span> pick <span class="Keyword">===</span> <span class="Number">13</span>) winner <span class="Keyword">=</span> <span class="BuiltInConstant">true</span>;
|
||||
<span class="Keyword">if</span> (pick <span class="Keyword">===</span> <span class="Number">47</span> <span class="Keyword">||</span> pick <span class="Keyword">===</span> <span class="Number">92</span> <span class="Keyword">||</span> pick <span class="Keyword">===</span> <span class="Number">13</span>) {
|
||||
winner <span class="Keyword">=</span> <span class="BuiltInConstant">true</span>;
|
||||
}
|
||||
|
||||
<span class="LibraryFunction">print</span>(inspect(<span class="String"><span class="String">"</span>My name is <span class="String">"</span></span> <span class="Keyword">+</span> <span class="Variable">this</span>.<span class="LibraryConstant">name</span>));
|
||||
</pre><script>window.example20 = "launch() if ignition is on\n\nvolume = 10 if band isnt SpinalTap\n\nletTheWildRumpusBegin() unless answer is no\n\nif car.speed < limit then accelerate()\n\nwinner = yes if pick in [47, 92, 13]\n\nprint inspect \"My name is #{@name}\"\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example20);'>load</div><br class='clear' /></div>
|
||||
@@ -1315,7 +1357,8 @@ print inspect <span class="String"><span class="String">"</span>My name is
|
||||
</p>
|
||||
<div class='code'><pre class="idle">solipsism <span class="Keyword">=</span> <span class="BuiltInConstant">true</span> <span class="Keyword">if</span> mind<span class="Keyword">?</span> <span class="Keyword">and</span> <span class="Keyword">not</span> world<span class="Keyword">?</span>
|
||||
|
||||
speed <span class="Keyword">?</span><span class="Keyword">=</span> <span class="Number">75</span>
|
||||
speed <span class="Keyword">=</span> <span class="Number">0</span>
|
||||
speed <span class="Keyword">?</span><span class="Keyword">=</span> <span class="Number">15</span>
|
||||
|
||||
footprints <span class="Keyword">=</span> yeti <span class="Keyword">?</span> <span class="String"><span class="String">"</span>bear<span class="String">"</span></span>
|
||||
|
||||
@@ -1323,22 +1366,32 @@ footprints <span class="Keyword">=</span> yeti <span class="Keyword">?</span> <s
|
||||
|
||||
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> footprints, solipsism;
|
||||
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> footprints, solipsism, speed;
|
||||
|
||||
<span class="Keyword">if</span> ((<span class="Keyword">typeof</span> mind <span class="Keyword">!</span><span class="Keyword">==</span> <span class="String"><span class="String">"</span>undefined<span class="String">"</span></span> <span class="Keyword">&</span><span class="Keyword">&</span> mind <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">null</span>) <span class="Keyword">&</span><span class="Keyword">&</span> <span class="Keyword">!</span>(<span class="Keyword">typeof</span> world <span class="Keyword">!</span><span class="Keyword">==</span> <span class="String"><span class="String">"</span>undefined<span class="String">"</span></span> <span class="Keyword">&</span><span class="Keyword">&</span> world <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">null</span>)) {
|
||||
solipsism <span class="Keyword">=</span> <span class="BuiltInConstant">true</span>;
|
||||
}
|
||||
|
||||
<span class="Keyword">if</span> (<span class="Keyword">typeof</span> speed <span class="Keyword">===</span> <span class="String"><span class="String">"</span>undefined<span class="String">"</span></span> <span class="Keyword">||</span> speed <span class="Keyword">===</span> <span class="BuiltInConstant">null</span>) speed <span class="Keyword">=</span> <span class="Number">75</span>;
|
||||
speed <span class="Keyword">=</span> <span class="Number">0</span>;
|
||||
|
||||
<span class="Keyword">if</span> (speed <span class="Keyword">==</span> <span class="BuiltInConstant">null</span>) {
|
||||
speed <span class="Keyword">=</span> <span class="Number">15</span>;
|
||||
}
|
||||
|
||||
footprints <span class="Keyword">=</span> <span class="Keyword">typeof</span> yeti <span class="Keyword">!</span><span class="Keyword">==</span> <span class="String"><span class="String">"</span>undefined<span class="String">"</span></span> <span class="Keyword">&</span><span class="Keyword">&</span> yeti <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">null</span> ? yeti : <span class="String"><span class="String">"</span>bear<span class="String">"</span></span>;
|
||||
</pre><script>window.example21 = "solipsism = true if mind? and not world?\n\nspeed ?= 75\n\nfootprints = yeti ? \"bear\"\n\nalert footprints"</script><div class='minibutton load' onclick='javascript: loadConsole(example21);'>load</div><div class='minibutton ok' onclick='javascript: var footprints, solipsism;
|
||||
</pre><script>window.example21 = "solipsism = true if mind? and not world?\n\nspeed = 0\nspeed ?= 15\n\nfootprints = yeti ? \"bear\"\n\nalert footprints"</script><div class='minibutton load' onclick='javascript: loadConsole(example21);'>load</div><div class='minibutton ok' onclick='javascript: var footprints, solipsism, speed;
|
||||
|
||||
if ((typeof mind !== "undefined" && mind !== null) && !(typeof world !== "undefined" && world !== null)) {
|
||||
solipsism = true;
|
||||
}
|
||||
|
||||
if (typeof speed === "undefined" || speed === null) speed = 75;
|
||||
speed = 0;
|
||||
|
||||
if (speed == null) {
|
||||
speed = 15;
|
||||
}
|
||||
|
||||
footprints = typeof yeti !== "undefined" && yeti !== null ? yeti : "bear";
|
||||
;alert(footprints);'>run: footprints</div><br class='clear' /></div>
|
||||
@@ -1385,6 +1438,7 @@ zip <span class="Keyword">=</span> <span class="Keyword">typeof</span> lottery.d
|
||||
</p>
|
||||
<p>
|
||||
Constructor functions are named, to better support helpful stack traces.
|
||||
In the first class in the example below, <tt>this.constructor.name is "Animal"</tt>.
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="Storage">class</span> <span class="TypeName">Animal</span>
|
||||
<span class="FunctionName">constructor</span><span class="Keyword">:</span> <span class="FunctionArgument">(@name)</span> <span class="Storage">-></span>
|
||||
@@ -1411,8 +1465,9 @@ tom.move()
|
||||
|
||||
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> Animal, Horse, Snake, sam, tom;
|
||||
<span class="Storage">var</span> __hasProp <span class="Keyword">=</span> <span class="LibraryClassType">Object</span>.<span class="LibraryConstant">prototype</span>.hasOwnProperty, <span class="FunctionName">__extends</span> = <span class="Storage">function</span>(<span class="FunctionArgument">child, parent</span>) { <span class="Keyword">for</span> (<span class="Storage">var</span> key <span class="Keyword">in</span> parent) { <span class="Keyword">if</span> (__hasProp.<span class="LibraryFunction">call</span>(parent, key)) child[key] <span class="Keyword">=</span> parent[key]; } <span class="Storage">function</span> <span class="FunctionName">ctor</span>() { <span class="Variable">this</span>.<span class="LibraryConstant">constructor</span> <span class="Keyword">=</span> child; } <span class="LibraryClassType">ctor</span>.<span class="LibraryConstant">prototype</span> = parent.<span class="LibraryConstant">prototype</span>; <span class="LibraryClassType">child</span>.<span class="LibraryConstant">prototype</span> = <span class="Keyword">new</span> <span class="TypeName">ctor</span>; child.__super__ <span class="Keyword">=</span> parent.<span class="LibraryConstant">prototype</span>; <span class="Keyword">return</span> child; };
|
||||
</pre><pre class="idle"><span class="Storage">var</span> Animal, Horse, Snake, sam, tom,
|
||||
__hasProp <span class="Keyword">=</span> {}.hasOwnProperty,
|
||||
<span class="FunctionName">__extends</span> = <span class="Storage">function</span>(<span class="FunctionArgument">child, parent</span>) { <span class="Keyword">for</span> (<span class="Storage">var</span> key <span class="Keyword">in</span> parent) { <span class="Keyword">if</span> (__hasProp.<span class="LibraryFunction">call</span>(parent, key)) child[key] <span class="Keyword">=</span> parent[key]; } <span class="Storage">function</span> <span class="FunctionName">ctor</span>() { <span class="Variable">this</span>.<span class="LibraryConstant">constructor</span> <span class="Keyword">=</span> child; } <span class="LibraryClassType">ctor</span>.<span class="LibraryConstant">prototype</span> = parent.<span class="LibraryConstant">prototype</span>; <span class="LibraryClassType">child</span>.<span class="LibraryConstant">prototype</span> = <span class="Keyword">new</span> <span class="TypeName">ctor</span>(); child.__super__ <span class="Keyword">=</span> parent.<span class="LibraryConstant">prototype</span>; <span class="Keyword">return</span> child; };
|
||||
|
||||
Animal <span class="Keyword">=</span> (<span class="Storage">function</span>() {
|
||||
|
||||
@@ -1428,12 +1483,12 @@ Animal <span class="Keyword">=</span> (<span class="Storage">function</span>() {
|
||||
|
||||
})();
|
||||
|
||||
Snake <span class="Keyword">=</span> (<span class="Storage">function</span>() {
|
||||
Snake <span class="Keyword">=</span> (<span class="Storage">function</span>(_super) {
|
||||
|
||||
__extends(Snake, Animal);
|
||||
__extends(Snake, _super);
|
||||
|
||||
<span class="Storage">function</span> <span class="FunctionName">Snake</span>() {
|
||||
Snake.__super__.<span class="LibraryConstant">constructor</span>.<span class="LibraryFunction">apply</span>(<span class="Variable">this</span>, arguments);
|
||||
<span class="Keyword">return</span> Snake.__super__.<span class="LibraryConstant">constructor</span>.<span class="LibraryFunction">apply</span>(<span class="Variable">this</span>, arguments);
|
||||
}
|
||||
|
||||
<span class="LibraryClassType">Snake</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">move</span> = <span class="Storage">function</span>() {
|
||||
@@ -1443,14 +1498,14 @@ Snake <span class="Keyword">=</span> (<span class="Storage">function</span>() {
|
||||
|
||||
<span class="Keyword">return</span> Snake;
|
||||
|
||||
})();
|
||||
})(Animal);
|
||||
|
||||
Horse <span class="Keyword">=</span> (<span class="Storage">function</span>() {
|
||||
Horse <span class="Keyword">=</span> (<span class="Storage">function</span>(_super) {
|
||||
|
||||
__extends(Horse, Animal);
|
||||
__extends(Horse, _super);
|
||||
|
||||
<span class="Storage">function</span> <span class="FunctionName">Horse</span>() {
|
||||
Horse.__super__.<span class="LibraryConstant">constructor</span>.<span class="LibraryFunction">apply</span>(<span class="Variable">this</span>, arguments);
|
||||
<span class="Keyword">return</span> Horse.__super__.<span class="LibraryConstant">constructor</span>.<span class="LibraryFunction">apply</span>(<span class="Variable">this</span>, arguments);
|
||||
}
|
||||
|
||||
<span class="LibraryClassType">Horse</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">move</span> = <span class="Storage">function</span>() {
|
||||
@@ -1460,7 +1515,7 @@ Horse <span class="Keyword">=</span> (<span class="Storage">function</span>() {
|
||||
|
||||
<span class="Keyword">return</span> Horse;
|
||||
|
||||
})();
|
||||
})(Animal);
|
||||
|
||||
sam <span class="Keyword">=</span> <span class="Keyword">new</span> <span class="TypeName">Snake</span>(<span class="String"><span class="String">"</span>Sammy the Python<span class="String">"</span></span>);
|
||||
|
||||
@@ -1469,8 +1524,9 @@ tom <span class="Keyword">=</span> <span class="Keyword">new</span> <span class=
|
||||
sam.move();
|
||||
|
||||
tom.move();
|
||||
</pre><script>window.example23 = "class Animal\n constructor: (@name) ->\n\n move: (meters) ->\n alert @name + \" moved #{meters}m.\"\n\nclass Snake extends Animal\n move: ->\n alert \"Slithering...\"\n super 5\n\nclass Horse extends Animal\n move: ->\n alert \"Galloping...\"\n super 45\n\nsam = new Snake \"Sammy the Python\"\ntom = new Horse \"Tommy the Palomino\"\n\nsam.move()\ntom.move()\n\n\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example23);'>load</div><div class='minibutton ok' onclick='javascript: var Animal, Horse, Snake, sam, tom;
|
||||
var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
|
||||
</pre><script>window.example23 = "class Animal\n constructor: (@name) ->\n\n move: (meters) ->\n alert @name + \" moved #{meters}m.\"\n\nclass Snake extends Animal\n move: ->\n alert \"Slithering...\"\n super 5\n\nclass Horse extends Animal\n move: ->\n alert \"Galloping...\"\n super 45\n\nsam = new Snake \"Sammy the Python\"\ntom = new Horse \"Tommy the Palomino\"\n\nsam.move()\ntom.move()\n\n\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example23);'>load</div><div class='minibutton ok' onclick='javascript: var Animal, Horse, Snake, sam, tom,
|
||||
__hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
Animal = (function() {
|
||||
|
||||
@@ -1486,12 +1542,12 @@ Animal = (function() {
|
||||
|
||||
})();
|
||||
|
||||
Snake = (function() {
|
||||
Snake = (function(_super) {
|
||||
|
||||
__extends(Snake, Animal);
|
||||
__extends(Snake, _super);
|
||||
|
||||
function Snake() {
|
||||
Snake.__super__.constructor.apply(this, arguments);
|
||||
return Snake.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
Snake.prototype.move = function() {
|
||||
@@ -1501,14 +1557,14 @@ Snake = (function() {
|
||||
|
||||
return Snake;
|
||||
|
||||
})();
|
||||
})(Animal);
|
||||
|
||||
Horse = (function() {
|
||||
Horse = (function(_super) {
|
||||
|
||||
__extends(Horse, Animal);
|
||||
__extends(Horse, _super);
|
||||
|
||||
function Horse() {
|
||||
Horse.__super__.constructor.apply(this, arguments);
|
||||
return Horse.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
Horse.prototype.move = function() {
|
||||
@@ -1518,7 +1574,7 @@ Horse = (function() {
|
||||
|
||||
return Horse;
|
||||
|
||||
})();
|
||||
})(Animal);
|
||||
|
||||
sam = new Snake("Sammy the Python");
|
||||
|
||||
@@ -1573,6 +1629,9 @@ theSwitch <span class="Keyword">=</span> <span class="Number">0</span>
|
||||
<span class="Keyword">[</span>theBait, theSwitch<span class="Keyword">] =</span> [theSwitch, theBait]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> theBait, theSwitch, _ref;
|
||||
|
||||
theBait <span class="Keyword">=</span> <span class="Number">1000</span>;
|
||||
@@ -1599,6 +1658,8 @@ _ref = [theSwitch, theBait], theBait = _ref[0], theSwitch = _ref[1];
|
||||
<span class="Keyword">[</span>city, temp, forecast<span class="Keyword">] =</span> weatherReport <span class="String"><span class="String">"</span>Berkeley, CA<span class="String">"</span></span>
|
||||
|
||||
|
||||
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> city, forecast, temp, weatherReport, _ref;
|
||||
|
||||
<span class="FunctionName">weatherReport</span> = <span class="Storage">function</span>(<span class="FunctionArgument">location</span>) {
|
||||
@@ -1631,7 +1692,8 @@ _ref = weatherReport("Berkeley, CA"), city = _ref[0], temp = _ref[1], forecast =
|
||||
<span class="Keyword">{</span>poet: {name, address: [street, city]}<span class="Keyword">} =</span> futurists
|
||||
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> city, futurists, name, street, _ref, _ref2;
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> city, futurists, name, street, _ref, _ref1;
|
||||
|
||||
futurists <span class="Keyword">=</span> {
|
||||
sculptor: <span class="String"><span class="String">"</span>Umberto Boccioni<span class="String">"</span></span>,
|
||||
@@ -1642,8 +1704,8 @@ futurists <span class="Keyword">=</span> {
|
||||
}
|
||||
};
|
||||
|
||||
_ref <span class="Keyword">=</span> futurists.poet, name <span class="Keyword">=</span> _ref.<span class="LibraryConstant">name</span>, (_ref2 <span class="Keyword">=</span> _ref.address, street <span class="Keyword">=</span> _ref2[<span class="Number">0</span>], city <span class="Keyword">=</span> _ref2[<span class="Number">1</span>]);
|
||||
</pre><script>window.example27 = "futurists =\n sculptor: \"Umberto Boccioni\"\n painter: \"Vladimir Burliuk\"\n poet:\n name: \"F.T. Marinetti\"\n address: [\n \"Via Roma 42R\"\n \"Bellagio, Italy 22021\"\n ]\n\n{poet: {name, address: [street, city]}} = futurists\n\nalert name + \" — \" + street"</script><div class='minibutton load' onclick='javascript: loadConsole(example27);'>load</div><div class='minibutton ok' onclick='javascript: var city, futurists, name, street, _ref, _ref2;
|
||||
_ref <span class="Keyword">=</span> futurists.poet, name <span class="Keyword">=</span> _ref.<span class="LibraryConstant">name</span>, (_ref1 <span class="Keyword">=</span> _ref.address, street <span class="Keyword">=</span> _ref1[<span class="Number">0</span>], city <span class="Keyword">=</span> _ref1[<span class="Number">1</span>]);
|
||||
</pre><script>window.example27 = "futurists =\n sculptor: \"Umberto Boccioni\"\n painter: \"Vladimir Burliuk\"\n poet:\n name: \"F.T. Marinetti\"\n address: [\n \"Via Roma 42R\"\n \"Bellagio, Italy 22021\"\n ]\n\n{poet: {name, address: [street, city]}} = futurists\n\nalert name + \" — \" + street"</script><div class='minibutton load' onclick='javascript: loadConsole(example27);'>load</div><div class='minibutton ok' onclick='javascript: var city, futurists, name, street, _ref, _ref1;
|
||||
|
||||
futurists = {
|
||||
sculptor: "Umberto Boccioni",
|
||||
@@ -1654,7 +1716,7 @@ futurists = {
|
||||
}
|
||||
};
|
||||
|
||||
_ref = futurists.poet, name = _ref.name, (_ref2 = _ref.address, street = _ref2[0], city = _ref2[1]);
|
||||
_ref = futurists.poet, name = _ref.name, (_ref1 = _ref.address, street = _ref1[0], city = _ref1[1]);
|
||||
;alert(name + " — " + street);'>run: name + " — " + street</div><br class='clear' /></div>
|
||||
<p>
|
||||
Destructuring assignment can even be combined with splats.
|
||||
@@ -1666,14 +1728,16 @@ _ref = futurists.poet, name = _ref.name, (_ref2 = _ref.address, street = _ref2[0
|
||||
|
||||
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> close, contents, open, tag, _i, _ref;
|
||||
<span class="Storage">var</span> __slice <span class="Keyword">=</span> <span class="LibraryClassType">Array</span>.<span class="LibraryConstant">prototype</span>.slice;
|
||||
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> close, contents, open, tag, _i, _ref,
|
||||
__slice <span class="Keyword">=</span> [].slice;
|
||||
|
||||
tag <span class="Keyword">=</span> <span class="String"><span class="String">"</span><impossible><span class="String">"</span></span>;
|
||||
|
||||
_ref <span class="Keyword">=</span> tag.<span class="LibraryFunction">split</span>(<span class="String"><span class="String">"</span><span class="String">"</span></span>), open <span class="Keyword">=</span> _ref[<span class="Number">0</span>], contents <span class="Keyword">=</span> <span class="Number">3</span> <span class="Keyword"><=</span> _ref.<span class="LibraryConstant">length</span> ? __slice.<span class="LibraryFunction">call</span>(_ref, <span class="Number">1</span>, _i <span class="Keyword">=</span> _ref.<span class="LibraryConstant">length</span> <span class="Keyword">-</span> <span class="Number">1</span>) : (_i <span class="Keyword">=</span> <span class="Number">1</span>, []), close <span class="Keyword">=</span> _ref[_i<span class="Keyword">++</span>];
|
||||
</pre><script>window.example28 = "tag = \"<impossible>\"\n\n[open, contents..., close] = tag.split(\"\")\n\nalert contents.join(\"\")"</script><div class='minibutton load' onclick='javascript: loadConsole(example28);'>load</div><div class='minibutton ok' onclick='javascript: var close, contents, open, tag, _i, _ref;
|
||||
var __slice = Array.prototype.slice;
|
||||
</pre><script>window.example28 = "tag = \"<impossible>\"\n\n[open, contents..., close] = tag.split(\"\")\n\nalert contents.join(\"\")"</script><div class='minibutton load' onclick='javascript: loadConsole(example28);'>load</div><div class='minibutton ok' onclick='javascript: var close, contents, open, tag, _i, _ref,
|
||||
__slice = [].slice;
|
||||
|
||||
tag = "<impossible>";
|
||||
|
||||
@@ -1716,10 +1780,15 @@ _ref = tag.split(""), open = _ref[0], contents = 3 <= _ref.length ? __slice.call
|
||||
};
|
||||
</pre><script>window.example29 = "Account = (customer, cart) ->\n @customer = customer\n @cart = cart\n\n $('.shopping_cart').bind 'click', (event) =>\n @customer.purchase @cart"</script><div class='minibutton load' onclick='javascript: loadConsole(example29);'>load</div><br class='clear' /></div>
|
||||
<p>
|
||||
If we had used <tt>-></tt> in the callback above, <tt>@customer</tt> would
|
||||
If we had used <tt>-></tt> in the callback above, <tt>@customer</tt> would
|
||||
have referred to the undefined "customer" property of the DOM element,
|
||||
and trying to call <tt>purchase()</tt> on it would have raised an exception.
|
||||
</p>
|
||||
<p>
|
||||
When used in a class definition, methods declared with the fat arrow will
|
||||
be automatically bound to each instance of the class when the instance is
|
||||
constructed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<span id="embedded" class="bookmark"></span>
|
||||
@@ -1733,6 +1802,7 @@ _ref = tag.split(""), open = _ref[0], contents = 3 <= _ref.length ? __slice.call
|
||||
<span class="String">}<span class="String">`</span></span>
|
||||
|
||||
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> hi;
|
||||
|
||||
<span class="FunctionName">hi</span> = <span class="Storage">function</span>() {
|
||||
@@ -1848,7 +1918,7 @@ healthy = (200 > cholesterol && cholesterol > 60);
|
||||
|
||||
<p>
|
||||
<span id="strings" class="bookmark"></span>
|
||||
<b class="header">String Interpolation, Heredocs, and Block Comments</b>
|
||||
<b class="header">String Interpolation, Block Strings, and Block Comments</b>
|
||||
Ruby-style string interpolation is included in CoffeeScript. Double-quoted
|
||||
strings allow for interpolated values, using <tt>#{ ... }</tt>,
|
||||
and single-quoted strings are literal.
|
||||
@@ -1859,6 +1929,9 @@ quote <span class="Keyword">=</span> <span class="String"><span class="String">
|
||||
sentence <span class="Keyword">=</span> <span class="String"><span class="String">"</span><span class="String"><span class="String">#{</span> <span class="Number">22</span> <span class="Keyword">/</span> <span class="Number">7</span> <span class="String">}</span></span> is a decent approximation of π<span class="String">"</span></span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> author, quote, sentence;
|
||||
|
||||
author <span class="Keyword">=</span> <span class="String"><span class="String">"</span>Wittgenstein<span class="String">"</span></span>;
|
||||
@@ -1893,57 +1966,55 @@ mobyDick <span class="Keyword">=</span> <span class="String"><span class="String
|
||||
mobyDick = "Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...";
|
||||
;alert(mobyDick);'>run: mobyDick</div><br class='clear' /></div>
|
||||
<p>
|
||||
Heredocs can be used to hold formatted or indentation-sensitive text
|
||||
Block strings can be used to hold formatted or indentation-sensitive text
|
||||
(or, if you just don't feel like escaping quotes and apostrophes). The
|
||||
indentation level that begins the heredoc is maintained throughout, so
|
||||
indentation level that begins the block is maintained throughout, so
|
||||
you can keep it all aligned with the body of your code.
|
||||
</p>
|
||||
<div class='code'><pre class="idle">html <span class="Keyword">=</span> <span class="String"><span class="String">'''</span></span>
|
||||
<div class='code'><pre class="idle">html <span class="Keyword">=</span> <span class="String"><span class="String">"""</span></span>
|
||||
<span class="String"> <strong></span>
|
||||
<span class="String"> cup of coffeescript</span>
|
||||
<span class="String"> </strong></span>
|
||||
<span class="String"> <span class="String">'''</span></span>
|
||||
|
||||
|
||||
<span class="String"> <span class="String">"""</span></span>
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> html;
|
||||
|
||||
html <span class="Keyword">=</span> <span class="String"><span class="String">'</span><strong><span class="UserDefinedConstant">\n</span> cup of coffeescript<span class="UserDefinedConstant">\n</span></strong><span class="String">'</span></span>;
|
||||
</pre><script>window.example36 = "html = '''\n <strong>\n cup of coffeescript\n </strong>\n '''\n\nalert html"</script><div class='minibutton load' onclick='javascript: loadConsole(example36);'>load</div><div class='minibutton ok' onclick='javascript: var html;
|
||||
html <span class="Keyword">=</span> <span class="String"><span class="String">"</span><strong><span class="UserDefinedConstant">\n</span> cup of coffeescript<span class="UserDefinedConstant">\n</span></strong><span class="String">"</span></span>;
|
||||
</pre><script>window.example36 = "html = \"\"\"\n <strong>\n cup of coffeescript\n </strong>\n \"\"\"\n\nalert html"</script><div class='minibutton load' onclick='javascript: loadConsole(example36);'>load</div><div class='minibutton ok' onclick='javascript: var html;
|
||||
|
||||
html = '<strong>\n cup of coffeescript\n</strong>';
|
||||
html = "<strong>\n cup of coffeescript\n</strong>";
|
||||
;alert(html);'>run: html</div><br class='clear' /></div>
|
||||
<p>
|
||||
Double-quoted heredocs, like double-quoted strings, allow interpolation.
|
||||
Double-quoted block strings, like other double-quoted strings, allow interpolation.
|
||||
</p>
|
||||
<p>
|
||||
Sometimes you'd like to pass a block comment through to the generated
|
||||
JavaScript. For example, when you need to embed a licensing header at
|
||||
the top of a file. Block comments, which mirror the syntax for heredocs,
|
||||
the top of a file. Block comments, which mirror the syntax for block strings,
|
||||
are preserved in the generated code.
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="Comment"><span class="Comment">###</span></span>
|
||||
<span class="Comment">CoffeeScript Compiler v1.1.3</span>
|
||||
<span class="Comment">CoffeeScript Compiler v1.4.0</span>
|
||||
<span class="Comment">Released under the MIT License</span>
|
||||
<span class="Comment"><span class="Comment">###</span></span>
|
||||
|
||||
|
||||
</pre><pre class="idle">
|
||||
<span class="Comment"><span class="Comment">/*</span></span>
|
||||
<span class="Comment">CoffeeScript Compiler v1.1.3</span>
|
||||
</pre><pre class="idle"><span class="Comment"><span class="Comment">/*</span></span>
|
||||
<span class="Comment">CoffeeScript Compiler v1.4.0</span>
|
||||
<span class="Comment">Released under the MIT License</span>
|
||||
<span class="Comment"><span class="Comment">*/</span></span>
|
||||
|
||||
|
||||
</pre><script>window.example37 = "###\nCoffeeScript Compiler v1.1.3\nReleased under the MIT License\n###\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example37);'>load</div><br class='clear' /></div>
|
||||
</pre><script>window.example37 = "###\nCoffeeScript Compiler v1.4.0\nReleased under the MIT License\n###\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example37);'>load</div><br class='clear' /></div>
|
||||
|
||||
<p>
|
||||
<span id="regexes" class="bookmark"></span>
|
||||
<b class="header">Extended Regular Expressions</b>
|
||||
Similar to "heredocs" and "herecomments", CoffeeScript supports "heregexes" —
|
||||
<b class="header">Block Regular Expressions</b>
|
||||
Similar to block strings and comments, CoffeeScript supports block regexes —
|
||||
extended regular expressions that ignore internal whitespace and can contain
|
||||
comments, after Perl's <tt>/x</tt> modifier, but delimited by <tt>///</tt>.
|
||||
They go a long way towards making complex regular expressions readable.
|
||||
To quote from the CoffeeScript source:
|
||||
comments and interpolation. Modeled after Perl's <tt>/x</tt> modifier, CoffeeSctipt's
|
||||
block regexes are delimited by <tt>///</tt> and go a long way towards making complex
|
||||
regular expressions readable. To quote from the CoffeeScript source:
|
||||
</p>
|
||||
<div class='code'><pre class="idle">OPERATOR <span class="Keyword">=</span> <span class="String">/// ^ (</span>
|
||||
<span class="String"> ?: [-=]> <span class="Comment"><span class="Comment">#</span> function</span></span>
|
||||
@@ -2048,11 +2119,11 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
|
||||
<h2>
|
||||
<span id="resources" class="bookmark"></span>
|
||||
Books and Screencasts
|
||||
Books
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
There are a number of excellent books and screencasts to help you get
|
||||
There are a number of excellent resources to help you get
|
||||
started with CoffeeScript, some of which are freely available online.
|
||||
</p>
|
||||
|
||||
@@ -2078,6 +2149,17 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
a fast-paced multiplayer word game, writing both the client-side and Node.js
|
||||
portions in CoffeeScript.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
Screencasts
|
||||
</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="http://coffeescript.codeschool.com">A Sip of CoffeeScript</a> is a <a href="http://www.codeschool.com">Code School Course</a>
|
||||
which combines 6 screencasts with in-browser coding to make learning fun. The first level is free to try out.
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://peepcode.com/products/coffeescript">Meet CoffeeScript</a>
|
||||
is a 75-minute long screencast by <a href="http://peepcode.com/">PeepCode</a>.
|
||||
@@ -2177,6 +2259,11 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
<a href="http://github.com/jashkenas/coffee-script/wiki/FAQ">The FAQ</a><br />
|
||||
Perhaps your CoffeeScript-related question has been asked before. Check the FAQ first.
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://github.com/jashkenas/coffee-script/downloads">High-Rez Logo</a><br />
|
||||
The CoffeeScript logo is available in Illustrator, EPS and PSD formats, for use
|
||||
in presentations.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
@@ -2195,10 +2282,137 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<span id="change_log" class="bookmark"></span>
|
||||
<span id="changelog" class="bookmark"></span>
|
||||
Change Log
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">
|
||||
<a href="https://github.com/jashkenas/coffee-script/compare/1.3.3...1.4.0">1.4.0</a>
|
||||
<span class="timestamp"> – <small>Oct 23, 2012</small></span>
|
||||
</b>
|
||||
<ul>
|
||||
<li>
|
||||
The CoffeeScript compiler now strips Microsoft's UTF-8 BOM if it
|
||||
exists, allowing you to compile BOM-borked source files.
|
||||
</li>
|
||||
<li>
|
||||
Fix Node/compiler deprecation warnings by removing <tt>registerExtension</tt>,
|
||||
and moving from <tt>path.exists</tt> to <tt>fs.exists</tt>.
|
||||
</li>
|
||||
<li>
|
||||
Small tweaks to splat compilation, backticks, slicing, and the
|
||||
error for duplicate keys in object literals.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">
|
||||
<a href="https://github.com/jashkenas/coffee-script/compare/1.3.1...1.3.3">1.3.3</a>
|
||||
<span class="timestamp"> – <small>May 15, 2012</small></span>
|
||||
</b>
|
||||
<ul>
|
||||
<li>
|
||||
Due to the new semantics of JavaScript's strict mode, CoffeeScript no
|
||||
longer guarantees that constructor functions have names in all runtimes.
|
||||
See <a href="https://github.com/jashkenas/coffee-script/issues/2052">#2052</a>
|
||||
for discussion.
|
||||
</li>
|
||||
<li>
|
||||
Inside of a nested function inside of an instance method, it's now possible
|
||||
to call <tt>super</tt> more reliably (walks recursively up).
|
||||
</li>
|
||||
<li>
|
||||
Named loop variables no longer have different scoping heuristics than
|
||||
other local variables. (Reverts #643)
|
||||
</li>
|
||||
<li>
|
||||
Fix for splats nested within the LHS of destructuring assignment.
|
||||
</li>
|
||||
<li>
|
||||
Corrections to our compile time strict mode forbidding of octal literals.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">
|
||||
<a href="https://github.com/jashkenas/coffee-script/compare/1.2.0...1.3.1">1.3.1</a>
|
||||
<span class="timestamp"> – <small>April 10, 2012</small></span>
|
||||
</b>
|
||||
<ul>
|
||||
<li>
|
||||
CoffeeScript now enforces all of JavaScript's <b>Strict Mode</b> early syntax
|
||||
errors at compile time. This includes old-style octal literals,
|
||||
duplicate property names in object literals, duplicate parameters in
|
||||
a function definition, deleting naked variables, setting the value of
|
||||
<tt>eval</tt> or <tt>arguments</tt>, and more.
|
||||
See a full discussion at
|
||||
<a href="https://github.com/jashkenas/coffee-script/issues/1547">#1547</a>.
|
||||
</li>
|
||||
<li>
|
||||
The REPL now has a handy new multi-line mode for entering large
|
||||
blocks of code. It's useful when copy-and-pasting examples into the
|
||||
REPL. Enter multi-line mode with <tt>Ctrl-V</tt>. You may also now
|
||||
pipe input directly into the REPL.
|
||||
</li>
|
||||
<li>
|
||||
CoffeeScript now prints a <tt>Generated by CoffeeScript VERSION</tt>
|
||||
header at the top of each compiled file.
|
||||
</li>
|
||||
<li>
|
||||
Conditional assignment of previously undefined variables
|
||||
<tt>a or= b</tt> is now considered a syntax error.
|
||||
</li>
|
||||
<li>
|
||||
A tweak to the semantics of <tt>do</tt>, which can now be used to
|
||||
more easily simulate a namespace: <tt>do (x = 1, y = 2) -> ...</tt>
|
||||
</li>
|
||||
<li>
|
||||
Loop indices are now mutable within a loop iteration, and immutable
|
||||
between them.
|
||||
</li>
|
||||
<li>
|
||||
Both endpoints of a slice are now allowed to be omitted for consistency,
|
||||
effectively creating a shallow copy of the list.
|
||||
</li>
|
||||
<li>
|
||||
Additional tweaks and improvments to <tt>coffee --watch</tt> under
|
||||
Node's "new" file watching API. Watch will now beep by default
|
||||
if you introduce a syntax error into a watched script. We also now
|
||||
ignore hidden directories by default when watching recursively.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">
|
||||
<a href="https://github.com/jashkenas/coffee-script/compare/1.1.3...1.2.0">1.2.0</a>
|
||||
<span class="timestamp"> – <small>Dec. 18, 2011</small></span>
|
||||
</b>
|
||||
<ul>
|
||||
<li>
|
||||
Multiple improvements to <tt>coffee --watch</tt> and <tt>--join</tt>.
|
||||
You may now use both together, as well as add and remove
|
||||
files and directories within a <tt>--watch</tt>'d folder.
|
||||
</li>
|
||||
<li>
|
||||
The <tt>throw</tt> statement can now be used as part of an expression.
|
||||
</li>
|
||||
<li>
|
||||
Block comments at the top of the file will now appear outside of the
|
||||
safety closure wrapper.
|
||||
</li>
|
||||
<li>
|
||||
Fixed a number of minor 1.1.3 regressions having to do with trailing
|
||||
operators and unfinished lines, and a more major 1.1.3 regression that
|
||||
caused bound functions <i>within</i> bound class functions to have the incorrect
|
||||
<tt>this</tt>.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">
|
||||
<a href="https://github.com/jashkenas/coffee-script/compare/1.1.2...1.1.3">1.1.3</a>
|
||||
@@ -2788,7 +3002,7 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
closeMenus = ->
|
||||
$('.navigation.active').removeClass 'active'
|
||||
|
||||
$('.minibutton.run').click evalJS
|
||||
$('.minibutton.run').click -> evalJS()
|
||||
|
||||
# Bind navigation buttons to open the menus.
|
||||
$('.navigation').click (e) ->
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var CoffeeScript, runScripts;
|
||||
|
||||
@@ -5,23 +6,36 @@
|
||||
|
||||
CoffeeScript.require = require;
|
||||
|
||||
CoffeeScript.eval = function(code, options) {
|
||||
CoffeeScript["eval"] = function(code, options) {
|
||||
var _ref;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
if ((_ref = options.bare) == null) {
|
||||
options.bare = true;
|
||||
}
|
||||
return eval(CoffeeScript.compile(code, options));
|
||||
};
|
||||
|
||||
CoffeeScript.run = function(code, options) {
|
||||
if (options == null) options = {};
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
options.bare = true;
|
||||
return Function(CoffeeScript.compile(code, options))();
|
||||
};
|
||||
|
||||
if (typeof window === "undefined" || window === null) return;
|
||||
if (typeof window === "undefined" || window === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoffeeScript.load = function(url, callback) {
|
||||
var xhr;
|
||||
xhr = new (window.ActiveXObject || XMLHttpRequest)('Microsoft.XMLHTTP');
|
||||
xhr = window.ActiveXObject ? new window.ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest();
|
||||
xhr.open('GET', url, true);
|
||||
if ('overrideMimeType' in xhr) xhr.overrideMimeType('text/plain');
|
||||
if ('overrideMimeType' in xhr) {
|
||||
xhr.overrideMimeType('text/plain');
|
||||
}
|
||||
xhr.onreadystatechange = function() {
|
||||
var _ref;
|
||||
if (xhr.readyState === 4) {
|
||||
@@ -30,7 +44,9 @@
|
||||
} else {
|
||||
throw new Error("Could not load " + url);
|
||||
}
|
||||
if (callback) return callback();
|
||||
if (callback) {
|
||||
return callback();
|
||||
}
|
||||
}
|
||||
};
|
||||
return xhr.send(null);
|
||||
@@ -44,7 +60,9 @@
|
||||
_results = [];
|
||||
for (_i = 0, _len = scripts.length; _i < _len; _i++) {
|
||||
s = scripts[_i];
|
||||
if (s.type === 'text/coffeescript') _results.push(s);
|
||||
if (s.type === 'text/coffeescript') {
|
||||
_results.push(s);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var CoffeeScript, cakefileDirectory, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks;
|
||||
var CoffeeScript, cakefileDirectory, existsSync, fatalError, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks;
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
@@ -11,6 +12,8 @@
|
||||
|
||||
CoffeeScript = require('./coffee-script');
|
||||
|
||||
existsSync = fs.existsSync || path.existsSync;
|
||||
|
||||
tasks = {};
|
||||
|
||||
options = {};
|
||||
@@ -35,7 +38,9 @@
|
||||
return switches.push([letter, flag, description]);
|
||||
},
|
||||
invoke: function(name) {
|
||||
if (!tasks[name]) missingTask(name);
|
||||
if (!tasks[name]) {
|
||||
missingTask(name);
|
||||
}
|
||||
return tasks[name].action(options);
|
||||
}
|
||||
});
|
||||
@@ -49,9 +54,15 @@
|
||||
filename: 'Cakefile'
|
||||
});
|
||||
oparse = new optparse.OptionParser(switches);
|
||||
if (!args.length) return printTasks();
|
||||
options = oparse.parse(args);
|
||||
_ref = options.arguments;
|
||||
if (!args.length) {
|
||||
return printTasks();
|
||||
}
|
||||
try {
|
||||
options = oparse.parse(args);
|
||||
} catch (e) {
|
||||
return fatalError("" + e);
|
||||
}
|
||||
_ref = options["arguments"];
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
arg = _ref[_i];
|
||||
@@ -61,8 +72,10 @@
|
||||
};
|
||||
|
||||
printTasks = function() {
|
||||
var desc, name, spaces, task;
|
||||
console.log('');
|
||||
var cakefilePath, desc, name, relative, spaces, task;
|
||||
relative = path.relative || path.resolve;
|
||||
cakefilePath = path.join(relative(__originalDirname, process.cwd()), 'Cakefile');
|
||||
console.log("" + cakefilePath + " defines the following tasks:\n");
|
||||
for (name in tasks) {
|
||||
task = tasks[name];
|
||||
spaces = 20 - name.length;
|
||||
@@ -70,19 +83,30 @@
|
||||
desc = task.description ? "# " + task.description : '';
|
||||
console.log("cake " + name + spaces + " " + desc);
|
||||
}
|
||||
if (switches.length) return console.log(oparse.help());
|
||||
if (switches.length) {
|
||||
return console.log(oparse.help());
|
||||
}
|
||||
};
|
||||
|
||||
fatalError = function(message) {
|
||||
console.error(message + '\n');
|
||||
console.log('To see a list of all tasks/options, run "cake"');
|
||||
return process.exit(1);
|
||||
};
|
||||
|
||||
missingTask = function(task) {
|
||||
console.log("No such task: \"" + task + "\"");
|
||||
return process.exit(1);
|
||||
return fatalError("No such task: " + task);
|
||||
};
|
||||
|
||||
cakefileDirectory = function(dir) {
|
||||
var parent;
|
||||
if (path.existsSync(path.join(dir, 'Cakefile'))) return dir;
|
||||
if (existsSync(path.join(dir, 'Cakefile'))) {
|
||||
return dir;
|
||||
}
|
||||
parent = path.normalize(path.join(dir, '..'));
|
||||
if (parent !== dir) return cakefileDirectory(parent);
|
||||
if (parent !== dir) {
|
||||
return cakefileDirectory(parent);
|
||||
}
|
||||
throw new Error("Cakefile not found in " + (process.cwd()));
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var Lexer, RESERVED, compile, fs, lexer, parser, path, vm, _ref;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
var Lexer, RESERVED, compile, fs, lexer, parser, path, stripBOM, vm, _ref,
|
||||
__hasProp = {}.hasOwnProperty;
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
@@ -12,36 +13,49 @@
|
||||
|
||||
vm = require('vm');
|
||||
|
||||
stripBOM = function(content) {
|
||||
if (content.charCodeAt(0) === 0xFEFF) {
|
||||
return content.substring(1);
|
||||
} else {
|
||||
return content;
|
||||
}
|
||||
};
|
||||
|
||||
if (require.extensions) {
|
||||
require.extensions['.coffee'] = function(module, filename) {
|
||||
var content;
|
||||
content = compile(fs.readFileSync(filename, 'utf8'), {
|
||||
content = compile(stripBOM(fs.readFileSync(filename, 'utf8')), {
|
||||
filename: filename
|
||||
});
|
||||
return module._compile(content, filename);
|
||||
};
|
||||
} else if (require.registerExtension) {
|
||||
require.registerExtension('.coffee', function(content) {
|
||||
return compile(content);
|
||||
});
|
||||
}
|
||||
|
||||
exports.VERSION = '1.1.3';
|
||||
exports.VERSION = '1.4.0';
|
||||
|
||||
exports.RESERVED = RESERVED;
|
||||
|
||||
exports.helpers = require('./helpers');
|
||||
|
||||
exports.compile = compile = function(code, options) {
|
||||
if (options == null) options = {};
|
||||
var header, js, merge;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
merge = exports.helpers.merge;
|
||||
try {
|
||||
return (parser.parse(lexer.tokenize(code))).compile(options);
|
||||
js = (parser.parse(lexer.tokenize(code))).compile(options);
|
||||
if (!options.header) {
|
||||
return js;
|
||||
}
|
||||
} catch (err) {
|
||||
if (options.filename) {
|
||||
err.message = "In " + options.filename + ", " + err.message;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
header = "Generated by CoffeeScript " + this.VERSION;
|
||||
return "// " + header + "\n" + js;
|
||||
};
|
||||
|
||||
exports.tokens = function(code, options) {
|
||||
@@ -58,10 +72,13 @@
|
||||
|
||||
exports.run = function(code, options) {
|
||||
var mainModule;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
mainModule = require.main;
|
||||
mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : '.';
|
||||
mainModule.moduleCache && (mainModule.moduleCache = {});
|
||||
mainModule.paths = require('module')._nodeModulePaths(path.dirname(options.filename));
|
||||
mainModule.paths = require('module')._nodeModulePaths(path.dirname(fs.realpathSync(options.filename)));
|
||||
if (path.extname(mainModule.filename) !== '.coffee' || require.extensions) {
|
||||
return mainModule._compile(compile(code, options), mainModule.filename);
|
||||
} else {
|
||||
@@ -69,10 +86,14 @@
|
||||
}
|
||||
};
|
||||
|
||||
exports.eval = function(code, options) {
|
||||
var Module, Script, js, k, o, r, sandbox, v, _i, _len, _module, _ref2, _ref3, _require;
|
||||
if (options == null) options = {};
|
||||
if (!(code = code.trim())) return;
|
||||
exports["eval"] = function(code, options) {
|
||||
var Module, Script, js, k, o, r, sandbox, v, _i, _len, _module, _ref1, _ref2, _require;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
if (!(code = code.trim())) {
|
||||
return;
|
||||
}
|
||||
Script = vm.Script;
|
||||
if (Script) {
|
||||
if (options.sandbox != null) {
|
||||
@@ -80,10 +101,10 @@
|
||||
sandbox = options.sandbox;
|
||||
} else {
|
||||
sandbox = Script.createContext();
|
||||
_ref2 = options.sandbox;
|
||||
for (k in _ref2) {
|
||||
if (!__hasProp.call(_ref2, k)) continue;
|
||||
v = _ref2[k];
|
||||
_ref1 = options.sandbox;
|
||||
for (k in _ref1) {
|
||||
if (!__hasProp.call(_ref1, k)) continue;
|
||||
v = _ref1[k];
|
||||
sandbox[k] = v;
|
||||
}
|
||||
}
|
||||
@@ -100,10 +121,12 @@
|
||||
return Module._load(path, _module, true);
|
||||
};
|
||||
_module.filename = sandbox.__filename;
|
||||
_ref3 = Object.getOwnPropertyNames(require);
|
||||
for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
|
||||
r = _ref3[_i];
|
||||
if (r !== 'paths') _require[r] = require[r];
|
||||
_ref2 = Object.getOwnPropertyNames(require);
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
r = _ref2[_i];
|
||||
if (r !== 'paths') {
|
||||
_require[r] = require[r];
|
||||
}
|
||||
}
|
||||
_require.paths = _module.paths = Module._nodeModulePaths(process.cwd());
|
||||
_require.resolve = function(request) {
|
||||
@@ -130,8 +153,8 @@
|
||||
|
||||
parser.lexer = {
|
||||
lex: function() {
|
||||
var tag, _ref2;
|
||||
_ref2 = this.tokens[this.pos++] || [''], tag = _ref2[0], this.yytext = _ref2[1], this.yylineno = _ref2[2];
|
||||
var tag, _ref1;
|
||||
_ref1 = this.tokens[this.pos++] || [''], tag = _ref1[0], this.yytext = _ref1[1], this.yylineno = _ref1[2];
|
||||
return tag;
|
||||
},
|
||||
setInput: function(tokens) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compileScript, compileScripts, compileStdio, contents, exec, forkNode, fs, helpers, lint, loadRequires, optionParser, optparse, opts, parseOptions, path, printLine, printTokens, printWarn, sources, spawn, usage, version, watch, writeJs, _ref;
|
||||
var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, exists, forkNode, fs, helpers, hidden, joinTimeout, lint, loadRequires, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, removeSource, sourceCode, sources, spawn, timeLog, unwatchDir, usage, version, wait, watch, watchDir, watchers, writeJs, _ref;
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
@@ -15,6 +16,8 @@
|
||||
|
||||
EventEmitter = require('events').EventEmitter;
|
||||
|
||||
exists = fs.exists || path.exists;
|
||||
|
||||
helpers.extend(CoffeeScript, new EventEmitter);
|
||||
|
||||
printLine = function(line) {
|
||||
@@ -25,7 +28,11 @@
|
||||
return process.stderr.write(line + '\n');
|
||||
};
|
||||
|
||||
BANNER = 'Usage: coffee [options] path/to/script.coffee\n\nIf called without options, `coffee` will run your script.';
|
||||
hidden = function(file) {
|
||||
return /^\.|~$/.test(file);
|
||||
};
|
||||
|
||||
BANNER = 'Usage: coffee [options] path/to/script.coffee -- [args]\n\nIf called without options, `coffee` will run your script.';
|
||||
|
||||
SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-r', '--require [FILE*]', 'require a library before executing your script'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']];
|
||||
|
||||
@@ -33,101 +40,124 @@
|
||||
|
||||
sources = [];
|
||||
|
||||
contents = [];
|
||||
sourceCode = [];
|
||||
|
||||
notSources = {};
|
||||
|
||||
watchers = {};
|
||||
|
||||
optionParser = null;
|
||||
|
||||
exports.run = function() {
|
||||
var literals, source, _i, _len, _results;
|
||||
parseOptions();
|
||||
if (opts.nodejs) return forkNode();
|
||||
if (opts.help) return usage();
|
||||
if (opts.version) return version();
|
||||
if (opts.require) loadRequires();
|
||||
if (opts.interactive) return require('./repl');
|
||||
if (opts.stdio) return compileStdio();
|
||||
if (opts.eval) return compileScript(null, sources[0]);
|
||||
if (!sources.length) return require('./repl');
|
||||
if (opts.run) opts.literals = sources.splice(1).concat(opts.literals);
|
||||
process.argv = process.argv.slice(0, 2).concat(opts.literals);
|
||||
if (opts.nodejs) {
|
||||
return forkNode();
|
||||
}
|
||||
if (opts.help) {
|
||||
return usage();
|
||||
}
|
||||
if (opts.version) {
|
||||
return version();
|
||||
}
|
||||
if (opts.require) {
|
||||
loadRequires();
|
||||
}
|
||||
if (opts.interactive) {
|
||||
return require('./repl');
|
||||
}
|
||||
if (opts.watch && !fs.watch) {
|
||||
return printWarn("The --watch feature depends on Node v0.6.0+. You are running " + process.version + ".");
|
||||
}
|
||||
if (opts.stdio) {
|
||||
return compileStdio();
|
||||
}
|
||||
if (opts["eval"]) {
|
||||
return compileScript(null, sources[0]);
|
||||
}
|
||||
if (!sources.length) {
|
||||
return require('./repl');
|
||||
}
|
||||
literals = opts.run ? sources.splice(1) : [];
|
||||
process.argv = process.argv.slice(0, 2).concat(literals);
|
||||
process.argv[0] = 'coffee';
|
||||
process.execPath = require.main.filename;
|
||||
return compileScripts();
|
||||
};
|
||||
|
||||
compileScripts = function() {
|
||||
var base, compile, remaining_files, source, trackCompleteFiles, trackUnprocessedFiles, unprocessed, _i, _j, _len, _len2, _results;
|
||||
unprocessed = [];
|
||||
remaining_files = function() {
|
||||
var total, x, _i, _len;
|
||||
total = 0;
|
||||
for (_i = 0, _len = unprocessed.length; _i < _len; _i++) {
|
||||
x = unprocessed[_i];
|
||||
total += x;
|
||||
}
|
||||
return total;
|
||||
};
|
||||
trackUnprocessedFiles = function(sourceIndex, fileCount) {
|
||||
var _ref2;
|
||||
if ((_ref2 = unprocessed[sourceIndex]) == null) unprocessed[sourceIndex] = 0;
|
||||
return unprocessed[sourceIndex] += fileCount;
|
||||
};
|
||||
trackCompleteFiles = function(sourceIndex, fileCount) {
|
||||
unprocessed[sourceIndex] -= fileCount;
|
||||
if (opts.join) {
|
||||
if (helpers.compact(contents).length > 0 && remaining_files() === 0) {
|
||||
return compileJoin();
|
||||
}
|
||||
}
|
||||
};
|
||||
_results = [];
|
||||
for (_i = 0, _len = sources.length; _i < _len; _i++) {
|
||||
source = sources[_i];
|
||||
trackUnprocessedFiles(sources.indexOf(source), 1);
|
||||
}
|
||||
_results = [];
|
||||
for (_j = 0, _len2 = sources.length; _j < _len2; _j++) {
|
||||
source = sources[_j];
|
||||
base = path.join(source);
|
||||
compile = function(source, sourceIndex, topLevel) {
|
||||
return path.exists(source, function(exists) {
|
||||
if (topLevel && !exists && source.slice(-7) !== '.coffee') {
|
||||
return compile("" + source + ".coffee", sourceIndex, topLevel);
|
||||
}
|
||||
if (topLevel && !exists) throw new Error("File not found: " + source);
|
||||
return fs.stat(source, function(err, stats) {
|
||||
if (err) throw err;
|
||||
if (stats.isDirectory()) {
|
||||
return fs.readdir(source, function(err, files) {
|
||||
var file, _k, _len3;
|
||||
if (err) throw err;
|
||||
trackUnprocessedFiles(sourceIndex, files.length);
|
||||
for (_k = 0, _len3 = files.length; _k < _len3; _k++) {
|
||||
file = files[_k];
|
||||
compile(path.join(source, file), sourceIndex);
|
||||
}
|
||||
return trackCompleteFiles(sourceIndex, 1);
|
||||
});
|
||||
} else if (topLevel || path.extname(source) === '.coffee') {
|
||||
fs.readFile(source, function(err, code) {
|
||||
if (err) throw err;
|
||||
if (opts.join) {
|
||||
contents[sourceIndex] = helpers.compact([contents[sourceIndex], code.toString()]).join('\n');
|
||||
} else {
|
||||
compileScript(source, code.toString(), base);
|
||||
}
|
||||
return trackCompleteFiles(sourceIndex, 1);
|
||||
});
|
||||
if (opts.watch && !opts.join) return watch(source, base);
|
||||
} else {
|
||||
return trackCompleteFiles(sourceIndex, 1);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
_results.push(compile(source, sources.indexOf(source), true));
|
||||
_results.push(compilePath(source, true, path.normalize(source)));
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
|
||||
compilePath = function(source, topLevel, base) {
|
||||
return fs.stat(source, function(err, stats) {
|
||||
if (err && err.code !== 'ENOENT') {
|
||||
throw err;
|
||||
}
|
||||
if ((err != null ? err.code : void 0) === 'ENOENT') {
|
||||
if (topLevel && source.slice(-7) !== '.coffee') {
|
||||
source = sources[sources.indexOf(source)] = "" + source + ".coffee";
|
||||
return compilePath(source, topLevel, base);
|
||||
}
|
||||
if (topLevel) {
|
||||
console.error("File not found: " + source);
|
||||
process.exit(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (stats.isDirectory()) {
|
||||
if (opts.watch) {
|
||||
watchDir(source, base);
|
||||
}
|
||||
return fs.readdir(source, function(err, files) {
|
||||
var file, index, _ref1, _ref2;
|
||||
if (err && err.code !== 'ENOENT') {
|
||||
throw err;
|
||||
}
|
||||
if ((err != null ? err.code : void 0) === 'ENOENT') {
|
||||
return;
|
||||
}
|
||||
index = sources.indexOf(source);
|
||||
files = files.filter(function(file) {
|
||||
return !hidden(file);
|
||||
});
|
||||
[].splice.apply(sources, [index, index - index + 1].concat(_ref1 = (function() {
|
||||
var _i, _len, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = files.length; _i < _len; _i++) {
|
||||
file = files[_i];
|
||||
_results.push(path.join(source, file));
|
||||
}
|
||||
return _results;
|
||||
})())), _ref1;
|
||||
[].splice.apply(sourceCode, [index, index - index + 1].concat(_ref2 = files.map(function() {
|
||||
return null;
|
||||
}))), _ref2;
|
||||
return files.forEach(function(file) {
|
||||
return compilePath(path.join(source, file), false, base);
|
||||
});
|
||||
});
|
||||
} else if (topLevel || path.extname(source) === '.coffee') {
|
||||
if (opts.watch) {
|
||||
watch(source, base);
|
||||
}
|
||||
return fs.readFile(source, function(err, code) {
|
||||
if (err && err.code !== 'ENOENT') {
|
||||
throw err;
|
||||
}
|
||||
if ((err != null ? err.code : void 0) === 'ENOENT') {
|
||||
return;
|
||||
}
|
||||
return compileScript(source, code.toString(), base);
|
||||
});
|
||||
} else {
|
||||
notSources[source] = true;
|
||||
return removeSource(source, base);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
compileScript = function(file, input, base) {
|
||||
var o, options, t, task;
|
||||
o = opts;
|
||||
@@ -145,6 +175,9 @@
|
||||
return printLine(CoffeeScript.nodes(t.input).toString().trim());
|
||||
} else if (o.run) {
|
||||
return CoffeeScript.run(t.input, t.options);
|
||||
} else if (o.join && t.file !== o.join) {
|
||||
sourceCode[sources.indexOf(t.file)] = t.input;
|
||||
return compileJoin();
|
||||
} else {
|
||||
t.output = CoffeeScript.compile(t.input, t.options);
|
||||
CoffeeScript.emit('success', task);
|
||||
@@ -158,8 +191,12 @@
|
||||
}
|
||||
} catch (err) {
|
||||
CoffeeScript.emit('failure', err, task);
|
||||
if (CoffeeScript.listeners('failure').length) return;
|
||||
if (o.watch) return printLine(err.message);
|
||||
if (CoffeeScript.listeners('failure').length) {
|
||||
return;
|
||||
}
|
||||
if (o.watch) {
|
||||
return printLine(err.message + '\x07');
|
||||
}
|
||||
printWarn(err instanceof Error && err.stack || ("ERROR: " + err));
|
||||
return process.exit(1);
|
||||
}
|
||||
@@ -170,78 +207,228 @@
|
||||
code = '';
|
||||
stdin = process.openStdin();
|
||||
stdin.on('data', function(buffer) {
|
||||
if (buffer) return code += buffer.toString();
|
||||
if (buffer) {
|
||||
return code += buffer.toString();
|
||||
}
|
||||
});
|
||||
return stdin.on('end', function() {
|
||||
return compileScript(null, code);
|
||||
});
|
||||
};
|
||||
|
||||
joinTimeout = null;
|
||||
|
||||
compileJoin = function() {
|
||||
var code;
|
||||
code = contents.join('\n');
|
||||
return compileScript(opts.join, code, opts.join);
|
||||
if (!opts.join) {
|
||||
return;
|
||||
}
|
||||
if (!sourceCode.some(function(code) {
|
||||
return code === null;
|
||||
})) {
|
||||
clearTimeout(joinTimeout);
|
||||
return joinTimeout = wait(100, function() {
|
||||
return compileScript(opts.join, sourceCode.join('\n'), opts.join);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
loadRequires = function() {
|
||||
var realFilename, req, _i, _len, _ref2;
|
||||
var realFilename, req, _i, _len, _ref1;
|
||||
realFilename = module.filename;
|
||||
module.filename = '.';
|
||||
_ref2 = opts.require;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
req = _ref2[_i];
|
||||
_ref1 = opts.require;
|
||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||
req = _ref1[_i];
|
||||
require(req);
|
||||
}
|
||||
return module.filename = realFilename;
|
||||
};
|
||||
|
||||
watch = function(source, base) {
|
||||
return fs.stat(source, function(err, prevStats) {
|
||||
if (err) throw err;
|
||||
return fs.watch(source, function(event) {
|
||||
if (event === 'change') {
|
||||
return fs.stat(source, function(err, stats) {
|
||||
if (err) throw err;
|
||||
if (stats.size === prevStats.size && stats.mtime.getTime() === prevStats.mtime.getTime()) {
|
||||
return;
|
||||
var compile, compileTimeout, prevStats, rewatch, watchErr, watcher;
|
||||
prevStats = null;
|
||||
compileTimeout = null;
|
||||
watchErr = function(e) {
|
||||
if (e.code === 'ENOENT') {
|
||||
if (sources.indexOf(source) === -1) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
rewatch();
|
||||
return compile();
|
||||
} catch (e) {
|
||||
removeSource(source, base, true);
|
||||
return compileJoin();
|
||||
}
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
compile = function() {
|
||||
clearTimeout(compileTimeout);
|
||||
return compileTimeout = wait(25, function() {
|
||||
return fs.stat(source, function(err, stats) {
|
||||
if (err) {
|
||||
return watchErr(err);
|
||||
}
|
||||
if (prevStats && stats.size === prevStats.size && stats.mtime.getTime() === prevStats.mtime.getTime()) {
|
||||
return rewatch();
|
||||
}
|
||||
prevStats = stats;
|
||||
return fs.readFile(source, function(err, code) {
|
||||
if (err) {
|
||||
return watchErr(err);
|
||||
}
|
||||
prevStats = stats;
|
||||
return fs.readFile(source, function(err, code) {
|
||||
if (err) throw err;
|
||||
return compileScript(source, code.toString(), base);
|
||||
});
|
||||
compileScript(source, code.toString(), base);
|
||||
return rewatch();
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
try {
|
||||
watcher = fs.watch(source, compile);
|
||||
} catch (e) {
|
||||
watchErr(e);
|
||||
}
|
||||
return rewatch = function() {
|
||||
if (watcher != null) {
|
||||
watcher.close();
|
||||
}
|
||||
return watcher = fs.watch(source, compile);
|
||||
};
|
||||
};
|
||||
|
||||
watchDir = function(source, base) {
|
||||
var readdirTimeout, watcher;
|
||||
readdirTimeout = null;
|
||||
try {
|
||||
return watcher = fs.watch(source, function() {
|
||||
clearTimeout(readdirTimeout);
|
||||
return readdirTimeout = wait(25, function() {
|
||||
return fs.readdir(source, function(err, files) {
|
||||
var file, _i, _len, _results;
|
||||
if (err) {
|
||||
if (err.code !== 'ENOENT') {
|
||||
throw err;
|
||||
}
|
||||
watcher.close();
|
||||
return unwatchDir(source, base);
|
||||
}
|
||||
_results = [];
|
||||
for (_i = 0, _len = files.length; _i < _len; _i++) {
|
||||
file = files[_i];
|
||||
if (!(!hidden(file) && !notSources[file])) {
|
||||
continue;
|
||||
}
|
||||
file = path.join(source, file);
|
||||
if (sources.some(function(s) {
|
||||
return s.indexOf(file) >= 0;
|
||||
})) {
|
||||
continue;
|
||||
}
|
||||
sources.push(file);
|
||||
sourceCode.push(null);
|
||||
_results.push(compilePath(file, false, base));
|
||||
}
|
||||
return _results;
|
||||
});
|
||||
});
|
||||
});
|
||||
} catch (e) {
|
||||
if (e.code !== 'ENOENT') {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
unwatchDir = function(source, base) {
|
||||
var file, prevSources, toRemove, _i, _len;
|
||||
prevSources = sources.slice(0);
|
||||
toRemove = (function() {
|
||||
var _i, _len, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = sources.length; _i < _len; _i++) {
|
||||
file = sources[_i];
|
||||
if (file.indexOf(source) >= 0) {
|
||||
_results.push(file);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
for (_i = 0, _len = toRemove.length; _i < _len; _i++) {
|
||||
file = toRemove[_i];
|
||||
removeSource(file, base, true);
|
||||
}
|
||||
if (!sources.some(function(s, i) {
|
||||
return prevSources[i] !== s;
|
||||
})) {
|
||||
return;
|
||||
}
|
||||
return compileJoin();
|
||||
};
|
||||
|
||||
removeSource = function(source, base, removeJs) {
|
||||
var index, jsPath;
|
||||
index = sources.indexOf(source);
|
||||
sources.splice(index, 1);
|
||||
sourceCode.splice(index, 1);
|
||||
if (removeJs && !opts.join) {
|
||||
jsPath = outputPath(source, base);
|
||||
return exists(jsPath, function(itExists) {
|
||||
if (itExists) {
|
||||
return fs.unlink(jsPath, function(err) {
|
||||
if (err && err.code !== 'ENOENT') {
|
||||
throw err;
|
||||
}
|
||||
return timeLog("removed " + source);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
writeJs = function(source, js, base) {
|
||||
var baseDir, compile, dir, filename, jsPath, srcDir;
|
||||
outputPath = function(source, base) {
|
||||
var baseDir, dir, filename, srcDir;
|
||||
filename = path.basename(source, path.extname(source)) + '.js';
|
||||
srcDir = path.dirname(source);
|
||||
baseDir = base === '.' ? srcDir : srcDir.substring(base.length);
|
||||
dir = opts.output ? path.join(opts.output, baseDir) : srcDir;
|
||||
jsPath = path.join(dir, filename);
|
||||
return path.join(dir, filename);
|
||||
};
|
||||
|
||||
writeJs = function(source, js, base) {
|
||||
var compile, jsDir, jsPath;
|
||||
jsPath = outputPath(source, base);
|
||||
jsDir = path.dirname(jsPath);
|
||||
compile = function() {
|
||||
if (js.length <= 0) js = ' ';
|
||||
if (js.length <= 0) {
|
||||
js = ' ';
|
||||
}
|
||||
return fs.writeFile(jsPath, js, function(err) {
|
||||
if (err) {
|
||||
return printLine(err.message);
|
||||
} else if (opts.compile && opts.watch) {
|
||||
return console.log("" + ((new Date).toLocaleTimeString()) + " - compiled " + source);
|
||||
return timeLog("compiled " + source);
|
||||
}
|
||||
});
|
||||
};
|
||||
return path.exists(dir, function(exists) {
|
||||
if (exists) {
|
||||
return exists(jsDir, function(itExists) {
|
||||
if (itExists) {
|
||||
return compile();
|
||||
} else {
|
||||
return exec("mkdir -p " + dir, compile);
|
||||
return exec("mkdir -p " + jsDir, compile);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
wait = function(milliseconds, func) {
|
||||
return setTimeout(func, milliseconds);
|
||||
};
|
||||
|
||||
timeLog = function(message) {
|
||||
return console.log("" + ((new Date).toLocaleTimeString()) + " - " + message);
|
||||
};
|
||||
|
||||
lint = function(file, js) {
|
||||
var conf, jsl, printIt;
|
||||
printIt = function(buffer) {
|
||||
@@ -258,11 +445,11 @@
|
||||
printTokens = function(tokens) {
|
||||
var strings, tag, token, value;
|
||||
strings = (function() {
|
||||
var _i, _len, _ref2, _results;
|
||||
var _i, _len, _ref1, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = tokens.length; _i < _len; _i++) {
|
||||
token = tokens[_i];
|
||||
_ref2 = [token[0], token[1].toString().replace(/\n/, '\\n')], tag = _ref2[0], value = _ref2[1];
|
||||
_ref1 = [token[0], token[1].toString().replace(/\n/, '\\n')], tag = _ref1[0], value = _ref1[1];
|
||||
_results.push("[" + tag + " " + value + "]");
|
||||
}
|
||||
return _results;
|
||||
@@ -271,19 +458,24 @@
|
||||
};
|
||||
|
||||
parseOptions = function() {
|
||||
var o;
|
||||
var i, o, source, _i, _len;
|
||||
optionParser = new optparse.OptionParser(SWITCHES, BANNER);
|
||||
o = opts = optionParser.parse(process.argv.slice(2));
|
||||
o.compile || (o.compile = !!o.output);
|
||||
o.run = !(o.compile || o.print || o.lint);
|
||||
o.print = !!(o.print || (o.eval || o.stdio && o.compile));
|
||||
return sources = o.arguments;
|
||||
o.print = !!(o.print || (o["eval"] || o.stdio && o.compile));
|
||||
sources = o["arguments"];
|
||||
for (i = _i = 0, _len = sources.length; _i < _len; i = ++_i) {
|
||||
source = sources[i];
|
||||
sourceCode[i] = null;
|
||||
}
|
||||
};
|
||||
|
||||
compileOptions = function(filename) {
|
||||
return {
|
||||
filename: filename,
|
||||
bare: opts.bare
|
||||
bare: opts.bare,
|
||||
header: opts.compile
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap;
|
||||
|
||||
@@ -8,7 +9,9 @@
|
||||
o = function(patternString, action, options) {
|
||||
var match;
|
||||
patternString = patternString.replace(/\s{2,}/g, ' ');
|
||||
if (!action) return [patternString, '$$ = $1;', options];
|
||||
if (!action) {
|
||||
return [patternString, '$$ = $1;', options];
|
||||
}
|
||||
action = (match = unwrap.exec(action)) ? match[1] : "(" + action + "())";
|
||||
action = action.replace(/\bnew /g, '$&yy.');
|
||||
action = action.replace(/\b(?:Block\.wrap|extend)\b/g, 'yy.$&');
|
||||
@@ -30,11 +33,11 @@
|
||||
],
|
||||
Line: [o('Expression'), o('Statement')],
|
||||
Statement: [
|
||||
o('Return'), o('Throw'), o('Comment'), o('STATEMENT', function() {
|
||||
o('Return'), o('Comment'), o('STATEMENT', function() {
|
||||
return new Literal($1);
|
||||
})
|
||||
],
|
||||
Expression: [o('Value'), o('Invocation'), o('Code'), o('Operation'), o('Assign'), o('If'), o('Try'), o('While'), o('For'), o('Switch'), o('Class')],
|
||||
Expression: [o('Value'), o('Invocation'), o('Code'), o('Operation'), o('Assign'), o('If'), o('Try'), o('While'), o('For'), o('Switch'), o('Class'), o('Throw')],
|
||||
Block: [
|
||||
o('INDENT OUTDENT', function() {
|
||||
return new Block;
|
||||
@@ -59,16 +62,21 @@
|
||||
return new Literal($1);
|
||||
}), o('REGEX', function() {
|
||||
return new Literal($1);
|
||||
}), o('DEBUGGER', function() {
|
||||
return new Literal($1);
|
||||
}), o('UNDEFINED', function() {
|
||||
return new Undefined;
|
||||
}), o('NULL', function() {
|
||||
return new Null;
|
||||
}), o('BOOL', function() {
|
||||
var val;
|
||||
val = new Literal($1);
|
||||
if ($1 === 'undefined') val.isUndefined = true;
|
||||
return val;
|
||||
return new Bool($1);
|
||||
})
|
||||
],
|
||||
Assign: [
|
||||
o('Assignable = Expression', function() {
|
||||
return new Assign($1, $3);
|
||||
}), o('Assignable = TERMINATOR Expression', function() {
|
||||
return new Assign($1, $4);
|
||||
}), o('Assignable = INDENT Expression OUTDENT', function() {
|
||||
return new Assign($1, $4);
|
||||
})
|
||||
@@ -118,6 +126,10 @@
|
||||
return [$1];
|
||||
}), o('ParamList , Param', function() {
|
||||
return $1.concat($3);
|
||||
}), o('ParamList OptComma TERMINATOR Param', function() {
|
||||
return $1.concat($4);
|
||||
}), o('ParamList OptComma INDENT ParamList OptComma OUTDENT', function() {
|
||||
return $1.concat($4);
|
||||
})
|
||||
],
|
||||
Param: [
|
||||
@@ -141,7 +153,7 @@
|
||||
}), o('Value Accessor', function() {
|
||||
return $1.add($2);
|
||||
}), o('Invocation Accessor', function() {
|
||||
return new Value($1, [$2]);
|
||||
return new Value($1, [].concat($2));
|
||||
}), o('ThisProperty')
|
||||
],
|
||||
Assignable: [
|
||||
@@ -287,6 +299,8 @@
|
||||
return new Range($1, null, $2);
|
||||
}), o('RangeDots Expression', function() {
|
||||
return new Range(null, $2, $1);
|
||||
}), o('RangeDots', function() {
|
||||
return new Range(null, null, $1);
|
||||
})
|
||||
],
|
||||
ArgList: [
|
||||
@@ -402,7 +416,7 @@
|
||||
})
|
||||
],
|
||||
ForValue: [
|
||||
o('Identifier'), o('Array', function() {
|
||||
o('Identifier'), o('ThisProperty'), o('Array', function() {
|
||||
return new Value($1);
|
||||
}), o('Object', function() {
|
||||
return new Value($1);
|
||||
@@ -555,23 +569,27 @@
|
||||
]
|
||||
};
|
||||
|
||||
operators = [['left', '.', '?.', '::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', 'LOGIC'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'DO', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS'], ['right', 'POST_IF']];
|
||||
operators = [['left', '.', '?.', '::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', 'LOGIC'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS'], ['right', 'POST_IF']];
|
||||
|
||||
tokens = [];
|
||||
|
||||
for (name in grammar) {
|
||||
alternatives = grammar[name];
|
||||
grammar[name] = (function() {
|
||||
var _i, _j, _len, _len2, _ref, _results;
|
||||
var _i, _j, _len, _len1, _ref, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = alternatives.length; _i < _len; _i++) {
|
||||
alt = alternatives[_i];
|
||||
_ref = alt[0].split(' ');
|
||||
for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) {
|
||||
for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
|
||||
token = _ref[_j];
|
||||
if (!grammar[token]) tokens.push(token);
|
||||
if (!grammar[token]) {
|
||||
tokens.push(token);
|
||||
}
|
||||
}
|
||||
if (name === 'Root') {
|
||||
alt[1] = "return " + alt[1];
|
||||
}
|
||||
if (name === 'Root') alt[1] = "return " + alt[1];
|
||||
_results.push(alt);
|
||||
}
|
||||
return _results;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var extend, flatten;
|
||||
var extend, flatten, _ref;
|
||||
|
||||
exports.starts = function(string, literal, start) {
|
||||
return literal === string.substr(start, literal.length);
|
||||
@@ -16,7 +17,9 @@
|
||||
_results = [];
|
||||
for (_i = 0, _len = array.length; _i < _len; _i++) {
|
||||
item = array[_i];
|
||||
if (item) _results.push(item);
|
||||
if (item) {
|
||||
_results.push(item);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
@@ -24,7 +27,9 @@
|
||||
exports.count = function(string, substr) {
|
||||
var num, pos;
|
||||
num = pos = 0;
|
||||
if (!substr.length) return 1 / 0;
|
||||
if (!substr.length) {
|
||||
return 1 / 0;
|
||||
}
|
||||
while (pos = 1 + string.indexOf(substr, pos)) {
|
||||
num++;
|
||||
}
|
||||
@@ -69,4 +74,15 @@
|
||||
return array[array.length - (back || 0) - 1];
|
||||
};
|
||||
|
||||
exports.some = (_ref = Array.prototype.some) != null ? _ref : function(fn) {
|
||||
var e, _i, _len;
|
||||
for (_i = 0, _len = this.length; _i < _len; _i++) {
|
||||
e = this[_i];
|
||||
if (fn(e)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var key, val, _ref;
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, INVERSES, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, starts, _ref, _ref2;
|
||||
var __hasProp = Object.prototype.hasOwnProperty, __indexOf = Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (__hasProp.call(this, i) && this[i] === item) return i; } return -1; };
|
||||
var BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, INVERSES, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, STRICT_PROSCRIBED, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, starts, _ref, _ref1,
|
||||
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
|
||||
_ref = require('./rewriter'), Rewriter = _ref.Rewriter, INVERSES = _ref.INVERSES;
|
||||
|
||||
_ref2 = require('./helpers'), count = _ref2.count, starts = _ref2.starts, compact = _ref2.compact, last = _ref2.last;
|
||||
_ref1 = require('./helpers'), count = _ref1.count, starts = _ref1.starts, compact = _ref1.compact, last = _ref1.last;
|
||||
|
||||
exports.Lexer = Lexer = (function() {
|
||||
|
||||
@@ -12,8 +13,12 @@
|
||||
|
||||
Lexer.prototype.tokenize = function(code, opts) {
|
||||
var i, tag;
|
||||
if (opts == null) opts = {};
|
||||
if (WHITESPACE.test(code)) code = "\n" + code;
|
||||
if (opts == null) {
|
||||
opts = {};
|
||||
}
|
||||
if (WHITESPACE.test(code)) {
|
||||
code = "\n" + code;
|
||||
}
|
||||
code = code.replace(/\r/g, '').replace(TRAILING_SPACES, '');
|
||||
this.code = code;
|
||||
this.line = opts.line || 0;
|
||||
@@ -28,24 +33,30 @@
|
||||
i += this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.heredocToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken();
|
||||
}
|
||||
this.closeIndentation();
|
||||
if (tag = this.ends.pop()) this.error("missing " + tag);
|
||||
if (opts.rewrite === false) return this.tokens;
|
||||
if (tag = this.ends.pop()) {
|
||||
this.error("missing " + tag);
|
||||
}
|
||||
if (opts.rewrite === false) {
|
||||
return this.tokens;
|
||||
}
|
||||
return (new Rewriter).rewrite(this.tokens);
|
||||
};
|
||||
|
||||
Lexer.prototype.identifierToken = function() {
|
||||
var colon, forcedIdentifier, id, input, match, prev, tag, _ref3, _ref4;
|
||||
if (!(match = IDENTIFIER.exec(this.chunk))) return 0;
|
||||
var colon, forcedIdentifier, id, input, match, prev, tag, _ref2, _ref3;
|
||||
if (!(match = IDENTIFIER.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
input = match[0], id = match[1], colon = match[2];
|
||||
if (id === 'own' && this.tag() === 'FOR') {
|
||||
this.token('OWN', id);
|
||||
return id.length;
|
||||
}
|
||||
forcedIdentifier = colon || (prev = last(this.tokens)) && (((_ref3 = prev[0]) === '.' || _ref3 === '?.' || _ref3 === '::') || !prev.spaced && prev[0] === '@');
|
||||
forcedIdentifier = colon || (prev = last(this.tokens)) && (((_ref2 = prev[0]) === '.' || _ref2 === '?.' || _ref2 === '::') || !prev.spaced && prev[0] === '@');
|
||||
tag = 'IDENTIFIER';
|
||||
if (!forcedIdentifier && (__indexOf.call(JS_KEYWORDS, id) >= 0 || __indexOf.call(COFFEE_KEYWORDS, id) >= 0)) {
|
||||
tag = id.toUpperCase();
|
||||
if (tag === 'WHEN' && (_ref4 = this.tag(), __indexOf.call(LINE_BREAK, _ref4) >= 0)) {
|
||||
if (tag === 'WHEN' && (_ref3 = this.tag(), __indexOf.call(LINE_BREAK, _ref3) >= 0)) {
|
||||
tag = 'LEADING_WHEN';
|
||||
} else if (tag === 'FOR') {
|
||||
this.seenFor = true;
|
||||
@@ -66,17 +77,19 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
if (__indexOf.call(['eval', 'arguments'].concat(JS_FORBIDDEN), id) >= 0) {
|
||||
if (__indexOf.call(JS_FORBIDDEN, id) >= 0) {
|
||||
if (forcedIdentifier) {
|
||||
tag = 'IDENTIFIER';
|
||||
id = new String(id);
|
||||
id.reserved = true;
|
||||
} else if (__indexOf.call(RESERVED, id) >= 0) {
|
||||
this.error("reserved word \"" + word + "\"");
|
||||
this.error("reserved word \"" + id + "\"");
|
||||
}
|
||||
}
|
||||
if (!forcedIdentifier) {
|
||||
if (__indexOf.call(COFFEE_ALIASES, id) >= 0) id = COFFEE_ALIAS_MAP[id];
|
||||
if (__indexOf.call(COFFEE_ALIASES, id) >= 0) {
|
||||
id = COFFEE_ALIAS_MAP[id];
|
||||
}
|
||||
tag = (function() {
|
||||
switch (id) {
|
||||
case '!':
|
||||
@@ -89,12 +102,9 @@
|
||||
return 'LOGIC';
|
||||
case 'true':
|
||||
case 'false':
|
||||
case 'null':
|
||||
case 'undefined':
|
||||
return 'BOOL';
|
||||
case 'break':
|
||||
case 'continue':
|
||||
case 'debugger':
|
||||
return 'STATEMENT';
|
||||
default:
|
||||
return tag;
|
||||
@@ -102,31 +112,51 @@
|
||||
})();
|
||||
}
|
||||
this.token(tag, id);
|
||||
if (colon) this.token(':', ':');
|
||||
if (colon) {
|
||||
this.token(':', ':');
|
||||
}
|
||||
return input.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.numberToken = function() {
|
||||
var binaryLiteral, lexedLength, match, number;
|
||||
if (!(match = NUMBER.exec(this.chunk))) return 0;
|
||||
var binaryLiteral, lexedLength, match, number, octalLiteral;
|
||||
if (!(match = NUMBER.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
number = match[0];
|
||||
if (/^0[BOX]/.test(number)) {
|
||||
this.error("radix prefix '" + number + "' must be lowercase");
|
||||
} else if (/E/.test(number) && !/^0x/.test(number)) {
|
||||
this.error("exponential notation '" + number + "' must be indicated with a lowercase 'e'");
|
||||
} else if (/^0\d*[89]/.test(number)) {
|
||||
this.error("decimal literal '" + number + "' must not be prefixed with '0'");
|
||||
} else if (/^0\d+/.test(number)) {
|
||||
this.error("octal literal '" + number + "' must be prefixed with '0o'");
|
||||
}
|
||||
lexedLength = number.length;
|
||||
if (binaryLiteral = /0b([01]+)/.exec(number)) {
|
||||
number = (parseInt(binaryLiteral[1], 2)).toString();
|
||||
if (octalLiteral = /^0o([0-7]+)/.exec(number)) {
|
||||
number = '0x' + (parseInt(octalLiteral[1], 8)).toString(16);
|
||||
}
|
||||
if (binaryLiteral = /^0b([01]+)/.exec(number)) {
|
||||
number = '0x' + (parseInt(binaryLiteral[1], 2)).toString(16);
|
||||
}
|
||||
this.token('NUMBER', number);
|
||||
return lexedLength;
|
||||
};
|
||||
|
||||
Lexer.prototype.stringToken = function() {
|
||||
var match, string;
|
||||
var match, octalEsc, string;
|
||||
switch (this.chunk.charAt(0)) {
|
||||
case "'":
|
||||
if (!(match = SIMPLESTR.exec(this.chunk))) return 0;
|
||||
if (!(match = SIMPLESTR.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
this.token('STRING', (string = match[0]).replace(MULTILINER, '\\\n'));
|
||||
break;
|
||||
case '"':
|
||||
if (!(string = this.balancedString(this.chunk, '"'))) return 0;
|
||||
if (!(string = this.balancedString(this.chunk, '"'))) {
|
||||
return 0;
|
||||
}
|
||||
if (0 < string.indexOf('#{', 1)) {
|
||||
this.interpolateString(string.slice(1, -1));
|
||||
} else {
|
||||
@@ -136,13 +166,18 @@
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
if (octalEsc = /^(?:\\.|[^\\])*\\(?:0[0-7]|[1-7])/.test(string)) {
|
||||
this.error("octal escape sequences " + string + " are not allowed");
|
||||
}
|
||||
this.line += count(string, '\n');
|
||||
return string.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.heredocToken = function() {
|
||||
var doc, heredoc, match, quote;
|
||||
if (!(match = HEREDOC.exec(this.chunk))) return 0;
|
||||
if (!(match = HEREDOC.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
heredoc = match[0];
|
||||
quote = heredoc.charAt(0);
|
||||
doc = this.sanitizeHeredoc(match[2], {
|
||||
@@ -162,14 +197,15 @@
|
||||
|
||||
Lexer.prototype.commentToken = function() {
|
||||
var comment, here, match;
|
||||
if (!(match = this.chunk.match(COMMENT))) return 0;
|
||||
if (!(match = this.chunk.match(COMMENT))) {
|
||||
return 0;
|
||||
}
|
||||
comment = match[0], here = match[1];
|
||||
if (here) {
|
||||
this.token('HERECOMMENT', this.sanitizeHeredoc(here, {
|
||||
herecomment: true,
|
||||
indent: Array(this.indent + 1).join(' ')
|
||||
}));
|
||||
this.token('TERMINATOR', '\n');
|
||||
}
|
||||
this.line += count(comment, '\n');
|
||||
return comment.length;
|
||||
@@ -181,33 +217,40 @@
|
||||
return 0;
|
||||
}
|
||||
this.token('JS', (script = match[0]).slice(1, -1));
|
||||
this.line += count(script, '\n');
|
||||
return script.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.regexToken = function() {
|
||||
var flags, length, match, prev, regex, _ref3, _ref4;
|
||||
if (this.chunk.charAt(0) !== '/') return 0;
|
||||
var flags, length, match, prev, regex, _ref2, _ref3;
|
||||
if (this.chunk.charAt(0) !== '/') {
|
||||
return 0;
|
||||
}
|
||||
if (match = HEREGEX.exec(this.chunk)) {
|
||||
length = this.heregexToken(match);
|
||||
this.line += count(match[0], '\n');
|
||||
return length;
|
||||
}
|
||||
prev = last(this.tokens);
|
||||
if (prev && (_ref3 = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref3) >= 0)) {
|
||||
if (prev && (_ref2 = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref2) >= 0)) {
|
||||
return 0;
|
||||
}
|
||||
if (!(match = REGEX.exec(this.chunk))) return 0;
|
||||
_ref4 = match, match = _ref4[0], regex = _ref4[1], flags = _ref4[2];
|
||||
if (!(match = REGEX.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
_ref3 = match, match = _ref3[0], regex = _ref3[1], flags = _ref3[2];
|
||||
if (regex.slice(0, 2) === '/*') {
|
||||
this.error('regular expressions cannot begin with `*`');
|
||||
}
|
||||
if (regex === '//') regex = '/(?:)/';
|
||||
if (regex === '//') {
|
||||
regex = '/(?:)/';
|
||||
}
|
||||
this.token('REGEX', "" + regex + flags);
|
||||
return match.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.heregexToken = function(match) {
|
||||
var body, flags, heregex, re, tag, tokens, value, _i, _len, _ref3, _ref4, _ref5, _ref6;
|
||||
var body, flags, heregex, re, tag, tokens, value, _i, _len, _ref2, _ref3, _ref4, _ref5;
|
||||
heregex = match[0], body = match[1], flags = match[2];
|
||||
if (0 > body.indexOf('#{')) {
|
||||
re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/');
|
||||
@@ -220,37 +263,42 @@
|
||||
this.token('IDENTIFIER', 'RegExp');
|
||||
this.tokens.push(['CALL_START', '(']);
|
||||
tokens = [];
|
||||
_ref3 = this.interpolateString(body, {
|
||||
_ref2 = this.interpolateString(body, {
|
||||
regex: true
|
||||
});
|
||||
for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
|
||||
_ref4 = _ref3[_i], tag = _ref4[0], value = _ref4[1];
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
_ref3 = _ref2[_i], tag = _ref3[0], value = _ref3[1];
|
||||
if (tag === 'TOKENS') {
|
||||
tokens.push.apply(tokens, value);
|
||||
} else {
|
||||
if (!(value = value.replace(HEREGEX_OMIT, ''))) continue;
|
||||
if (!(value = value.replace(HEREGEX_OMIT, ''))) {
|
||||
continue;
|
||||
}
|
||||
value = value.replace(/\\/g, '\\\\');
|
||||
tokens.push(['STRING', this.makeString(value, '"', true)]);
|
||||
}
|
||||
tokens.push(['+', '+']);
|
||||
}
|
||||
tokens.pop();
|
||||
if (((_ref5 = tokens[0]) != null ? _ref5[0] : void 0) !== 'STRING') {
|
||||
if (((_ref4 = tokens[0]) != null ? _ref4[0] : void 0) !== 'STRING') {
|
||||
this.tokens.push(['STRING', '""'], ['+', '+']);
|
||||
}
|
||||
(_ref6 = this.tokens).push.apply(_ref6, tokens);
|
||||
if (flags) this.tokens.push([',', ','], ['STRING', '"' + flags + '"']);
|
||||
(_ref5 = this.tokens).push.apply(_ref5, tokens);
|
||||
if (flags) {
|
||||
this.tokens.push([',', ','], ['STRING', '"' + flags + '"']);
|
||||
}
|
||||
this.token(')', ')');
|
||||
return heregex.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.lineToken = function() {
|
||||
var diff, indent, match, noNewlines, prev, size;
|
||||
if (!(match = MULTI_DENT.exec(this.chunk))) return 0;
|
||||
var diff, indent, match, noNewlines, size;
|
||||
if (!(match = MULTI_DENT.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
indent = match[0];
|
||||
this.line += count(indent, '\n');
|
||||
this.seenFor = false;
|
||||
prev = last(this.tokens, 1);
|
||||
size = indent.length - 1 - indent.lastIndexOf('\n');
|
||||
noNewlines = this.unfinished();
|
||||
if (size - this.indebt === this.indent) {
|
||||
@@ -300,7 +348,9 @@
|
||||
this.token('OUTDENT', dent);
|
||||
}
|
||||
}
|
||||
if (dent) this.outdebt -= moveOut;
|
||||
if (dent) {
|
||||
this.outdebt -= moveOut;
|
||||
}
|
||||
while (this.value() === ';') {
|
||||
this.tokens.pop();
|
||||
}
|
||||
@@ -316,7 +366,9 @@
|
||||
return 0;
|
||||
}
|
||||
prev = last(this.tokens);
|
||||
if (prev) prev[match ? 'spaced' : 'newLine'] = true;
|
||||
if (prev) {
|
||||
prev[match ? 'spaced' : 'newLine'] = true;
|
||||
}
|
||||
if (match) {
|
||||
return match[0].length;
|
||||
} else {
|
||||
@@ -328,30 +380,36 @@
|
||||
while (this.value() === ';') {
|
||||
this.tokens.pop();
|
||||
}
|
||||
if (this.tag() !== 'TERMINATOR') this.token('TERMINATOR', '\n');
|
||||
if (this.tag() !== 'TERMINATOR') {
|
||||
this.token('TERMINATOR', '\n');
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
Lexer.prototype.suppressNewlines = function() {
|
||||
if (this.value() === '\\') this.tokens.pop();
|
||||
if (this.value() === '\\') {
|
||||
this.tokens.pop();
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
Lexer.prototype.literalToken = function() {
|
||||
var match, prev, tag, value, _ref3, _ref4, _ref5, _ref6;
|
||||
var match, prev, tag, value, _ref2, _ref3, _ref4, _ref5;
|
||||
if (match = OPERATOR.exec(this.chunk)) {
|
||||
value = match[0];
|
||||
if (CODE.test(value)) this.tagParameters();
|
||||
if (CODE.test(value)) {
|
||||
this.tagParameters();
|
||||
}
|
||||
} else {
|
||||
value = this.chunk.charAt(0);
|
||||
}
|
||||
tag = value;
|
||||
prev = last(this.tokens);
|
||||
if (value === '=' && prev) {
|
||||
if (!prev[1].reserved && (_ref3 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref3) >= 0)) {
|
||||
if (!prev[1].reserved && (_ref2 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref2) >= 0)) {
|
||||
this.error("reserved word \"" + (this.value()) + "\" can't be assigned");
|
||||
}
|
||||
if ((_ref4 = prev[1]) === '||' || _ref4 === '&&') {
|
||||
if ((_ref3 = prev[1]) === '||' || _ref3 === '&&') {
|
||||
prev[0] = 'COMPOUND_ASSIGN';
|
||||
prev[1] += '=';
|
||||
return value.length;
|
||||
@@ -373,10 +431,12 @@
|
||||
} else if (__indexOf.call(LOGIC, value) >= 0 || value === '?' && (prev != null ? prev.spaced : void 0)) {
|
||||
tag = 'LOGIC';
|
||||
} else if (prev && !prev.spaced) {
|
||||
if (value === '(' && (_ref5 = prev[0], __indexOf.call(CALLABLE, _ref5) >= 0)) {
|
||||
if (prev[0] === '?') prev[0] = 'FUNC_EXIST';
|
||||
if (value === '(' && (_ref4 = prev[0], __indexOf.call(CALLABLE, _ref4) >= 0)) {
|
||||
if (prev[0] === '?') {
|
||||
prev[0] = 'FUNC_EXIST';
|
||||
}
|
||||
tag = 'CALL_START';
|
||||
} else if (value === '[' && (_ref6 = prev[0], __indexOf.call(INDEXABLE, _ref6) >= 0)) {
|
||||
} else if (value === '[' && (_ref5 = prev[0], __indexOf.call(INDEXABLE, _ref5) >= 0)) {
|
||||
tag = 'INDEX_START';
|
||||
switch (prev[0]) {
|
||||
case '?':
|
||||
@@ -400,29 +460,37 @@
|
||||
};
|
||||
|
||||
Lexer.prototype.sanitizeHeredoc = function(doc, options) {
|
||||
var attempt, herecomment, indent, match, _ref3;
|
||||
var attempt, herecomment, indent, match, _ref2;
|
||||
indent = options.indent, herecomment = options.herecomment;
|
||||
if (herecomment) {
|
||||
if (HEREDOC_ILLEGAL.test(doc)) {
|
||||
this.error("block comment cannot contain \"*/\", starting");
|
||||
}
|
||||
if (doc.indexOf('\n') <= 0) return doc;
|
||||
if (doc.indexOf('\n') <= 0) {
|
||||
return doc;
|
||||
}
|
||||
} else {
|
||||
while (match = HEREDOC_INDENT.exec(doc)) {
|
||||
attempt = match[1];
|
||||
if (indent === null || (0 < (_ref3 = attempt.length) && _ref3 < indent.length)) {
|
||||
if (indent === null || (0 < (_ref2 = attempt.length) && _ref2 < indent.length)) {
|
||||
indent = attempt;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (indent) doc = doc.replace(RegExp("\\n" + indent, "g"), '\n');
|
||||
if (!herecomment) doc = doc.replace(/^\n/, '');
|
||||
if (indent) {
|
||||
doc = doc.replace(RegExp("\\n" + indent, "g"), '\n');
|
||||
}
|
||||
if (!herecomment) {
|
||||
doc = doc.replace(/^\n/, '');
|
||||
}
|
||||
return doc;
|
||||
};
|
||||
|
||||
Lexer.prototype.tagParameters = function() {
|
||||
var i, stack, tok, tokens;
|
||||
if (this.tag() !== ')') return this;
|
||||
if (this.tag() !== ')') {
|
||||
return this;
|
||||
}
|
||||
stack = [];
|
||||
tokens = this.tokens;
|
||||
i = tokens.length;
|
||||
@@ -452,23 +520,30 @@
|
||||
};
|
||||
|
||||
Lexer.prototype.balancedString = function(str, end) {
|
||||
var i, letter, match, prev, stack, _ref3;
|
||||
var continueCount, i, letter, match, prev, stack, _i, _ref2;
|
||||
continueCount = 0;
|
||||
stack = [end];
|
||||
for (i = 1, _ref3 = str.length; 1 <= _ref3 ? i < _ref3 : i > _ref3; 1 <= _ref3 ? i++ : i--) {
|
||||
for (i = _i = 1, _ref2 = str.length; 1 <= _ref2 ? _i < _ref2 : _i > _ref2; i = 1 <= _ref2 ? ++_i : --_i) {
|
||||
if (continueCount) {
|
||||
--continueCount;
|
||||
continue;
|
||||
}
|
||||
switch (letter = str.charAt(i)) {
|
||||
case '\\':
|
||||
i++;
|
||||
++continueCount;
|
||||
continue;
|
||||
case end:
|
||||
stack.pop();
|
||||
if (!stack.length) return str.slice(0, i + 1);
|
||||
if (!stack.length) {
|
||||
return str.slice(0, +i + 1 || 9e9);
|
||||
}
|
||||
end = stack[stack.length - 1];
|
||||
continue;
|
||||
}
|
||||
if (end === '}' && (letter === '"' || letter === "'")) {
|
||||
stack.push(end = letter);
|
||||
} else if (end === '}' && letter === '/' && (match = HEREGEX.exec(str.slice(i)) || REGEX.exec(str.slice(i)))) {
|
||||
i += match[0].length - 1;
|
||||
continueCount += match[0].length - 1;
|
||||
} else if (end === '}' && letter === '{') {
|
||||
stack.push(end = '}');
|
||||
} else if (end === '"' && prev === '#' && letter === '{') {
|
||||
@@ -480,8 +555,10 @@
|
||||
};
|
||||
|
||||
Lexer.prototype.interpolateString = function(str, options) {
|
||||
var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _len, _ref3, _ref4, _ref5;
|
||||
if (options == null) options = {};
|
||||
var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _i, _len, _ref2, _ref3, _ref4;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
heredoc = options.heredoc, regex = options.regex;
|
||||
tokens = [];
|
||||
pi = 0;
|
||||
@@ -494,7 +571,9 @@
|
||||
if (!(letter === '#' && str.charAt(i + 1) === '{' && (expr = this.balancedString(str.slice(i + 1), '}')))) {
|
||||
continue;
|
||||
}
|
||||
if (pi < i) tokens.push(['NEOSTRING', str.slice(pi, i)]);
|
||||
if (pi < i) {
|
||||
tokens.push(['NEOSTRING', str.slice(pi, i)]);
|
||||
}
|
||||
inner = expr.slice(1, -1);
|
||||
if (inner.length) {
|
||||
nested = new Lexer().tokenize(inner, {
|
||||
@@ -502,13 +581,13 @@
|
||||
rewrite: false
|
||||
});
|
||||
nested.pop();
|
||||
if (((_ref3 = nested[0]) != null ? _ref3[0] : void 0) === 'TERMINATOR') {
|
||||
if (((_ref2 = nested[0]) != null ? _ref2[0] : void 0) === 'TERMINATOR') {
|
||||
nested.shift();
|
||||
}
|
||||
if (len = nested.length) {
|
||||
if (len > 1) {
|
||||
nested.unshift(['(', '(']);
|
||||
nested.push([')', ')']);
|
||||
nested.unshift(['(', '(', this.line]);
|
||||
nested.push([')', ')', this.line]);
|
||||
}
|
||||
tokens.push(['TOKENS', nested]);
|
||||
}
|
||||
@@ -516,28 +595,44 @@
|
||||
i += expr.length;
|
||||
pi = i + 1;
|
||||
}
|
||||
if ((i > pi && pi < str.length)) tokens.push(['NEOSTRING', str.slice(pi)]);
|
||||
if (regex) return tokens;
|
||||
if (!tokens.length) return this.token('STRING', '""');
|
||||
if (tokens[0][0] !== 'NEOSTRING') tokens.unshift(['', '']);
|
||||
if (interpolated = tokens.length > 1) this.token('(', '(');
|
||||
for (i = 0, _len = tokens.length; i < _len; i++) {
|
||||
_ref4 = tokens[i], tag = _ref4[0], value = _ref4[1];
|
||||
if (i) this.token('+', '+');
|
||||
if ((i > pi && pi < str.length)) {
|
||||
tokens.push(['NEOSTRING', str.slice(pi)]);
|
||||
}
|
||||
if (regex) {
|
||||
return tokens;
|
||||
}
|
||||
if (!tokens.length) {
|
||||
return this.token('STRING', '""');
|
||||
}
|
||||
if (tokens[0][0] !== 'NEOSTRING') {
|
||||
tokens.unshift(['', '']);
|
||||
}
|
||||
if (interpolated = tokens.length > 1) {
|
||||
this.token('(', '(');
|
||||
}
|
||||
for (i = _i = 0, _len = tokens.length; _i < _len; i = ++_i) {
|
||||
_ref3 = tokens[i], tag = _ref3[0], value = _ref3[1];
|
||||
if (i) {
|
||||
this.token('+', '+');
|
||||
}
|
||||
if (tag === 'TOKENS') {
|
||||
(_ref5 = this.tokens).push.apply(_ref5, value);
|
||||
(_ref4 = this.tokens).push.apply(_ref4, value);
|
||||
} else {
|
||||
this.token('STRING', this.makeString(value, '"', heredoc));
|
||||
}
|
||||
}
|
||||
if (interpolated) this.token(')', ')');
|
||||
if (interpolated) {
|
||||
this.token(')', ')');
|
||||
}
|
||||
return tokens;
|
||||
};
|
||||
|
||||
Lexer.prototype.pair = function(tag) {
|
||||
var size, wanted;
|
||||
if (tag !== (wanted = last(this.ends))) {
|
||||
if ('OUTDENT' !== wanted) this.error("unmatched " + tag);
|
||||
if ('OUTDENT' !== wanted) {
|
||||
this.error("unmatched " + tag);
|
||||
}
|
||||
this.indent -= size = last(this.indents);
|
||||
this.outdentToken(size, true);
|
||||
return this.pair(tag);
|
||||
@@ -560,8 +655,8 @@
|
||||
};
|
||||
|
||||
Lexer.prototype.unfinished = function() {
|
||||
var _ref3;
|
||||
return LINE_CONTINUER.test(this.chunk) || ((_ref3 = this.tag()) === '\\' || _ref3 === '.' || _ref3 === '?.' || _ref3 === 'UNARY' || _ref3 === 'MATH' || _ref3 === '+' || _ref3 === '-' || _ref3 === 'SHIFT' || _ref3 === 'RELATION' || _ref3 === 'COMPARE' || _ref3 === 'LOGIC' || _ref3 === 'COMPOUND_ASSIGN' || _ref3 === 'THROW' || _ref3 === 'EXTENDS');
|
||||
var _ref2;
|
||||
return LINE_CONTINUER.test(this.chunk) || ((_ref2 = this.tag()) === '\\' || _ref2 === '.' || _ref2 === '?.' || _ref2 === 'UNARY' || _ref2 === 'MATH' || _ref2 === '+' || _ref2 === '-' || _ref2 === 'SHIFT' || _ref2 === 'RELATION' || _ref2 === 'COMPARE' || _ref2 === 'LOGIC' || _ref2 === 'THROW' || _ref2 === 'EXTENDS');
|
||||
};
|
||||
|
||||
Lexer.prototype.escapeLines = function(str, heredoc) {
|
||||
@@ -569,7 +664,9 @@
|
||||
};
|
||||
|
||||
Lexer.prototype.makeString = function(body, quote, heredoc) {
|
||||
if (!body) return quote + quote;
|
||||
if (!body) {
|
||||
return quote + quote;
|
||||
}
|
||||
body = body.replace(/\\([\s\S])/g, function(match, contents) {
|
||||
if (contents === '\n' || contents === quote) {
|
||||
return contents;
|
||||
@@ -616,15 +713,19 @@
|
||||
|
||||
COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat(COFFEE_ALIASES);
|
||||
|
||||
RESERVED = ['case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', '__hasProp', '__extends', '__slice', '__bind', '__indexOf'];
|
||||
RESERVED = ['case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', '__hasProp', '__extends', '__slice', '__bind', '__indexOf', 'implements', 'interface', 'package', 'private', 'protected', 'public', 'static', 'yield'];
|
||||
|
||||
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED);
|
||||
STRICT_PROSCRIBED = ['arguments', 'eval'];
|
||||
|
||||
exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS);
|
||||
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED);
|
||||
|
||||
exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS).concat(STRICT_PROSCRIBED);
|
||||
|
||||
exports.STRICT_PROSCRIBED = STRICT_PROSCRIBED;
|
||||
|
||||
IDENTIFIER = /^([$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)([^\n\S]*:(?!:))?/;
|
||||
|
||||
NUMBER = /^0x[\da-f]+|^0b[01]+|^\d*\.?\d+(?:e[+-]?\d+)?/i;
|
||||
NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\da-f]+|^\d*\.?\d+(?:e[+-]?\d+)?/i;
|
||||
|
||||
HEREDOC = /^("""|''')([\s\S]*?)(?:\n[^\n\S]*)?\1/;
|
||||
|
||||
@@ -672,15 +773,15 @@
|
||||
|
||||
RELATION = ['IN', 'OF', 'INSTANCEOF'];
|
||||
|
||||
BOOL = ['TRUE', 'FALSE', 'NULL', 'UNDEFINED'];
|
||||
BOOL = ['TRUE', 'FALSE'];
|
||||
|
||||
NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', '++', '--', ']'];
|
||||
NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', 'NULL', 'UNDEFINED', '++', '--', ']'];
|
||||
|
||||
NOT_SPACED_REGEX = NOT_REGEX.concat(')', '}', 'THIS', 'IDENTIFIER', 'STRING');
|
||||
|
||||
CALLABLE = ['IDENTIFIER', 'STRING', 'REGEX', ')', ']', '}', '?', '::', '@', 'THIS', 'SUPER'];
|
||||
|
||||
INDEXABLE = CALLABLE.concat('NUMBER', 'BOOL');
|
||||
INDEXABLE = CALLABLE.concat('NUMBER', 'BOOL', 'NULL', 'UNDEFINED');
|
||||
|
||||
LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'];
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments;
|
||||
|
||||
@@ -9,39 +10,48 @@
|
||||
}
|
||||
|
||||
OptionParser.prototype.parse = function(args) {
|
||||
var arg, i, isOption, matchedRule, options, originalArgs, pos, rule, value, _i, _len, _len2, _ref;
|
||||
var arg, i, isOption, matchedRule, options, originalArgs, pos, rule, seenNonOptionArg, skippingArgument, value, _i, _j, _len, _len1, _ref;
|
||||
options = {
|
||||
arguments: [],
|
||||
literals: []
|
||||
"arguments": []
|
||||
};
|
||||
skippingArgument = false;
|
||||
originalArgs = args;
|
||||
args = normalizeArguments(args);
|
||||
for (i = 0, _len = args.length; i < _len; i++) {
|
||||
for (i = _i = 0, _len = args.length; _i < _len; i = ++_i) {
|
||||
arg = args[i];
|
||||
if (skippingArgument) {
|
||||
skippingArgument = false;
|
||||
continue;
|
||||
}
|
||||
if (arg === '--') {
|
||||
pos = originalArgs.indexOf('--');
|
||||
options.arguments = [originalArgs[1 + pos]];
|
||||
options.literals = originalArgs.slice(2 + pos);
|
||||
options["arguments"] = options["arguments"].concat(originalArgs.slice(pos + 1));
|
||||
break;
|
||||
}
|
||||
isOption = !!(arg.match(LONG_FLAG) || arg.match(SHORT_FLAG));
|
||||
matchedRule = false;
|
||||
_ref = this.rules;
|
||||
for (_i = 0, _len2 = _ref.length; _i < _len2; _i++) {
|
||||
rule = _ref[_i];
|
||||
if (rule.shortFlag === arg || rule.longFlag === arg) {
|
||||
value = rule.hasArgument ? args[i += 1] : true;
|
||||
options[rule.name] = rule.isList ? (options[rule.name] || []).concat(value) : value;
|
||||
matchedRule = true;
|
||||
break;
|
||||
seenNonOptionArg = options["arguments"].length > 0;
|
||||
if (!seenNonOptionArg) {
|
||||
matchedRule = false;
|
||||
_ref = this.rules;
|
||||
for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
|
||||
rule = _ref[_j];
|
||||
if (rule.shortFlag === arg || rule.longFlag === arg) {
|
||||
value = true;
|
||||
if (rule.hasArgument) {
|
||||
skippingArgument = true;
|
||||
value = args[i + 1];
|
||||
}
|
||||
options[rule.name] = rule.isList ? (options[rule.name] || []).concat(value) : value;
|
||||
matchedRule = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isOption && !matchedRule) {
|
||||
throw new Error("unrecognized option: " + arg);
|
||||
}
|
||||
}
|
||||
if (isOption && !matchedRule) {
|
||||
throw new Error("unrecognized option: " + arg);
|
||||
}
|
||||
if (!isOption) {
|
||||
options.arguments = originalArgs.slice(originalArgs.indexOf(arg));
|
||||
break;
|
||||
if (seenNonOptionArg || !isOption) {
|
||||
options["arguments"].push(arg);
|
||||
}
|
||||
}
|
||||
return options;
|
||||
@@ -50,7 +60,9 @@
|
||||
OptionParser.prototype.help = function() {
|
||||
var letPart, lines, rule, spaces, _i, _len, _ref;
|
||||
lines = [];
|
||||
if (this.banner) lines.unshift("" + this.banner + "\n");
|
||||
if (this.banner) {
|
||||
lines.unshift("" + this.banner + "\n");
|
||||
}
|
||||
_ref = this.rules;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
rule = _ref[_i];
|
||||
@@ -66,9 +78,9 @@
|
||||
|
||||
})();
|
||||
|
||||
LONG_FLAG = /^(--\w[\w\-]+)/;
|
||||
LONG_FLAG = /^(--\w[\w\-]*)/;
|
||||
|
||||
SHORT_FLAG = /^(-\w)/;
|
||||
SHORT_FLAG = /^(-\w)$/;
|
||||
|
||||
MULTI_FLAG = /^-(\w{2,})/;
|
||||
|
||||
@@ -79,7 +91,9 @@
|
||||
_results = [];
|
||||
for (_i = 0, _len = rules.length; _i < _len; _i++) {
|
||||
tuple = rules[_i];
|
||||
if (tuple.length < 3) tuple.unshift(null);
|
||||
if (tuple.length < 3) {
|
||||
tuple.unshift(null);
|
||||
}
|
||||
_results.push(buildRule.apply(null, tuple));
|
||||
}
|
||||
return _results;
|
||||
@@ -87,7 +101,9 @@
|
||||
|
||||
buildRule = function(shortFlag, longFlag, description, options) {
|
||||
var match;
|
||||
if (options == null) options = {};
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
match = longFlag.match(OPTIONAL);
|
||||
longFlag = longFlag.match(LONG_FLAG)[1];
|
||||
return {
|
||||
@@ -101,14 +117,14 @@
|
||||
};
|
||||
|
||||
normalizeArguments = function(args) {
|
||||
var arg, l, match, result, _i, _j, _len, _len2, _ref;
|
||||
var arg, l, match, result, _i, _j, _len, _len1, _ref;
|
||||
args = args.slice(0);
|
||||
result = [];
|
||||
for (_i = 0, _len = args.length; _i < _len; _i++) {
|
||||
arg = args[_i];
|
||||
if (match = arg.match(MULTI_FLAG)) {
|
||||
_ref = match[1].split('');
|
||||
for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) {
|
||||
for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
|
||||
l = _ref[_j];
|
||||
result.push('-' + l);
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,5 +1,11 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var ACCESSOR, CoffeeScript, Module, REPL_PROMPT, REPL_PROMPT_CONTINUATION, SIMPLEVAR, Script, autocomplete, backlog, completeAttribute, completeVariable, enableColours, error, getCompletions, inspect, readline, repl, run, stdin, stdout;
|
||||
var ACCESSOR, CoffeeScript, Module, REPL_PROMPT, REPL_PROMPT_CONTINUATION, REPL_PROMPT_MULTILINE, SIMPLEVAR, Script, autocomplete, backlog, completeAttribute, completeVariable, enableColours, error, getCompletions, inspect, multilineMode, pipedInput, readline, repl, run, stdin, stdout,
|
||||
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
|
||||
stdin = process.openStdin();
|
||||
|
||||
stdout = process.stdout;
|
||||
|
||||
CoffeeScript = require('./coffee-script');
|
||||
|
||||
@@ -13,6 +19,8 @@
|
||||
|
||||
REPL_PROMPT = 'coffee> ';
|
||||
|
||||
REPL_PROMPT_MULTILINE = '------> ';
|
||||
|
||||
REPL_PROMPT_CONTINUATION = '......> ';
|
||||
|
||||
enableColours = false;
|
||||
@@ -21,18 +29,104 @@
|
||||
enableColours = !process.env.NODE_DISABLE_COLORS;
|
||||
}
|
||||
|
||||
stdin = process.openStdin();
|
||||
|
||||
stdout = process.stdout;
|
||||
|
||||
error = function(err) {
|
||||
return stdout.write((err.stack || err.toString()) + '\n');
|
||||
};
|
||||
|
||||
ACCESSOR = /\s*([\w\.]+)(?:\.(\w*))$/;
|
||||
|
||||
SIMPLEVAR = /(\w+)$/i;
|
||||
|
||||
autocomplete = function(text) {
|
||||
return completeAttribute(text) || completeVariable(text) || [[], text];
|
||||
};
|
||||
|
||||
completeAttribute = function(text) {
|
||||
var all, candidates, completions, key, match, obj, prefix, _i, _len, _ref;
|
||||
if (match = text.match(ACCESSOR)) {
|
||||
all = match[0], obj = match[1], prefix = match[2];
|
||||
try {
|
||||
obj = Script.runInThisContext(obj);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
obj = Object(obj);
|
||||
candidates = Object.getOwnPropertyNames(obj);
|
||||
while (obj = Object.getPrototypeOf(obj)) {
|
||||
_ref = Object.getOwnPropertyNames(obj);
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
key = _ref[_i];
|
||||
if (__indexOf.call(candidates, key) < 0) {
|
||||
candidates.push(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
completions = getCompletions(prefix, candidates);
|
||||
return [completions, prefix];
|
||||
}
|
||||
};
|
||||
|
||||
completeVariable = function(text) {
|
||||
var candidates, completions, free, key, keywords, r, vars, _i, _len, _ref;
|
||||
free = (_ref = text.match(SIMPLEVAR)) != null ? _ref[1] : void 0;
|
||||
if (text === "") {
|
||||
free = "";
|
||||
}
|
||||
if (free != null) {
|
||||
vars = Script.runInThisContext('Object.getOwnPropertyNames(Object(this))');
|
||||
keywords = (function() {
|
||||
var _i, _len, _ref1, _results;
|
||||
_ref1 = CoffeeScript.RESERVED;
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||
r = _ref1[_i];
|
||||
if (r.slice(0, 2) !== '__') {
|
||||
_results.push(r);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
candidates = vars;
|
||||
for (_i = 0, _len = keywords.length; _i < _len; _i++) {
|
||||
key = keywords[_i];
|
||||
if (__indexOf.call(candidates, key) < 0) {
|
||||
candidates.push(key);
|
||||
}
|
||||
}
|
||||
completions = getCompletions(free, candidates);
|
||||
return [completions, free];
|
||||
}
|
||||
};
|
||||
|
||||
getCompletions = function(prefix, candidates) {
|
||||
var el, _i, _len, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = candidates.length; _i < _len; _i++) {
|
||||
el = candidates[_i];
|
||||
if (0 === el.indexOf(prefix)) {
|
||||
_results.push(el);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
|
||||
process.on('uncaughtException', error);
|
||||
|
||||
backlog = '';
|
||||
|
||||
run = function(buffer) {
|
||||
var code, returnValue, _;
|
||||
buffer = buffer.replace(/(^|[\r\n]+)(\s*)##?(?:[^#\r\n][^\r\n]*|)($|[\r\n])/, "$1$2$3");
|
||||
buffer = buffer.replace(/[\r\n]+$/, "");
|
||||
if (multilineMode) {
|
||||
backlog += "" + buffer + "\n";
|
||||
repl.setPrompt(REPL_PROMPT_CONTINUATION);
|
||||
repl.prompt();
|
||||
return;
|
||||
}
|
||||
if (!buffer.toString().trim() && !backlog) {
|
||||
repl.prompt();
|
||||
return;
|
||||
@@ -48,96 +142,129 @@
|
||||
backlog = '';
|
||||
try {
|
||||
_ = global._;
|
||||
returnValue = CoffeeScript.eval("_=(" + code + "\n)", {
|
||||
returnValue = CoffeeScript["eval"]("_=(" + code + "\n)", {
|
||||
filename: 'repl',
|
||||
modulename: 'repl'
|
||||
});
|
||||
if (returnValue === void 0) global._ = _;
|
||||
process.stdout.write(inspect(returnValue, false, 2, enableColours) + '\n');
|
||||
if (returnValue === void 0) {
|
||||
global._ = _;
|
||||
}
|
||||
repl.output.write("" + (inspect(returnValue, false, 2, enableColours)) + "\n");
|
||||
} catch (err) {
|
||||
error(err);
|
||||
}
|
||||
return repl.prompt();
|
||||
};
|
||||
|
||||
ACCESSOR = /\s*([\w\.]+)(?:\.(\w*))$/;
|
||||
|
||||
SIMPLEVAR = /\s*(\w*)$/i;
|
||||
|
||||
autocomplete = function(text) {
|
||||
return completeAttribute(text) || completeVariable(text) || [[], text];
|
||||
};
|
||||
|
||||
completeAttribute = function(text) {
|
||||
var all, completions, match, obj, prefix, val;
|
||||
if (match = text.match(ACCESSOR)) {
|
||||
all = match[0], obj = match[1], prefix = match[2];
|
||||
try {
|
||||
val = Script.runInThisContext(obj);
|
||||
} catch (error) {
|
||||
if (stdin.readable && stdin.isRaw) {
|
||||
pipedInput = '';
|
||||
repl = {
|
||||
prompt: function() {
|
||||
return stdout.write(this._prompt);
|
||||
},
|
||||
setPrompt: function(p) {
|
||||
return this._prompt = p;
|
||||
},
|
||||
input: stdin,
|
||||
output: stdout,
|
||||
on: function() {}
|
||||
};
|
||||
stdin.on('data', function(chunk) {
|
||||
var line, lines, _i, _len, _ref;
|
||||
pipedInput += chunk;
|
||||
if (!/\n/.test(pipedInput)) {
|
||||
return;
|
||||
}
|
||||
completions = getCompletions(prefix, Object.getOwnPropertyNames(val));
|
||||
return [completions, prefix];
|
||||
}
|
||||
};
|
||||
|
||||
completeVariable = function(text) {
|
||||
var completions, free, keywords, possibilities, r, vars, _ref;
|
||||
free = (_ref = text.match(SIMPLEVAR)) != null ? _ref[1] : void 0;
|
||||
if (free != null) {
|
||||
vars = Script.runInThisContext('Object.getOwnPropertyNames(this)');
|
||||
keywords = (function() {
|
||||
var _i, _len, _ref2, _results;
|
||||
_ref2 = CoffeeScript.RESERVED;
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
r = _ref2[_i];
|
||||
if (r.slice(0, 2) !== '__') _results.push(r);
|
||||
lines = pipedInput.split("\n");
|
||||
pipedInput = lines[lines.length - 1];
|
||||
_ref = lines.slice(0, -1);
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
line = _ref[_i];
|
||||
if (!(line)) {
|
||||
continue;
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
possibilities = vars.concat(keywords);
|
||||
completions = getCompletions(free, possibilities);
|
||||
return [completions, free];
|
||||
}
|
||||
};
|
||||
|
||||
getCompletions = function(prefix, candidates) {
|
||||
var el, _i, _len, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = candidates.length; _i < _len; _i++) {
|
||||
el = candidates[_i];
|
||||
if (el.indexOf(prefix) === 0) _results.push(el);
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
|
||||
process.on('uncaughtException', error);
|
||||
|
||||
if (readline.createInterface.length < 3) {
|
||||
repl = readline.createInterface(stdin, autocomplete);
|
||||
stdin.on('data', function(buffer) {
|
||||
return repl.write(buffer);
|
||||
stdout.write("" + line + "\n");
|
||||
run(line);
|
||||
}
|
||||
});
|
||||
stdin.on('end', function() {
|
||||
var line, _i, _len, _ref;
|
||||
_ref = pipedInput.trim().split("\n");
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
line = _ref[_i];
|
||||
if (!(line)) {
|
||||
continue;
|
||||
}
|
||||
stdout.write("" + line + "\n");
|
||||
run(line);
|
||||
}
|
||||
stdout.write('\n');
|
||||
return process.exit(0);
|
||||
});
|
||||
} else {
|
||||
repl = readline.createInterface(stdin, stdout, autocomplete);
|
||||
if (readline.createInterface.length < 3) {
|
||||
repl = readline.createInterface(stdin, autocomplete);
|
||||
stdin.on('data', function(buffer) {
|
||||
return repl.write(buffer);
|
||||
});
|
||||
} else {
|
||||
repl = readline.createInterface(stdin, stdout, autocomplete);
|
||||
}
|
||||
}
|
||||
|
||||
multilineMode = false;
|
||||
|
||||
repl.input.on('keypress', function(char, key) {
|
||||
var cursorPos, newPrompt;
|
||||
if (!(key && key.ctrl && !key.meta && !key.shift && key.name === 'v')) {
|
||||
return;
|
||||
}
|
||||
cursorPos = repl.cursor;
|
||||
repl.output.cursorTo(0);
|
||||
repl.output.clearLine(1);
|
||||
multilineMode = !multilineMode;
|
||||
if (!multilineMode && backlog) {
|
||||
repl._line();
|
||||
}
|
||||
backlog = '';
|
||||
repl.setPrompt((newPrompt = multilineMode ? REPL_PROMPT_MULTILINE : REPL_PROMPT));
|
||||
repl.prompt();
|
||||
return repl.output.cursorTo(newPrompt.length + (repl.cursor = cursorPos));
|
||||
});
|
||||
|
||||
repl.input.on('keypress', function(char, key) {
|
||||
if (!(multilineMode && repl.line)) {
|
||||
return;
|
||||
}
|
||||
if (!(key && key.ctrl && !key.meta && !key.shift && key.name === 'd')) {
|
||||
return;
|
||||
}
|
||||
multilineMode = false;
|
||||
return repl._line();
|
||||
});
|
||||
|
||||
repl.on('attemptClose', function() {
|
||||
if (backlog) {
|
||||
if (multilineMode) {
|
||||
multilineMode = false;
|
||||
repl.output.cursorTo(0);
|
||||
repl.output.clearLine(1);
|
||||
repl._onLine(repl.line);
|
||||
return;
|
||||
}
|
||||
if (backlog || repl.line) {
|
||||
backlog = '';
|
||||
process.stdout.write('\n');
|
||||
repl.historyIndex = -1;
|
||||
repl.setPrompt(REPL_PROMPT);
|
||||
return repl.prompt();
|
||||
repl.output.write('\n(^C again to quit)');
|
||||
return repl._line((repl.line = ''));
|
||||
} else {
|
||||
return repl.close();
|
||||
}
|
||||
});
|
||||
|
||||
repl.on('close', function() {
|
||||
process.stdout.write('\n');
|
||||
return stdin.destroy();
|
||||
repl.output.write('\n');
|
||||
return repl.input.destroy();
|
||||
});
|
||||
|
||||
repl.on('line', run);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref;
|
||||
var __hasProp = Object.prototype.hasOwnProperty, __indexOf = Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (__hasProp.call(this, i) && this[i] === item) return i; } return -1; }, __slice = Array.prototype.slice;
|
||||
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref,
|
||||
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
|
||||
__slice = [].slice;
|
||||
|
||||
exports.Rewriter = (function() {
|
||||
|
||||
@@ -30,17 +32,19 @@
|
||||
};
|
||||
|
||||
Rewriter.prototype.detectEnd = function(i, condition, action) {
|
||||
var levels, token, tokens, _ref, _ref2;
|
||||
var levels, token, tokens, _ref, _ref1;
|
||||
tokens = this.tokens;
|
||||
levels = 0;
|
||||
while (token = tokens[i]) {
|
||||
if (levels === 0 && condition.call(this, token, i)) {
|
||||
return action.call(this, token, i);
|
||||
}
|
||||
if (!token || levels < 0) return action.call(this, token, i - 1);
|
||||
if (!token || levels < 0) {
|
||||
return action.call(this, token, i - 1);
|
||||
}
|
||||
if (_ref = token[0], __indexOf.call(EXPRESSION_START, _ref) >= 0) {
|
||||
levels += 1;
|
||||
} else if (_ref2 = token[0], __indexOf.call(EXPRESSION_END, _ref2) >= 0) {
|
||||
} else if (_ref1 = token[0], __indexOf.call(EXPRESSION_END, _ref1) >= 0) {
|
||||
levels -= 1;
|
||||
}
|
||||
i += 1;
|
||||
@@ -49,13 +53,17 @@
|
||||
};
|
||||
|
||||
Rewriter.prototype.removeLeadingNewlines = function() {
|
||||
var i, tag, _len, _ref;
|
||||
var i, tag, _i, _len, _ref;
|
||||
_ref = this.tokens;
|
||||
for (i = 0, _len = _ref.length; i < _len; i++) {
|
||||
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
|
||||
tag = _ref[i][0];
|
||||
if (tag !== 'TERMINATOR') break;
|
||||
if (tag !== 'TERMINATOR') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i) {
|
||||
return this.tokens.splice(0, i);
|
||||
}
|
||||
if (i) return this.tokens.splice(0, i);
|
||||
};
|
||||
|
||||
Rewriter.prototype.removeMidExpressionNewlines = function() {
|
||||
@@ -79,7 +87,9 @@
|
||||
return this.tokens[token[0] === 'OUTDENT' ? i - 1 : i][0] = 'CALL_END';
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
if (token[0] === 'CALL_START') this.detectEnd(i + 1, condition, action);
|
||||
if (token[0] === 'CALL_START') {
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
@@ -94,31 +104,40 @@
|
||||
return token[0] = 'INDEX_END';
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
if (token[0] === 'INDEX_START') this.detectEnd(i + 1, condition, action);
|
||||
if (token[0] === 'INDEX_START') {
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.addImplicitBraces = function() {
|
||||
var action, condition, stack, start, startIndent;
|
||||
var action, condition, sameLine, stack, start, startIndent, startIndex, startsLine;
|
||||
stack = [];
|
||||
start = null;
|
||||
startsLine = null;
|
||||
sameLine = true;
|
||||
startIndent = 0;
|
||||
startIndex = 0;
|
||||
condition = function(token, i) {
|
||||
var one, tag, three, two, _ref, _ref2;
|
||||
_ref = this.tokens.slice(i + 1, (i + 3) + 1 || 9e9), one = _ref[0], two = _ref[1], three = _ref[2];
|
||||
if ('HERECOMMENT' === (one != null ? one[0] : void 0)) return false;
|
||||
var one, tag, three, two, _ref, _ref1;
|
||||
_ref = this.tokens.slice(i + 1, +(i + 3) + 1 || 9e9), one = _ref[0], two = _ref[1], three = _ref[2];
|
||||
if ('HERECOMMENT' === (one != null ? one[0] : void 0)) {
|
||||
return false;
|
||||
}
|
||||
tag = token[0];
|
||||
return ((tag === 'TERMINATOR' || tag === 'OUTDENT') && !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':')) || (tag === ',' && one && ((_ref2 = one[0]) !== 'IDENTIFIER' && _ref2 !== 'NUMBER' && _ref2 !== 'STRING' && _ref2 !== '@' && _ref2 !== 'TERMINATOR' && _ref2 !== 'OUTDENT'));
|
||||
if (__indexOf.call(LINEBREAKS, tag) >= 0) {
|
||||
sameLine = false;
|
||||
}
|
||||
return (((tag === 'TERMINATOR' || tag === 'OUTDENT') || (__indexOf.call(IMPLICIT_END, tag) >= 0 && sameLine && !(i - startIndex === 1))) && ((!startsLine && this.tag(i - 1) !== ',') || !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':'))) || (tag === ',' && one && ((_ref1 = one[0]) !== 'IDENTIFIER' && _ref1 !== 'NUMBER' && _ref1 !== 'STRING' && _ref1 !== '@' && _ref1 !== 'TERMINATOR' && _ref1 !== 'OUTDENT'));
|
||||
};
|
||||
action = function(token, i) {
|
||||
var tok;
|
||||
tok = ['}', '}', token[2]];
|
||||
tok.generated = true;
|
||||
tok = this.generate('}', '}', token[2]);
|
||||
return this.tokens.splice(i, 0, tok);
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var ago, idx, tag, tok, value, _ref, _ref2;
|
||||
var ago, idx, prevTag, tag, tok, value, _ref, _ref1;
|
||||
if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) {
|
||||
stack.push([(tag === 'INDENT' && this.tag(i - 1) === '{' ? '{' : tag), i]);
|
||||
return 1;
|
||||
@@ -127,18 +146,21 @@
|
||||
start = stack.pop();
|
||||
return 1;
|
||||
}
|
||||
if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref2 = stack[stack.length - 1]) != null ? _ref2[0] : void 0) !== '{'))) {
|
||||
if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref1 = stack[stack.length - 1]) != null ? _ref1[0] : void 0) !== '{'))) {
|
||||
return 1;
|
||||
}
|
||||
sameLine = true;
|
||||
startIndex = i + 1;
|
||||
stack.push(['{']);
|
||||
idx = ago === '@' ? i - 2 : i - 1;
|
||||
while (this.tag(idx - 2) === 'HERECOMMENT') {
|
||||
idx -= 2;
|
||||
}
|
||||
prevTag = this.tag(idx - 1);
|
||||
startsLine = !prevTag || (__indexOf.call(LINEBREAKS, prevTag) >= 0);
|
||||
value = new String('{');
|
||||
value.generated = true;
|
||||
tok = ['{', value, token[2]];
|
||||
tok.generated = true;
|
||||
tok = this.generate('{', value, token[2]);
|
||||
tokens.splice(idx, 0, tok);
|
||||
this.detectEnd(i + 2, condition, action);
|
||||
return 2;
|
||||
@@ -146,49 +168,71 @@
|
||||
};
|
||||
|
||||
Rewriter.prototype.addImplicitParentheses = function() {
|
||||
var action, noCall;
|
||||
noCall = false;
|
||||
var action, condition, noCall, seenControl, seenSingle;
|
||||
noCall = seenSingle = seenControl = false;
|
||||
condition = function(token, i) {
|
||||
var post, tag, _ref, _ref1;
|
||||
tag = token[0];
|
||||
if (!seenSingle && token.fromThen) {
|
||||
return true;
|
||||
}
|
||||
if (tag === 'IF' || tag === 'ELSE' || tag === 'CATCH' || tag === '->' || tag === '=>' || tag === 'CLASS') {
|
||||
seenSingle = true;
|
||||
}
|
||||
if (tag === 'IF' || tag === 'ELSE' || tag === 'SWITCH' || tag === 'TRY' || tag === '=') {
|
||||
seenControl = true;
|
||||
}
|
||||
if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') {
|
||||
return true;
|
||||
}
|
||||
return !token.generated && this.tag(i - 1) !== ',' && (__indexOf.call(IMPLICIT_END, tag) >= 0 || (tag === 'INDENT' && !seenControl)) && (tag !== 'INDENT' || (((_ref = this.tag(i - 2)) !== 'CLASS' && _ref !== 'EXTENDS') && (_ref1 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref1) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
|
||||
};
|
||||
action = function(token, i) {
|
||||
return this.tokens.splice(i, 0, ['CALL_END', ')', token[2]]);
|
||||
return this.tokens.splice(i, 0, this.generate('CALL_END', ')', token[2]));
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var callObject, current, next, prev, seenControl, seenSingle, tag, _ref, _ref2, _ref3;
|
||||
var callObject, current, next, prev, tag, _ref, _ref1, _ref2;
|
||||
tag = token[0];
|
||||
if (tag === 'CLASS' || tag === 'IF') noCall = true;
|
||||
_ref = tokens.slice(i - 1, (i + 1) + 1 || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2];
|
||||
callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0);
|
||||
if (tag === 'CLASS' || tag === 'IF' || tag === 'FOR' || tag === 'WHILE') {
|
||||
noCall = true;
|
||||
}
|
||||
_ref = tokens.slice(i - 1, +(i + 1) + 1 || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2];
|
||||
callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref1 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref1) >= 0);
|
||||
seenSingle = false;
|
||||
seenControl = false;
|
||||
if (__indexOf.call(LINEBREAKS, tag) >= 0) noCall = false;
|
||||
if (prev && !prev.spaced && tag === '?') token.call = true;
|
||||
if (token.fromThen) return 1;
|
||||
if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref3 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref3) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) {
|
||||
if (__indexOf.call(LINEBREAKS, tag) >= 0) {
|
||||
noCall = false;
|
||||
}
|
||||
if (prev && !prev.spaced && tag === '?') {
|
||||
token.call = true;
|
||||
}
|
||||
if (token.fromThen) {
|
||||
return 1;
|
||||
}
|
||||
tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
|
||||
this.detectEnd(i + 1, function(token, i) {
|
||||
var post, _ref4;
|
||||
tag = token[0];
|
||||
if (!seenSingle && token.fromThen) return true;
|
||||
if (tag === 'IF' || tag === 'ELSE' || tag === 'CATCH' || tag === '->' || tag === '=>') {
|
||||
seenSingle = true;
|
||||
}
|
||||
if (tag === 'IF' || tag === 'ELSE' || tag === 'SWITCH' || tag === 'TRY') {
|
||||
seenControl = true;
|
||||
}
|
||||
if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') {
|
||||
return true;
|
||||
}
|
||||
return !token.generated && this.tag(i - 1) !== ',' && (__indexOf.call(IMPLICIT_END, tag) >= 0 || (tag === 'INDENT' && !seenControl)) && (tag !== 'INDENT' || (this.tag(i - 2) !== 'CLASS' && (_ref4 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref4) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
|
||||
}, action);
|
||||
if (prev[0] === '?') prev[0] = 'FUNC_EXIST';
|
||||
if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) {
|
||||
return 1;
|
||||
}
|
||||
tokens.splice(i, 0, this.generate('CALL_START', '(', token[2]));
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
if (prev[0] === '?') {
|
||||
prev[0] = 'FUNC_EXIST';
|
||||
}
|
||||
return 2;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.addImplicitIndentation = function() {
|
||||
var action, condition, indent, outdent, starter;
|
||||
starter = indent = outdent = null;
|
||||
condition = function(token, i) {
|
||||
var _ref;
|
||||
return token[1] !== ';' && (_ref = token[0], __indexOf.call(SINGLE_CLOSERS, _ref) >= 0) && !(token[0] === 'ELSE' && (starter !== 'IF' && starter !== 'THEN'));
|
||||
};
|
||||
action = function(token, i) {
|
||||
return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var action, condition, indent, outdent, starter, tag, _ref, _ref2;
|
||||
var tag, _ref, _ref1;
|
||||
tag = token[0];
|
||||
if (tag === 'TERMINATOR' && this.tag(i + 1) === 'THEN') {
|
||||
tokens.splice(i, 1);
|
||||
@@ -204,19 +248,15 @@
|
||||
}
|
||||
if (__indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
|
||||
starter = tag;
|
||||
_ref2 = this.indentation(token), indent = _ref2[0], outdent = _ref2[1];
|
||||
if (starter === 'THEN') indent.fromThen = true;
|
||||
indent.generated = outdent.generated = true;
|
||||
_ref1 = this.indentation(token, true), indent = _ref1[0], outdent = _ref1[1];
|
||||
if (starter === 'THEN') {
|
||||
indent.fromThen = true;
|
||||
}
|
||||
tokens.splice(i + 1, 0, indent);
|
||||
condition = function(token, i) {
|
||||
var _ref3;
|
||||
return token[1] !== ';' && (_ref3 = token[0], __indexOf.call(SINGLE_CLOSERS, _ref3) >= 0) && !(token[0] === 'ELSE' && (starter !== 'IF' && starter !== 'THEN'));
|
||||
};
|
||||
action = function(token, i) {
|
||||
return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
|
||||
};
|
||||
this.detectEnd(i + 2, condition, action);
|
||||
if (tag === 'THEN') tokens.splice(i, 1);
|
||||
if (tag === 'THEN') {
|
||||
tokens.splice(i, 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
@@ -224,24 +264,45 @@
|
||||
};
|
||||
|
||||
Rewriter.prototype.tagPostfixConditionals = function() {
|
||||
var condition;
|
||||
var action, condition, original;
|
||||
original = null;
|
||||
condition = function(token, i) {
|
||||
var _ref;
|
||||
return (_ref = token[0]) === 'TERMINATOR' || _ref === 'INDENT';
|
||||
};
|
||||
action = function(token, i) {
|
||||
if (token[0] !== 'INDENT' || (token.generated && !token.fromThen)) {
|
||||
return original[0] = 'POST_' + original[0];
|
||||
}
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
var original;
|
||||
if (token[0] !== 'IF') return 1;
|
||||
if (token[0] !== 'IF') {
|
||||
return 1;
|
||||
}
|
||||
original = token;
|
||||
this.detectEnd(i + 1, condition, function(token, i) {
|
||||
if (token[0] !== 'INDENT') return original[0] = 'POST_' + original[0];
|
||||
});
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.indentation = function(token) {
|
||||
return [['INDENT', 2, token[2]], ['OUTDENT', 2, token[2]]];
|
||||
Rewriter.prototype.indentation = function(token, implicit) {
|
||||
var indent, outdent;
|
||||
if (implicit == null) {
|
||||
implicit = false;
|
||||
}
|
||||
indent = ['INDENT', 2, token[2]];
|
||||
outdent = ['OUTDENT', 2, token[2]];
|
||||
if (implicit) {
|
||||
indent.generated = outdent.generated = true;
|
||||
}
|
||||
return [indent, outdent];
|
||||
};
|
||||
|
||||
Rewriter.prototype.generate = function(tag, value, line) {
|
||||
var tok;
|
||||
tok = [tag, value, line];
|
||||
tok.generated = true;
|
||||
return tok;
|
||||
};
|
||||
|
||||
Rewriter.prototype.tag = function(i) {
|
||||
@@ -271,7 +332,7 @@
|
||||
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
|
||||
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'UNARY', 'SUPER', '@', '->', '=>', '[', '(', '{', '--', '++'];
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'NULL', 'UNDEFINED', 'UNARY', 'SUPER', '@', '->', '=>', '[', '(', '{', '--', '++'];
|
||||
|
||||
IMPLICIT_UNSPACED_CALL = ['+', '-'];
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var Scope, extend, last, _ref;
|
||||
|
||||
@@ -18,14 +19,17 @@
|
||||
}
|
||||
];
|
||||
this.positions = {};
|
||||
if (!this.parent) Scope.root = this;
|
||||
if (!this.parent) {
|
||||
Scope.root = this;
|
||||
}
|
||||
}
|
||||
|
||||
Scope.prototype.add = function(name, type, immediate) {
|
||||
var pos;
|
||||
if (this.shared && !immediate) return this.parent.add(name, type, immediate);
|
||||
if (typeof (pos = this.positions[name]) === 'number') {
|
||||
return this.variables[pos].type = type;
|
||||
if (this.shared && !immediate) {
|
||||
return this.parent.add(name, type, immediate);
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(this.positions, name)) {
|
||||
return this.variables[this.positions[name]].type = type;
|
||||
} else {
|
||||
return this.positions[name] = this.variables.push({
|
||||
name: name,
|
||||
@@ -34,49 +38,65 @@
|
||||
}
|
||||
};
|
||||
|
||||
Scope.prototype.find = function(name, options) {
|
||||
if (this.check(name, options)) return true;
|
||||
Scope.prototype.namedMethod = function() {
|
||||
if (this.method.name || !this.parent) {
|
||||
return this.method;
|
||||
}
|
||||
return this.parent.namedMethod();
|
||||
};
|
||||
|
||||
Scope.prototype.find = function(name) {
|
||||
if (this.check(name)) {
|
||||
return true;
|
||||
}
|
||||
this.add(name, 'var');
|
||||
return false;
|
||||
};
|
||||
|
||||
Scope.prototype.parameter = function(name) {
|
||||
if (this.shared && this.parent.check(name, true)) return;
|
||||
if (this.shared && this.parent.check(name, true)) {
|
||||
return;
|
||||
}
|
||||
return this.add(name, 'param');
|
||||
};
|
||||
|
||||
Scope.prototype.check = function(name, immediate) {
|
||||
var found, _ref2;
|
||||
found = !!this.type(name);
|
||||
if (found || immediate) return found;
|
||||
return !!((_ref2 = this.parent) != null ? _ref2.check(name) : void 0);
|
||||
Scope.prototype.check = function(name) {
|
||||
var _ref1;
|
||||
return !!(this.type(name) || ((_ref1 = this.parent) != null ? _ref1.check(name) : void 0));
|
||||
};
|
||||
|
||||
Scope.prototype.temporary = function(name, index) {
|
||||
if (name.length > 1) {
|
||||
return '_' + name + (index > 1 ? index : '');
|
||||
return '_' + name + (index > 1 ? index - 1 : '');
|
||||
} else {
|
||||
return '_' + (index + parseInt(name, 36)).toString(36).replace(/\d/g, 'a');
|
||||
}
|
||||
};
|
||||
|
||||
Scope.prototype.type = function(name) {
|
||||
var v, _i, _len, _ref2;
|
||||
_ref2 = this.variables;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
v = _ref2[_i];
|
||||
if (v.name === name) return v.type;
|
||||
var v, _i, _len, _ref1;
|
||||
_ref1 = this.variables;
|
||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||
v = _ref1[_i];
|
||||
if (v.name === name) {
|
||||
return v.type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
Scope.prototype.freeVariable = function(type) {
|
||||
Scope.prototype.freeVariable = function(name, reserve) {
|
||||
var index, temp;
|
||||
if (reserve == null) {
|
||||
reserve = true;
|
||||
}
|
||||
index = 0;
|
||||
while (this.check((temp = this.temporary(type, index)))) {
|
||||
while (this.check((temp = this.temporary(name, index)))) {
|
||||
index++;
|
||||
}
|
||||
this.add(temp, 'var', true);
|
||||
if (reserve) {
|
||||
this.add(temp, 'var', true);
|
||||
}
|
||||
return temp;
|
||||
};
|
||||
|
||||
@@ -84,7 +104,7 @@
|
||||
this.add(name, {
|
||||
value: value,
|
||||
assigned: true
|
||||
});
|
||||
}, true);
|
||||
return this.hasAssignments = true;
|
||||
};
|
||||
|
||||
@@ -93,12 +113,12 @@
|
||||
};
|
||||
|
||||
Scope.prototype.declaredVariables = function() {
|
||||
var realVars, tempVars, v, _i, _len, _ref2;
|
||||
var realVars, tempVars, v, _i, _len, _ref1;
|
||||
realVars = [];
|
||||
tempVars = [];
|
||||
_ref2 = this.variables;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
v = _ref2[_i];
|
||||
_ref1 = this.variables;
|
||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||
v = _ref1[_i];
|
||||
if (v.type === 'var') {
|
||||
(v.name.charAt(0) === '_' ? tempVars : realVars).push(v.name);
|
||||
}
|
||||
@@ -107,12 +127,14 @@
|
||||
};
|
||||
|
||||
Scope.prototype.assignedVariables = function() {
|
||||
var v, _i, _len, _ref2, _results;
|
||||
_ref2 = this.variables;
|
||||
var v, _i, _len, _ref1, _results;
|
||||
_ref1 = this.variables;
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
v = _ref2[_i];
|
||||
if (v.type.assigned) _results.push("" + v.name + " = " + v.type.value);
|
||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||
v = _ref1[_i];
|
||||
if (v.type.assigned) {
|
||||
_results.push("" + v.name + " = " + v.type.value);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
|
||||
12
package.json
12
package.json
@@ -3,10 +3,10 @@
|
||||
"description": "Unfancy JavaScript",
|
||||
"keywords": ["javascript", "language", "coffeescript", "compiler"],
|
||||
"author": "Jeremy Ashkenas",
|
||||
"version": "1.1.3",
|
||||
"version": "1.4.0",
|
||||
"licenses": [{
|
||||
"type": "MIT",
|
||||
"url": "http://github.com/jashkenas/coffee-script/raw/master/LICENSE"
|
||||
"url": "https://raw.github.com/jashkenas/coffee-script/master/LICENSE"
|
||||
}],
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
@@ -19,13 +19,17 @@
|
||||
"coffee": "./bin/coffee",
|
||||
"cake": "./bin/cake"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node ./bin/cake test"
|
||||
},
|
||||
"homepage": "http://coffeescript.org",
|
||||
"bugs": "https://github.com/jashkenas/coffee-script/issues",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/jashkenas/coffee-script.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"uglify-js": "1.0.6",
|
||||
"jison": "0.2.11"
|
||||
"uglify-js": ">=1.0.0",
|
||||
"jison": ">=0.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@ CoffeeScript = require './coffee-script'
|
||||
CoffeeScript.require = require
|
||||
|
||||
# Use standard JavaScript `eval` to eval code.
|
||||
CoffeeScript.eval = (code, options) ->
|
||||
CoffeeScript.eval = (code, options = {}) ->
|
||||
options.bare ?= on
|
||||
eval CoffeeScript.compile code, options
|
||||
|
||||
# Running code does not provide access to this scope.
|
||||
@@ -17,7 +18,10 @@ return unless window?
|
||||
|
||||
# Load a remote script from the current domain via XHR.
|
||||
CoffeeScript.load = (url, callback) ->
|
||||
xhr = new (window.ActiveXObject or XMLHttpRequest)('Microsoft.XMLHTTP')
|
||||
xhr = if window.ActiveXObject
|
||||
new window.ActiveXObject('Microsoft.XMLHTTP')
|
||||
else
|
||||
new XMLHttpRequest()
|
||||
xhr.open 'GET', url, true
|
||||
xhr.overrideMimeType 'text/plain' if 'overrideMimeType' of xhr
|
||||
xhr.onreadystatechange = ->
|
||||
|
||||
@@ -13,6 +13,8 @@ helpers = require './helpers'
|
||||
optparse = require './optparse'
|
||||
CoffeeScript = require './coffee-script'
|
||||
|
||||
existsSync = fs.existsSync or path.existsSync
|
||||
|
||||
# Keep track of the list of defined tasks, the accepted options, and so on.
|
||||
tasks = {}
|
||||
options = {}
|
||||
@@ -41,21 +43,26 @@ helpers.extend global,
|
||||
|
||||
# Run `cake`. Executes all of the tasks you pass, in order. Note that Node's
|
||||
# asynchrony may cause tasks to execute in a different order than you'd expect.
|
||||
# If no tasks are passed, print the help screen. Keep a reference to the
|
||||
# original directory name, when running Cake tasks from subdirectories.
|
||||
# If no tasks are passed, print the help screen. Keep a reference to the
|
||||
# original directory name, when running Cake tasks from subdirectories.
|
||||
exports.run = ->
|
||||
global.__originalDirname = fs.realpathSync '.'
|
||||
process.chdir cakefileDirectory __originalDirname
|
||||
args = process.argv.slice 2
|
||||
args = process.argv[2..]
|
||||
CoffeeScript.run fs.readFileSync('Cakefile').toString(), filename: 'Cakefile'
|
||||
oparse = new optparse.OptionParser switches
|
||||
return printTasks() unless args.length
|
||||
options = oparse.parse(args)
|
||||
try
|
||||
options = oparse.parse(args)
|
||||
catch e
|
||||
return fatalError "#{e}"
|
||||
invoke arg for arg in options.arguments
|
||||
|
||||
# Display the list of Cake tasks in a format similar to `rake -T`
|
||||
printTasks = ->
|
||||
console.log ''
|
||||
relative = path.relative or path.resolve
|
||||
cakefilePath = path.join relative(__originalDirname, process.cwd()), 'Cakefile'
|
||||
console.log "#{cakefilePath} defines the following tasks:\n"
|
||||
for name, task of tasks
|
||||
spaces = 20 - name.length
|
||||
spaces = if spaces > 0 then Array(spaces + 1).join(' ') else ''
|
||||
@@ -63,15 +70,18 @@ printTasks = ->
|
||||
console.log "cake #{name}#{spaces} #{desc}"
|
||||
console.log oparse.help() if switches.length
|
||||
|
||||
# Print an error and exit when attempting to call an undefined task.
|
||||
missingTask = (task) ->
|
||||
console.log "No such task: \"#{task}\""
|
||||
# Print an error and exit when attempting to use an invalid task/option.
|
||||
fatalError = (message) ->
|
||||
console.error message + '\n'
|
||||
console.log 'To see a list of all tasks/options, run "cake"'
|
||||
process.exit 1
|
||||
|
||||
# When `cake` is invoked, search in the current and all parent directories
|
||||
missingTask = (task) -> fatalError "No such task: #{task}"
|
||||
|
||||
# When `cake` is invoked, search in the current and all parent directories
|
||||
# to find the relevant Cakefile.
|
||||
cakefileDirectory = (dir) ->
|
||||
return dir if path.existsSync path.join dir, 'Cakefile'
|
||||
return dir if existsSync path.join dir, 'Cakefile'
|
||||
parent = path.normalize path.join dir, '..'
|
||||
return cakefileDirectory parent unless parent is dir
|
||||
throw new Error "Cakefile not found in #{process.cwd()}"
|
||||
|
||||
@@ -12,16 +12,16 @@ path = require 'path'
|
||||
{parser} = require './parser'
|
||||
vm = require 'vm'
|
||||
|
||||
# TODO: Remove registerExtension when fully deprecated.
|
||||
stripBOM = (content) ->
|
||||
if content.charCodeAt(0) is 0xFEFF then content.substring 1 else content
|
||||
|
||||
if require.extensions
|
||||
require.extensions['.coffee'] = (module, filename) ->
|
||||
content = compile fs.readFileSync(filename, 'utf8'), {filename}
|
||||
content = compile stripBOM(fs.readFileSync filename, 'utf8'), {filename}
|
||||
module._compile content, filename
|
||||
else if require.registerExtension
|
||||
require.registerExtension '.coffee', (content) -> compile content
|
||||
|
||||
# The current CoffeeScript version number.
|
||||
exports.VERSION = '1.1.3'
|
||||
exports.VERSION = '1.4.0'
|
||||
|
||||
# Words that cannot be used as identifiers in CoffeeScript code
|
||||
exports.RESERVED = RESERVED
|
||||
@@ -32,11 +32,15 @@ exports.helpers = require './helpers'
|
||||
# Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
|
||||
# compiler.
|
||||
exports.compile = compile = (code, options = {}) ->
|
||||
{merge} = exports.helpers
|
||||
try
|
||||
(parser.parse lexer.tokenize code).compile options
|
||||
js = (parser.parse lexer.tokenize code).compile options
|
||||
return js unless options.header
|
||||
catch err
|
||||
err.message = "In #{options.filename}, #{err.message}" if options.filename
|
||||
throw err
|
||||
header = "Generated by CoffeeScript #{@VERSION}"
|
||||
"// #{header}\n#{js}"
|
||||
|
||||
# Tokenize a string of CoffeeScript code, and return the array of tokens.
|
||||
exports.tokens = (code, options) ->
|
||||
@@ -44,7 +48,7 @@ exports.tokens = (code, options) ->
|
||||
|
||||
# Parse a string of CoffeeScript code or an array of lexed tokens, and
|
||||
# return the AST. You can then compile it by calling `.compile()` on the root,
|
||||
# or traverse it by using `.traverse()` with a callback.
|
||||
# or traverse it by using `.traverseChildren()` with a callback.
|
||||
exports.nodes = (source, options) ->
|
||||
if typeof source is 'string'
|
||||
parser.parse lexer.tokenize source, options
|
||||
@@ -53,7 +57,7 @@ exports.nodes = (source, options) ->
|
||||
|
||||
# Compile and execute a string of CoffeeScript (on the server), correctly
|
||||
# setting `__filename`, `__dirname`, and relative `require()`.
|
||||
exports.run = (code, options) ->
|
||||
exports.run = (code, options = {}) ->
|
||||
mainModule = require.main
|
||||
|
||||
# Set the filename.
|
||||
@@ -64,7 +68,7 @@ exports.run = (code, options) ->
|
||||
mainModule.moduleCache and= {}
|
||||
|
||||
# Assign paths for node_modules loading
|
||||
mainModule.paths = require('module')._nodeModulePaths path.dirname options.filename
|
||||
mainModule.paths = require('module')._nodeModulePaths path.dirname fs.realpathSync options.filename
|
||||
|
||||
# Compile.
|
||||
if path.extname(mainModule.filename) isnt '.coffee' or require.extensions
|
||||
|
||||
@@ -13,18 +13,22 @@ CoffeeScript = require './coffee-script'
|
||||
{spawn, exec} = require 'child_process'
|
||||
{EventEmitter} = require 'events'
|
||||
|
||||
exists = fs.exists or path.exists
|
||||
|
||||
# Allow CoffeeScript to emit Node.js events.
|
||||
helpers.extend CoffeeScript, new EventEmitter
|
||||
|
||||
printLine = (line) -> process.stdout.write line + '\n'
|
||||
printWarn = (line) -> process.stderr.write line + '\n'
|
||||
|
||||
hidden = (file) -> /^\.|~$/.test file
|
||||
|
||||
# The help banner that is printed when `coffee` is called without arguments.
|
||||
BANNER = '''
|
||||
Usage: coffee [options] path/to/script.coffee
|
||||
Usage: coffee [options] path/to/script.coffee -- [args]
|
||||
|
||||
If called without options, `coffee` will run your script.
|
||||
'''
|
||||
'''
|
||||
|
||||
# The list of all the valid option flags that `coffee` knows how to handle.
|
||||
SWITCHES = [
|
||||
@@ -49,7 +53,9 @@ SWITCHES = [
|
||||
# Top-level objects shared by all the functions.
|
||||
opts = {}
|
||||
sources = []
|
||||
contents = []
|
||||
sourceCode = []
|
||||
notSources = {}
|
||||
watchers = {}
|
||||
optionParser = null
|
||||
|
||||
# Run `coffee` by parsing passed options and determining what action to take.
|
||||
@@ -62,63 +68,53 @@ exports.run = ->
|
||||
return version() if opts.version
|
||||
loadRequires() if opts.require
|
||||
return require './repl' if opts.interactive
|
||||
if opts.watch and !fs.watch
|
||||
return printWarn "The --watch feature depends on Node v0.6.0+. You are running #{process.version}."
|
||||
return compileStdio() if opts.stdio
|
||||
return compileScript null, sources[0] if opts.eval
|
||||
return require './repl' unless sources.length
|
||||
if opts.run
|
||||
opts.literals = sources.splice(1).concat opts.literals
|
||||
process.argv = process.argv.slice(0, 2).concat opts.literals
|
||||
literals = if opts.run then sources.splice 1 else []
|
||||
process.argv = process.argv[0..1].concat literals
|
||||
process.argv[0] = 'coffee'
|
||||
process.execPath = require.main.filename
|
||||
compileScripts()
|
||||
for source in sources
|
||||
compilePath source, yes, path.normalize source
|
||||
|
||||
# Compile a path, which could be a script or a directory. If a directory
|
||||
# is passed, recursively compile all '.coffee' extension source files in it
|
||||
# and all subdirectories.
|
||||
compilePath = (source, topLevel, base) ->
|
||||
fs.stat source, (err, stats) ->
|
||||
throw err if err and err.code isnt 'ENOENT'
|
||||
if err?.code is 'ENOENT'
|
||||
if topLevel and source[-7..] isnt '.coffee'
|
||||
source = sources[sources.indexOf(source)] = "#{source}.coffee"
|
||||
return compilePath source, topLevel, base
|
||||
if topLevel
|
||||
console.error "File not found: #{source}"
|
||||
process.exit 1
|
||||
return
|
||||
if stats.isDirectory()
|
||||
watchDir source, base if opts.watch
|
||||
fs.readdir source, (err, files) ->
|
||||
throw err if err and err.code isnt 'ENOENT'
|
||||
return if err?.code is 'ENOENT'
|
||||
index = sources.indexOf source
|
||||
files = files.filter (file) -> not hidden file
|
||||
sources[index..index] = (path.join source, file for file in files)
|
||||
sourceCode[index..index] = files.map -> null
|
||||
files.forEach (file) ->
|
||||
compilePath (path.join source, file), no, base
|
||||
else if topLevel or path.extname(source) is '.coffee'
|
||||
watch source, base if opts.watch
|
||||
fs.readFile source, (err, code) ->
|
||||
throw err if err and err.code isnt 'ENOENT'
|
||||
return if err?.code is 'ENOENT'
|
||||
compileScript(source, code.toString(), base)
|
||||
else
|
||||
notSources[source] = yes
|
||||
removeSource source, base
|
||||
|
||||
# Asynchronously read in each CoffeeScript in a list of source files and
|
||||
# compile them. If a directory is passed, recursively compile all
|
||||
# '.coffee' extension source files in it and all subdirectories.
|
||||
compileScripts = ->
|
||||
unprocessed = []
|
||||
remaining_files = ->
|
||||
total = 0
|
||||
total += x for x in unprocessed
|
||||
total
|
||||
trackUnprocessedFiles = (sourceIndex, fileCount) ->
|
||||
unprocessed[sourceIndex] ?= 0
|
||||
unprocessed[sourceIndex] += fileCount
|
||||
trackCompleteFiles = (sourceIndex, fileCount) ->
|
||||
unprocessed[sourceIndex] -= fileCount
|
||||
if opts.join
|
||||
if helpers.compact(contents).length > 0 and remaining_files() == 0
|
||||
compileJoin()
|
||||
for source in sources
|
||||
trackUnprocessedFiles sources.indexOf(source), 1
|
||||
for source in sources
|
||||
base = path.join(source)
|
||||
compile = (source, sourceIndex, topLevel) ->
|
||||
path.exists source, (exists) ->
|
||||
if topLevel and not exists and source[-7..] isnt '.coffee'
|
||||
return compile "#{source}.coffee", sourceIndex, topLevel
|
||||
throw new Error "File not found: #{source}" if topLevel and not exists
|
||||
fs.stat source, (err, stats) ->
|
||||
throw err if err
|
||||
if stats.isDirectory()
|
||||
fs.readdir source, (err, files) ->
|
||||
throw err if err
|
||||
trackUnprocessedFiles sourceIndex, files.length
|
||||
for file in files
|
||||
compile path.join(source, file), sourceIndex
|
||||
trackCompleteFiles sourceIndex, 1
|
||||
else if topLevel or path.extname(source) is '.coffee'
|
||||
fs.readFile source, (err, code) ->
|
||||
throw err if err
|
||||
if opts.join
|
||||
contents[sourceIndex] = helpers.compact([contents[sourceIndex], code.toString()]).join('\n')
|
||||
else
|
||||
compileScript(source, code.toString(), base)
|
||||
trackCompleteFiles sourceIndex, 1
|
||||
watch source, base if opts.watch and not opts.join
|
||||
else
|
||||
trackCompleteFiles sourceIndex, 1
|
||||
compile source, sources.indexOf(source), true
|
||||
|
||||
# Compile a single source script, containing the given code, according to the
|
||||
# requested options. If evaluating the script directly sets `__filename`,
|
||||
@@ -132,6 +128,9 @@ compileScript = (file, input, base) ->
|
||||
if o.tokens then printTokens CoffeeScript.tokens t.input
|
||||
else if o.nodes then printLine CoffeeScript.nodes(t.input).toString().trim()
|
||||
else if o.run then CoffeeScript.run t.input, t.options
|
||||
else if o.join and t.file isnt o.join
|
||||
sourceCode[sources.indexOf(t.file)] = t.input
|
||||
compileJoin()
|
||||
else
|
||||
t.output = CoffeeScript.compile t.input, t.options
|
||||
CoffeeScript.emit 'success', task
|
||||
@@ -141,7 +140,7 @@ compileScript = (file, input, base) ->
|
||||
catch err
|
||||
CoffeeScript.emit 'failure', err, task
|
||||
return if CoffeeScript.listeners('failure').length
|
||||
return printLine err.message if o.watch
|
||||
return printLine err.message + '\x07' if o.watch
|
||||
printWarn err instanceof Error and err.stack or "ERROR: #{err}"
|
||||
process.exit 1
|
||||
|
||||
@@ -155,11 +154,15 @@ compileStdio = ->
|
||||
stdin.on 'end', ->
|
||||
compileScript null, code
|
||||
|
||||
# After all of the source files are done being read, concatenate and compile
|
||||
# If all of the source files are done being read, concatenate and compile
|
||||
# them together.
|
||||
joinTimeout = null
|
||||
compileJoin = ->
|
||||
code = contents.join '\n'
|
||||
compileScript opts.join, code, opts.join
|
||||
return unless opts.join
|
||||
unless sourceCode.some((code) -> code is null)
|
||||
clearTimeout joinTimeout
|
||||
joinTimeout = wait 100, ->
|
||||
compileScript opts.join, sourceCode.join('\n'), opts.join
|
||||
|
||||
# Load files that are to-be-required before compilation occurs.
|
||||
loadRequires = ->
|
||||
@@ -172,37 +175,116 @@ loadRequires = ->
|
||||
# time the file is updated. May be used in combination with other options,
|
||||
# such as `--lint` or `--print`.
|
||||
watch = (source, base) ->
|
||||
fs.stat source, (err, prevStats)->
|
||||
throw err if err
|
||||
fs.watch source, (event) ->
|
||||
if event is 'change'
|
||||
fs.stat source, (err, stats) ->
|
||||
throw err if err
|
||||
return if stats.size is prevStats.size and
|
||||
stats.mtime.getTime() is prevStats.mtime.getTime()
|
||||
prevStats = stats
|
||||
fs.readFile source, (err, code) ->
|
||||
throw err if err
|
||||
compileScript(source, code.toString(), base)
|
||||
|
||||
prevStats = null
|
||||
compileTimeout = null
|
||||
|
||||
watchErr = (e) ->
|
||||
if e.code is 'ENOENT'
|
||||
return if sources.indexOf(source) is -1
|
||||
try
|
||||
rewatch()
|
||||
compile()
|
||||
catch e
|
||||
removeSource source, base, yes
|
||||
compileJoin()
|
||||
else throw e
|
||||
|
||||
compile = ->
|
||||
clearTimeout compileTimeout
|
||||
compileTimeout = wait 25, ->
|
||||
fs.stat source, (err, stats) ->
|
||||
return watchErr err if err
|
||||
return rewatch() if prevStats and stats.size is prevStats.size and
|
||||
stats.mtime.getTime() is prevStats.mtime.getTime()
|
||||
prevStats = stats
|
||||
fs.readFile source, (err, code) ->
|
||||
return watchErr err if err
|
||||
compileScript(source, code.toString(), base)
|
||||
rewatch()
|
||||
|
||||
try
|
||||
watcher = fs.watch source, compile
|
||||
catch e
|
||||
watchErr e
|
||||
|
||||
rewatch = ->
|
||||
watcher?.close()
|
||||
watcher = fs.watch source, compile
|
||||
|
||||
|
||||
# Watch a directory of files for new additions.
|
||||
watchDir = (source, base) ->
|
||||
readdirTimeout = null
|
||||
try
|
||||
watcher = fs.watch source, ->
|
||||
clearTimeout readdirTimeout
|
||||
readdirTimeout = wait 25, ->
|
||||
fs.readdir source, (err, files) ->
|
||||
if err
|
||||
throw err unless err.code is 'ENOENT'
|
||||
watcher.close()
|
||||
return unwatchDir source, base
|
||||
for file in files when not hidden(file) and not notSources[file]
|
||||
file = path.join source, file
|
||||
continue if sources.some (s) -> s.indexOf(file) >= 0
|
||||
sources.push file
|
||||
sourceCode.push null
|
||||
compilePath file, no, base
|
||||
catch e
|
||||
throw e unless e.code is 'ENOENT'
|
||||
|
||||
unwatchDir = (source, base) ->
|
||||
prevSources = sources[..]
|
||||
toRemove = (file for file in sources when file.indexOf(source) >= 0)
|
||||
removeSource file, base, yes for file in toRemove
|
||||
return unless sources.some (s, i) -> prevSources[i] isnt s
|
||||
compileJoin()
|
||||
|
||||
# Remove a file from our source list, and source code cache. Optionally remove
|
||||
# the compiled JS version as well.
|
||||
removeSource = (source, base, removeJs) ->
|
||||
index = sources.indexOf source
|
||||
sources.splice index, 1
|
||||
sourceCode.splice index, 1
|
||||
if removeJs and not opts.join
|
||||
jsPath = outputPath source, base
|
||||
exists jsPath, (itExists) ->
|
||||
if itExists
|
||||
fs.unlink jsPath, (err) ->
|
||||
throw err if err and err.code isnt 'ENOENT'
|
||||
timeLog "removed #{source}"
|
||||
|
||||
# Get the corresponding output JavaScript path for a source file.
|
||||
outputPath = (source, base) ->
|
||||
filename = path.basename(source, path.extname(source)) + '.js'
|
||||
srcDir = path.dirname source
|
||||
baseDir = if base is '.' then srcDir else srcDir.substring base.length
|
||||
dir = if opts.output then path.join opts.output, baseDir else srcDir
|
||||
path.join dir, filename
|
||||
|
||||
# Write out a JavaScript source file with the compiled code. By default, files
|
||||
# are written out in `cwd` as `.js` files with the same name, but the output
|
||||
# directory can be customized with `--output`.
|
||||
writeJs = (source, js, base) ->
|
||||
filename = path.basename(source, path.extname(source)) + '.js'
|
||||
srcDir = path.dirname source
|
||||
baseDir = if base is '.' then srcDir else srcDir.substring base.length
|
||||
dir = if opts.output then path.join opts.output, baseDir else srcDir
|
||||
jsPath = path.join dir, filename
|
||||
compile = ->
|
||||
jsPath = outputPath source, base
|
||||
jsDir = path.dirname jsPath
|
||||
compile = ->
|
||||
js = ' ' if js.length <= 0
|
||||
fs.writeFile jsPath, js, (err) ->
|
||||
if err
|
||||
printLine err.message
|
||||
else if opts.compile and opts.watch
|
||||
console.log "#{(new Date).toLocaleTimeString()} - compiled #{source}"
|
||||
path.exists dir, (exists) ->
|
||||
if exists then compile() else exec "mkdir -p #{dir}", compile
|
||||
timeLog "compiled #{source}"
|
||||
exists jsDir, (itExists) ->
|
||||
if itExists then compile() else exec "mkdir -p #{jsDir}", compile
|
||||
|
||||
# Convenience for cleaner setTimeouts.
|
||||
wait = (milliseconds, func) -> setTimeout func, milliseconds
|
||||
|
||||
# When watching scripts, it's useful to log changes with the timestamp.
|
||||
timeLog = (message) ->
|
||||
console.log "#{(new Date).toLocaleTimeString()} - #{message}"
|
||||
|
||||
# Pipe compiled JS through JSLint (requires a working `jsl` command), printing
|
||||
# any errors or warnings that arise.
|
||||
@@ -226,14 +308,17 @@ printTokens = (tokens) ->
|
||||
# `process.argv` that are specified in `SWITCHES`.
|
||||
parseOptions = ->
|
||||
optionParser = new optparse.OptionParser SWITCHES, BANNER
|
||||
o = opts = optionParser.parse process.argv.slice 2
|
||||
o = opts = optionParser.parse process.argv[2..]
|
||||
o.compile or= !!o.output
|
||||
o.run = not (o.compile or o.print or o.lint)
|
||||
o.print = !! (o.print or (o.eval or o.stdio and o.compile))
|
||||
sources = o.arguments
|
||||
sourceCode[i] = null for source, i in sources
|
||||
return
|
||||
|
||||
# The compile-time options to pass to the CoffeeScript compiler.
|
||||
compileOptions = (filename) -> {filename, bare: opts.bare}
|
||||
compileOptions = (filename) ->
|
||||
{filename, bare: opts.bare, header: opts.compile}
|
||||
|
||||
# Start up a new Node.js instance with the arguments in `--nodejs` passed to
|
||||
# the `node` binary, preserving the other options.
|
||||
|
||||
@@ -77,7 +77,6 @@ grammar =
|
||||
# Pure statements which cannot be expressions.
|
||||
Statement: [
|
||||
o 'Return'
|
||||
o 'Throw'
|
||||
o 'Comment'
|
||||
o 'STATEMENT', -> new Literal $1
|
||||
]
|
||||
@@ -98,6 +97,7 @@ grammar =
|
||||
o 'For'
|
||||
o 'Switch'
|
||||
o 'Class'
|
||||
o 'Throw'
|
||||
]
|
||||
|
||||
# An indented block of expressions. Note that the [Rewriter](rewriter.html)
|
||||
@@ -126,15 +126,16 @@ grammar =
|
||||
o 'AlphaNumeric'
|
||||
o 'JS', -> new Literal $1
|
||||
o 'REGEX', -> new Literal $1
|
||||
o 'BOOL', ->
|
||||
val = new Literal $1
|
||||
val.isUndefined = yes if $1 is 'undefined'
|
||||
val
|
||||
o 'DEBUGGER', -> new Literal $1
|
||||
o 'UNDEFINED', -> new Undefined
|
||||
o 'NULL', -> new Null
|
||||
o 'BOOL', -> new Bool $1
|
||||
]
|
||||
|
||||
# Assignment of a variable, property, or index to a value.
|
||||
Assign: [
|
||||
o 'Assignable = Expression', -> new Assign $1, $3
|
||||
o 'Assignable = TERMINATOR Expression', -> new Assign $1, $4
|
||||
o 'Assignable = INDENT Expression OUTDENT', -> new Assign $1, $4
|
||||
]
|
||||
|
||||
@@ -191,6 +192,8 @@ grammar =
|
||||
o '', -> []
|
||||
o 'Param', -> [$1]
|
||||
o 'ParamList , Param', -> $1.concat $3
|
||||
o 'ParamList OptComma TERMINATOR Param', -> $1.concat $4
|
||||
o 'ParamList OptComma INDENT ParamList OptComma OUTDENT', -> $1.concat $4
|
||||
]
|
||||
|
||||
# A single parameter in a function definition can be ordinary, or a splat
|
||||
@@ -218,7 +221,7 @@ grammar =
|
||||
SimpleAssignable: [
|
||||
o 'Identifier', -> new Value $1
|
||||
o 'Value Accessor', -> $1.add $2
|
||||
o 'Invocation Accessor', -> new Value $1, [$2]
|
||||
o 'Invocation Accessor', -> new Value $1, [].concat $2
|
||||
o 'ThisProperty'
|
||||
]
|
||||
|
||||
@@ -341,6 +344,7 @@ grammar =
|
||||
o 'Expression RangeDots Expression', -> new Range $1, $3, $2
|
||||
o 'Expression RangeDots', -> new Range $1, null, $2
|
||||
o 'RangeDots Expression', -> new Range null, $2, $1
|
||||
o 'RangeDots', -> new Range null, null, $1
|
||||
]
|
||||
|
||||
# The **ArgList** is both the list of objects passed into a function call,
|
||||
@@ -440,6 +444,7 @@ grammar =
|
||||
# This enables support for pattern matching.
|
||||
ForValue: [
|
||||
o 'Identifier'
|
||||
o 'ThisProperty'
|
||||
o 'Array', -> new Value $1
|
||||
o 'Object', -> new Value $1
|
||||
]
|
||||
@@ -528,7 +533,7 @@ grammar =
|
||||
o 'Expression LOGIC Expression', -> new Op $2, $1, $3
|
||||
o 'Expression RELATION Expression', ->
|
||||
if $2.charAt(0) is '!'
|
||||
new Op($2.slice(1), $1, $3).invert()
|
||||
new Op($2[1..], $1, $3).invert()
|
||||
else
|
||||
new Op $2, $1, $3
|
||||
|
||||
@@ -566,7 +571,7 @@ operators = [
|
||||
['nonassoc', 'INDENT', 'OUTDENT']
|
||||
['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS']
|
||||
['right', 'FORIN', 'FOROF', 'BY', 'WHEN']
|
||||
['right', 'IF', 'ELSE', 'FOR', 'DO', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS']
|
||||
['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS']
|
||||
['right', 'POST_IF']
|
||||
]
|
||||
|
||||
|
||||
@@ -54,3 +54,8 @@ exports.del = (obj, key) ->
|
||||
|
||||
# Gets the last item of an array(-like) object.
|
||||
exports.last = (array, back) -> array[array.length - (back or 0) - 1]
|
||||
|
||||
# Typical Array::some
|
||||
exports.some = Array::some ? (fn) ->
|
||||
return true for e in this when fn e
|
||||
false
|
||||
|
||||
102
src/lexer.coffee
102
src/lexer.coffee
@@ -48,7 +48,7 @@ exports.Lexer = class Lexer
|
||||
# short-circuiting if any of them succeed. Their order determines precedence:
|
||||
# `@literalToken` is the fallback catch-all.
|
||||
i = 0
|
||||
while @chunk = code.slice i
|
||||
while @chunk = code[i..]
|
||||
i += @identifierToken() or
|
||||
@commentToken() or
|
||||
@whitespaceToken() or
|
||||
@@ -106,22 +106,22 @@ exports.Lexer = class Lexer
|
||||
@tokens.pop()
|
||||
id = '!' + id
|
||||
|
||||
if id in ['eval', 'arguments'].concat JS_FORBIDDEN
|
||||
if id in JS_FORBIDDEN
|
||||
if forcedIdentifier
|
||||
tag = 'IDENTIFIER'
|
||||
id = new String id
|
||||
id.reserved = yes
|
||||
else if id in RESERVED
|
||||
@error "reserved word \"#{word}\""
|
||||
@error "reserved word \"#{id}\""
|
||||
|
||||
unless forcedIdentifier
|
||||
id = COFFEE_ALIAS_MAP[id] if id in COFFEE_ALIASES
|
||||
tag = switch id
|
||||
when '!' then 'UNARY'
|
||||
when '==', '!=' then 'COMPARE'
|
||||
when '&&', '||' then 'LOGIC'
|
||||
when 'true', 'false', 'null', 'undefined' then 'BOOL'
|
||||
when 'break', 'continue', 'debugger' then 'STATEMENT'
|
||||
when '!' then 'UNARY'
|
||||
when '==', '!=' then 'COMPARE'
|
||||
when '&&', '||' then 'LOGIC'
|
||||
when 'true', 'false' then 'BOOL'
|
||||
when 'break', 'continue' then 'STATEMENT'
|
||||
else tag
|
||||
|
||||
@token tag, id
|
||||
@@ -133,9 +133,19 @@ exports.Lexer = class Lexer
|
||||
numberToken: ->
|
||||
return 0 unless match = NUMBER.exec @chunk
|
||||
number = match[0]
|
||||
if /^0[BOX]/.test number
|
||||
@error "radix prefix '#{number}' must be lowercase"
|
||||
else if /E/.test(number) and not /^0x/.test number
|
||||
@error "exponential notation '#{number}' must be indicated with a lowercase 'e'"
|
||||
else if /^0\d*[89]/.test number
|
||||
@error "decimal literal '#{number}' must not be prefixed with '0'"
|
||||
else if /^0\d+/.test number
|
||||
@error "octal literal '#{number}' must be prefixed with '0o'"
|
||||
lexedLength = number.length
|
||||
if binaryLiteral = /0b([01]+)/.exec number
|
||||
number = (parseInt binaryLiteral[1], 2).toString()
|
||||
if octalLiteral = /^0o([0-7]+)/.exec number
|
||||
number = '0x' + (parseInt octalLiteral[1], 8).toString 16
|
||||
if binaryLiteral = /^0b([01]+)/.exec number
|
||||
number = '0x' + (parseInt binaryLiteral[1], 2).toString 16
|
||||
@token 'NUMBER', number
|
||||
lexedLength
|
||||
|
||||
@@ -149,11 +159,13 @@ exports.Lexer = class Lexer
|
||||
when '"'
|
||||
return 0 unless string = @balancedString @chunk, '"'
|
||||
if 0 < string.indexOf '#{', 1
|
||||
@interpolateString string.slice 1, -1
|
||||
@interpolateString string[1...-1]
|
||||
else
|
||||
@token 'STRING', @escapeLines string
|
||||
else
|
||||
return 0
|
||||
if octalEsc = /^(?:\\.|[^\\])*\\(?:0[0-7]|[1-7])/.test string
|
||||
@error "octal escape sequences #{string} are not allowed"
|
||||
@line += count string, '\n'
|
||||
string.length
|
||||
|
||||
@@ -178,14 +190,14 @@ exports.Lexer = class Lexer
|
||||
if here
|
||||
@token 'HERECOMMENT', @sanitizeHeredoc here,
|
||||
herecomment: true, indent: Array(@indent + 1).join(' ')
|
||||
@token 'TERMINATOR', '\n'
|
||||
@line += count comment, '\n'
|
||||
comment.length
|
||||
|
||||
# Matches JavaScript interpolated directly into the source via backticks.
|
||||
jsToken: ->
|
||||
return 0 unless @chunk.charAt(0) is '`' and match = JSTOKEN.exec @chunk
|
||||
@token 'JS', (script = match[0]).slice 1, -1
|
||||
@token 'JS', (script = match[0])[1...-1]
|
||||
@line += count script, '\n'
|
||||
script.length
|
||||
|
||||
# Matches regular expression literals. Lexing regular expressions is difficult
|
||||
@@ -248,7 +260,6 @@ exports.Lexer = class Lexer
|
||||
indent = match[0]
|
||||
@line += count indent, '\n'
|
||||
@seenFor = no
|
||||
prev = last @tokens, 1
|
||||
size = indent.length - 1 - indent.lastIndexOf '\n'
|
||||
noNewlines = @unfinished()
|
||||
if size - @indebt is @indent
|
||||
@@ -262,7 +273,7 @@ exports.Lexer = class Lexer
|
||||
diff = size - @indent + @outdebt
|
||||
@token 'INDENT', diff
|
||||
@indents.push diff
|
||||
@ends .push 'OUTDENT'
|
||||
@ends.push 'OUTDENT'
|
||||
@outdebt = @indebt = 0
|
||||
else
|
||||
@indebt = 0
|
||||
@@ -335,9 +346,9 @@ exports.Lexer = class Lexer
|
||||
prev[0] = 'COMPOUND_ASSIGN'
|
||||
prev[1] += '='
|
||||
return value.length
|
||||
if value is ';'
|
||||
@seenFor = no
|
||||
tag = 'TERMINATOR'
|
||||
if value is ';'
|
||||
@seenFor = no
|
||||
tag = 'TERMINATOR'
|
||||
else if value in MATH then tag = 'MATH'
|
||||
else if value in COMPARE then tag = 'COMPARE'
|
||||
else if value in COMPOUND_ASSIGN then tag = 'COMPOUND_ASSIGN'
|
||||
@@ -407,22 +418,26 @@ exports.Lexer = class Lexer
|
||||
# contents of the string. This method allows us to have strings within
|
||||
# interpolations within strings, ad infinitum.
|
||||
balancedString: (str, end) ->
|
||||
continueCount = 0
|
||||
stack = [end]
|
||||
for i in [1...str.length]
|
||||
if continueCount
|
||||
--continueCount
|
||||
continue
|
||||
switch letter = str.charAt i
|
||||
when '\\'
|
||||
i++
|
||||
++continueCount
|
||||
continue
|
||||
when end
|
||||
stack.pop()
|
||||
unless stack.length
|
||||
return str.slice 0, i + 1
|
||||
return str[0..i]
|
||||
end = stack[stack.length - 1]
|
||||
continue
|
||||
if end is '}' and letter in ['"', "'"]
|
||||
stack.push end = letter
|
||||
else if end is '}' and letter is '/' and match = (HEREGEX.exec(str.slice i) or REGEX.exec(str.slice i))
|
||||
i += match[0].length - 1
|
||||
else if end is '}' and letter is '/' and match = (HEREGEX.exec(str[i..]) or REGEX.exec(str[i..]))
|
||||
continueCount += match[0].length - 1
|
||||
else if end is '}' and letter is '{'
|
||||
stack.push end = '}'
|
||||
else if end is '"' and prev is '#' and letter is '{'
|
||||
@@ -448,22 +463,22 @@ exports.Lexer = class Lexer
|
||||
i += 1
|
||||
continue
|
||||
unless letter is '#' and str.charAt(i+1) is '{' and
|
||||
(expr = @balancedString str.slice(i + 1), '}')
|
||||
(expr = @balancedString str[i + 1..], '}')
|
||||
continue
|
||||
tokens.push ['NEOSTRING', str.slice(pi, i)] if pi < i
|
||||
inner = expr.slice(1, -1)
|
||||
tokens.push ['NEOSTRING', str[pi...i]] if pi < i
|
||||
inner = expr[1...-1]
|
||||
if inner.length
|
||||
nested = new Lexer().tokenize inner, line: @line, rewrite: off
|
||||
nested.pop()
|
||||
nested.shift() if nested[0]?[0] is 'TERMINATOR'
|
||||
if len = nested.length
|
||||
if len > 1
|
||||
nested.unshift ['(', '(']
|
||||
nested.push [')', ')']
|
||||
nested.unshift ['(', '(', @line]
|
||||
nested.push [')', ')', @line]
|
||||
tokens.push ['TOKENS', nested]
|
||||
i += expr.length
|
||||
pi = i + 1
|
||||
tokens.push ['NEOSTRING', str.slice pi] if i > pi < str.length
|
||||
tokens.push ['NEOSTRING', str[pi..]] if i > pi < str.length
|
||||
return tokens if regex
|
||||
return @token 'STRING', '""' unless tokens.length
|
||||
tokens.unshift ['', ''] unless tokens[0][0] is 'NEOSTRING'
|
||||
@@ -511,7 +526,7 @@ exports.Lexer = class Lexer
|
||||
unfinished: ->
|
||||
LINE_CONTINUER.test(@chunk) or
|
||||
@tag() in ['\\', '.', '?.', 'UNARY', 'MATH', '+', '-', 'SHIFT', 'RELATION'
|
||||
'COMPARE', 'LOGIC', 'COMPOUND_ASSIGN', 'THROW', 'EXTENDS']
|
||||
'COMPARE', 'LOGIC', 'THROW', 'EXTENDS']
|
||||
|
||||
# Converts newlines for string literals.
|
||||
escapeLines: (str, heredoc) ->
|
||||
@@ -524,9 +539,9 @@ exports.Lexer = class Lexer
|
||||
if contents in ['\n', quote] then contents else match
|
||||
body = body.replace /// #{quote} ///g, '\\$&'
|
||||
quote + @escapeLines(body, heredoc) + quote
|
||||
|
||||
|
||||
# Throws a syntax error on the current `@line`.
|
||||
error: (message) ->
|
||||
error: (message) ->
|
||||
throw SyntaxError "#{message} on line #{ @line + 1}"
|
||||
|
||||
# Constants
|
||||
@@ -562,16 +577,20 @@ COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat COFFEE_ALIASES
|
||||
# used by CoffeeScript internally. We throw an error when these are encountered,
|
||||
# to avoid having a JavaScript error at runtime.
|
||||
RESERVED = [
|
||||
'case', 'default', 'function', 'var', 'void', 'with'
|
||||
'const', 'let', 'enum', 'export', 'import', 'native'
|
||||
'__hasProp', '__extends', '__slice', '__bind', '__indexOf'
|
||||
'case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum'
|
||||
'export', 'import', 'native', '__hasProp', '__extends', '__slice', '__bind'
|
||||
'__indexOf', 'implements', 'interface', 'package', 'private', 'protected'
|
||||
'public', 'static', 'yield'
|
||||
]
|
||||
|
||||
STRICT_PROSCRIBED = ['arguments', 'eval']
|
||||
|
||||
# The superset of both JavaScript keywords and reserved words, none of which may
|
||||
# be used as identifiers or properties.
|
||||
JS_FORBIDDEN = JS_KEYWORDS.concat RESERVED
|
||||
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED)
|
||||
|
||||
exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS)
|
||||
exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS).concat(STRICT_PROSCRIBED)
|
||||
exports.STRICT_PROSCRIBED = STRICT_PROSCRIBED
|
||||
|
||||
# Token matching regexes.
|
||||
IDENTIFIER = /// ^
|
||||
@@ -580,8 +599,9 @@ IDENTIFIER = /// ^
|
||||
///
|
||||
|
||||
NUMBER = ///
|
||||
^ 0x[\da-f]+ | # hex
|
||||
^ 0b[01]+ | # binary
|
||||
^ 0b[01]+ | # binary
|
||||
^ 0o[0-7]+ | # octal
|
||||
^ 0x[\da-f]+ | # hex
|
||||
^ \d*\.?\d+ (?:e[+-]?\d+)? # decimal
|
||||
///i
|
||||
|
||||
@@ -663,7 +683,7 @@ MATH = ['*', '/', '%']
|
||||
RELATION = ['IN', 'OF', 'INSTANCEOF']
|
||||
|
||||
# Boolean tokens.
|
||||
BOOL = ['TRUE', 'FALSE', 'NULL', 'UNDEFINED']
|
||||
BOOL = ['TRUE', 'FALSE']
|
||||
|
||||
# Tokens which a regular expression will never immediately follow, but which
|
||||
# a division operator might.
|
||||
@@ -671,7 +691,7 @@ BOOL = ['TRUE', 'FALSE', 'NULL', 'UNDEFINED']
|
||||
# See: http://www.mozilla.org/js/language/js20-2002-04/rationale/syntax.html#regular-expressions
|
||||
#
|
||||
# Our list is shorter, due to sans-parentheses method calls.
|
||||
NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', '++', '--', ']']
|
||||
NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', 'NULL', 'UNDEFINED', '++', '--', ']']
|
||||
|
||||
# If the previous token is not spaced, there are more preceding tokens that
|
||||
# force a division parse:
|
||||
@@ -681,7 +701,7 @@ NOT_SPACED_REGEX = NOT_REGEX.concat ')', '}', 'THIS', 'IDENTIFIER', 'STRING'
|
||||
# parentheses or bracket following these tokens will be recorded as the start
|
||||
# of a function invocation or indexing operation.
|
||||
CALLABLE = ['IDENTIFIER', 'STRING', 'REGEX', ')', ']', '}', '?', '::', '@', 'THIS', 'SUPER']
|
||||
INDEXABLE = CALLABLE.concat 'NUMBER', 'BOOL'
|
||||
INDEXABLE = CALLABLE.concat 'NUMBER', 'BOOL', 'NULL', 'UNDEFINED'
|
||||
|
||||
# Tokens that, when immediately preceding a `WHEN`, indicate that the `WHEN`
|
||||
# occurs at the start of a line. We disambiguate these from trailing whens to
|
||||
|
||||
337
src/nodes.coffee
337
src/nodes.coffee
@@ -4,10 +4,10 @@
|
||||
# the syntax tree into a string of JavaScript code, call `compile()` on the root.
|
||||
|
||||
{Scope} = require './scope'
|
||||
{RESERVED} = require './lexer'
|
||||
{RESERVED, STRICT_PROSCRIBED} = require './lexer'
|
||||
|
||||
# Import the helpers we plan to use.
|
||||
{compact, flatten, extend, merge, del, starts, ends, last} = require './helpers'
|
||||
{compact, flatten, extend, merge, del, starts, ends, last, some} = require './helpers'
|
||||
|
||||
exports.extend = extend # for parser
|
||||
|
||||
@@ -49,7 +49,7 @@ exports.Base = class Base
|
||||
# Statements converted into expressions via closure-wrapping share a scope
|
||||
# object with their parent closure, to preserve the expected lexical scope.
|
||||
compileClosure: (o) ->
|
||||
if @jumps() or this instanceof Throw
|
||||
if @jumps()
|
||||
throw SyntaxError 'cannot use a pure statement in an expression.'
|
||||
o.sharedScope = yes
|
||||
Closure.wrap(this).compileNode o
|
||||
@@ -227,12 +227,15 @@ exports.Block = class Block extends Base
|
||||
else if top
|
||||
node.front = true
|
||||
code = node.compile o
|
||||
codes.push if node.isStatement o then code else "#{@tab}#{code};"
|
||||
unless node.isStatement o
|
||||
code = "#{@tab}#{code};"
|
||||
code = "#{code}\n" if node instanceof Literal
|
||||
codes.push code
|
||||
else
|
||||
codes.push node.compile o, LEVEL_LIST
|
||||
if top
|
||||
if @spaced
|
||||
return '\n' + codes.join('\n\n') + '\n'
|
||||
return "\n#{codes.join '\n\n'}\n"
|
||||
else
|
||||
return codes.join '\n'
|
||||
code = codes.join(', ') or 'void 0'
|
||||
@@ -243,14 +246,22 @@ exports.Block = class Block extends Base
|
||||
# It would be better not to generate them in the first place, but for now,
|
||||
# clean up obvious double-parentheses.
|
||||
compileRoot: (o) ->
|
||||
o.indent = @tab = if o.bare then '' else TAB
|
||||
o.scope = new Scope null, this, null
|
||||
o.level = LEVEL_TOP
|
||||
@spaced = yes
|
||||
code = @compileWithDeclarations o
|
||||
# the `1` below accounts for `arguments`, always "in scope"
|
||||
return code if o.bare or o.scope.variables.length <= 1
|
||||
"(function() {\n#{code}\n}).call(this);\n"
|
||||
o.indent = if o.bare then '' else TAB
|
||||
o.scope = new Scope null, this, null
|
||||
o.level = LEVEL_TOP
|
||||
@spaced = yes
|
||||
prelude = ""
|
||||
unless o.bare
|
||||
preludeExps = for exp, i in @expressions
|
||||
break unless exp.unwrap() instanceof Comment
|
||||
exp
|
||||
rest = @expressions[preludeExps.length...]
|
||||
@expressions = preludeExps
|
||||
prelude = "#{@compileNode merge(o, indent: '')}\n" if preludeExps.length
|
||||
@expressions = rest
|
||||
code = @compileWithDeclarations o
|
||||
return code if o.bare
|
||||
"#{prelude}(function() {\n#{code}\n}).call(this);\n"
|
||||
|
||||
# Compile the expressions body for the contents of a function, with
|
||||
# declarations of all inner variables pushed up to the top.
|
||||
@@ -261,20 +272,24 @@ exports.Block = class Block extends Base
|
||||
break unless exp instanceof Comment or exp instanceof Literal
|
||||
o = merge(o, level: LEVEL_TOP)
|
||||
if i
|
||||
rest = @expressions.splice i, @expressions.length
|
||||
code = @compileNode(o)
|
||||
rest = @expressions.splice i, 9e9
|
||||
[spaced, @spaced] = [@spaced, no]
|
||||
[code , @spaced] = [(@compileNode o), spaced]
|
||||
@expressions = rest
|
||||
post = @compileNode o
|
||||
{scope} = o
|
||||
if scope.expressions is this
|
||||
declars = o.scope.hasDeclarations()
|
||||
assigns = scope.hasAssignments
|
||||
if (declars or assigns) and i
|
||||
code += '\n'
|
||||
if declars
|
||||
code += "#{@tab}var #{ scope.declaredVariables().join(', ') };\n"
|
||||
if assigns
|
||||
code += "#{@tab}var #{ multident scope.assignedVariables().join(', '), @tab };\n"
|
||||
if declars or assigns
|
||||
code += '\n' if i
|
||||
code += "#{@tab}var "
|
||||
if declars
|
||||
code += scope.declaredVariables().join ', '
|
||||
if assigns
|
||||
code += ",\n#{@tab + TAB}" if declars
|
||||
code += scope.assignedVariables().join ",\n#{@tab + TAB}"
|
||||
code += ';\n'
|
||||
code + post
|
||||
|
||||
# Wrap up the given nodes as a **Block**, unless it already happens
|
||||
@@ -306,15 +321,13 @@ exports.Literal = class Literal extends Base
|
||||
name is @value
|
||||
|
||||
jumps: (o) ->
|
||||
return no unless @isStatement()
|
||||
if not (o and (o.loop or o.block and (@value isnt 'continue'))) then this else no
|
||||
return this if @value is 'break' and not (o?.loop or o?.block)
|
||||
return this if @value is 'continue' and not o?.loop
|
||||
|
||||
compileNode: (o) ->
|
||||
code = if @isUndefined
|
||||
if o.level >= LEVEL_ACCESS then '(void 0)' else 'void 0'
|
||||
else if @value is 'this'
|
||||
code = if @value is 'this'
|
||||
if o.scope.method?.bound then o.scope.method.context else @value
|
||||
else if @value.reserved and "#{@value}" not in ['eval', 'arguments']
|
||||
else if @value.reserved
|
||||
"\"#{@value}\""
|
||||
else
|
||||
@value
|
||||
@@ -323,6 +336,23 @@ exports.Literal = class Literal extends Base
|
||||
toString: ->
|
||||
' "' + @value + '"'
|
||||
|
||||
class exports.Undefined extends Base
|
||||
isAssignable: NO
|
||||
isComplex: NO
|
||||
compileNode: (o) ->
|
||||
if o.level >= LEVEL_ACCESS then '(void 0)' else 'void 0'
|
||||
|
||||
class exports.Null extends Base
|
||||
isAssignable: NO
|
||||
isComplex: NO
|
||||
compileNode: -> "null"
|
||||
|
||||
class exports.Bool extends Base
|
||||
isAssignable: NO
|
||||
isComplex: NO
|
||||
compileNode: -> @val
|
||||
constructor: (@val) ->
|
||||
|
||||
#### Return
|
||||
|
||||
# A `return` is a *pureStatement* -- wrapping it in a closure wouldn't
|
||||
@@ -371,6 +401,7 @@ exports.Value = class Value extends Base
|
||||
isComplex : -> @hasProperties() or @base.isComplex()
|
||||
isAssignable : -> @hasProperties() or @base.isAssignable()
|
||||
isSimpleNumber : -> @base instanceof Literal and SIMPLENUM.test @base.value
|
||||
isString : -> @base instanceof Literal and IS_STRING.test @base.value
|
||||
isAtomic : ->
|
||||
for node in @properties.concat @base
|
||||
return no if node.soak or node instanceof Call
|
||||
@@ -452,7 +483,7 @@ exports.Comment = class Comment extends Base
|
||||
makeReturn: THIS
|
||||
|
||||
compileNode: (o, level) ->
|
||||
code = '/*' + multident(@comment, @tab) + "\n#{@tab}*/"
|
||||
code = '/*' + multident(@comment, @tab) + "\n#{@tab}*/\n"
|
||||
code = o.indent + code if (level or o.level) is LEVEL_TOP
|
||||
code
|
||||
|
||||
@@ -480,7 +511,7 @@ exports.Call = class Call extends Base
|
||||
# Grab the reference to the superclass's implementation of the current
|
||||
# method.
|
||||
superReference: (o) ->
|
||||
{method} = o.scope
|
||||
method = o.scope.namedMethod()
|
||||
throw SyntaxError 'cannot call super outside of a function.' unless method
|
||||
{name} = method
|
||||
throw SyntaxError 'cannot call super on an anonymous function.' unless name?
|
||||
@@ -492,6 +523,11 @@ exports.Call = class Call extends Base
|
||||
else
|
||||
"#{name}.__super__.constructor"
|
||||
|
||||
# The appropriate `this` value for a `super` call.
|
||||
superThis : (o) ->
|
||||
method = o.scope.method
|
||||
(method and not method.klass and method.context) or "this"
|
||||
|
||||
# Soaked chained invocations unfold into if/else ternary structures.
|
||||
unfoldSoak: (o) ->
|
||||
if @soak
|
||||
@@ -550,29 +586,29 @@ exports.Call = class Call extends Base
|
||||
args = @filterImplicitObjects @args
|
||||
args = (arg.compile o, LEVEL_LIST for arg in args).join ', '
|
||||
if @isSuper
|
||||
@superReference(o) + ".call(this#{ args and ', ' + args })"
|
||||
@superReference(o) + ".call(#{@superThis(o)}#{ args and ', ' + args })"
|
||||
else
|
||||
(if @isNew then 'new ' else '') + @variable.compile(o, LEVEL_ACCESS) + "(#{args})"
|
||||
|
||||
# `super()` is converted into a call against the superclass's implementation
|
||||
# of the current function.
|
||||
compileSuper: (args, o) ->
|
||||
"#{@superReference(o)}.call(this#{ if args.length then ', ' else '' }#{args})"
|
||||
"#{@superReference(o)}.call(#{@superThis(o)}#{ if args.length then ', ' else '' }#{args})"
|
||||
|
||||
# If you call a function with a splat, it's converted into a JavaScript
|
||||
# `.apply()` call to allow an array of arguments to be passed.
|
||||
# If it's a constructor, then things get real tricky. We have to inject an
|
||||
# inner constructor in order to be able to pass the varargs.
|
||||
compileSplat: (o, splatArgs) ->
|
||||
return "#{ @superReference o }.apply(this, #{splatArgs})" if @isSuper
|
||||
return "#{ @superReference o }.apply(#{@superThis(o)}, #{splatArgs})" if @isSuper
|
||||
if @isNew
|
||||
idt = @tab + TAB
|
||||
return """
|
||||
(function(func, args, ctor) {
|
||||
#{idt}ctor.prototype = func.prototype;
|
||||
#{idt}var child = new ctor, result = func.apply(child, args);
|
||||
#{idt}return typeof result === "object" ? result : child;
|
||||
#{@tab}})(#{ @variable.compile o, LEVEL_LIST }, #{splatArgs}, function() {})
|
||||
#{idt}return Object(result) === result ? result : child;
|
||||
#{@tab}})(#{ @variable.compile o, LEVEL_LIST }, #{splatArgs}, function(){})
|
||||
"""
|
||||
base = new Value @variable
|
||||
if (name = base.properties.pop()) and base.isComplex()
|
||||
@@ -665,6 +701,8 @@ exports.Range = class Range extends Base
|
||||
# Set up endpoints.
|
||||
known = @fromNum and @toNum
|
||||
idx = del o, 'index'
|
||||
idxName = del o, 'name'
|
||||
namedIndex = idxName and idxName isnt idx
|
||||
varPart = "#{idx} = #{@fromC}"
|
||||
varPart += ", #{@toC}" if @toC isnt @toVar
|
||||
varPart += ", #{@step}" if @step isnt @stepVar
|
||||
@@ -684,9 +722,18 @@ exports.Range = class Range extends Base
|
||||
stepPart = if @stepVar
|
||||
"#{idx} += #{@stepVar}"
|
||||
else if known
|
||||
if from <= to then "#{idx}++" else "#{idx}--"
|
||||
if namedIndex
|
||||
if from <= to then "++#{idx}" else "--#{idx}"
|
||||
else
|
||||
if from <= to then "#{idx}++" else "#{idx}--"
|
||||
else
|
||||
"#{cond} ? #{idx}++ : #{idx}--"
|
||||
if namedIndex
|
||||
"#{cond} ? ++#{idx} : --#{idx}"
|
||||
else
|
||||
"#{cond} ? #{idx}++ : #{idx}--"
|
||||
|
||||
varPart = "#{idxName} = #{varPart}" if namedIndex
|
||||
stepPart = "#{idxName} = #{stepPart}" if namedIndex
|
||||
|
||||
# The final loop body.
|
||||
"#{varPart}; #{condPart}; #{stepPart}"
|
||||
@@ -732,14 +779,15 @@ exports.Slice = class Slice extends Base
|
||||
compileNode: (o) ->
|
||||
{to, from} = @range
|
||||
fromStr = from and from.compile(o, LEVEL_PAREN) or '0'
|
||||
compiled = to and to.compile o, LEVEL_ACCESS
|
||||
compiled = to and to.compile o, LEVEL_PAREN
|
||||
if to and not (not @range.exclusive and +compiled is -1)
|
||||
toStr = ', ' + if @range.exclusive
|
||||
compiled
|
||||
else if SIMPLENUM.test compiled
|
||||
(+compiled + 1).toString()
|
||||
"#{+compiled + 1}"
|
||||
else
|
||||
"#{compiled} + 1 || 9e9"
|
||||
compiled = to.compile o, LEVEL_ACCESS
|
||||
"+#{compiled} + 1 || 9e9"
|
||||
".slice(#{ fromStr }#{ toStr or '' })"
|
||||
|
||||
#### Obj
|
||||
@@ -827,6 +875,8 @@ exports.Class = class Class extends Base
|
||||
tail instanceof Access and tail.name.value
|
||||
else
|
||||
@variable.base.value
|
||||
if decl in STRICT_PROSCRIBED
|
||||
throw SyntaxError "variable name may not be #{decl}"
|
||||
decl and= IDENTIFIER.test(decl) and decl
|
||||
|
||||
# For all `this`-references and bound functions in the class definition,
|
||||
@@ -851,7 +901,7 @@ exports.Class = class Class extends Base
|
||||
# Merge the properties from a top-level object as prototypal properties
|
||||
# on the class.
|
||||
addProperties: (node, name, o) ->
|
||||
props = node.base.properties[0..]
|
||||
props = node.base.properties[..]
|
||||
exprs = while assign = props.shift()
|
||||
if assign instanceof Assign
|
||||
base = assign.variable.base
|
||||
@@ -870,6 +920,8 @@ exports.Class = class Class extends Base
|
||||
else
|
||||
if assign.variable.this
|
||||
func.static = yes
|
||||
if func.bound
|
||||
func.context = name
|
||||
else
|
||||
assign.variable = new Value(new Literal(name), [(new Access new Literal 'prototype'), new Access base ])
|
||||
if func instanceof Code and func.bound
|
||||
@@ -888,6 +940,16 @@ exports.Class = class Class extends Base
|
||||
exps[i] = @addProperties node, name, o
|
||||
child.expressions = exps = flatten exps
|
||||
|
||||
# `use strict` (and other directives) must be the first expression statement(s)
|
||||
# of a function body. This method ensures the prologue is correctly positioned
|
||||
# above the `constructor`.
|
||||
hoistDirectivePrologue: ->
|
||||
index = 0
|
||||
{expressions} = @body
|
||||
++index while (node = expressions[index]) and node instanceof Comment or
|
||||
node instanceof Value and node.isString()
|
||||
@directives = expressions.splice 0, index
|
||||
|
||||
# Make sure that a constructor is defined for the class, and properly
|
||||
# configured.
|
||||
ensureConstructor: (name) ->
|
||||
@@ -895,6 +957,7 @@ exports.Class = class Class extends Base
|
||||
@ctor = new Code
|
||||
@ctor.body.push new Literal "#{name}.__super__.constructor.apply(this, arguments)" if @parent
|
||||
@ctor.body.push new Literal "#{@externalCtor}.apply(this, arguments)" if @externalCtor
|
||||
@ctor.body.makeReturn()
|
||||
@body.expressions.unshift @ctor
|
||||
@ctor.ctor = @ctor.name = name
|
||||
@ctor.klass = null
|
||||
@@ -905,20 +968,30 @@ exports.Class = class Class extends Base
|
||||
# constructor, property assignments, and inheritance getting built out below.
|
||||
compileNode: (o) ->
|
||||
decl = @determineName()
|
||||
name = decl or @name or '_Class'
|
||||
name = decl or '_Class'
|
||||
name = "_#{name}" if name.reserved
|
||||
lname = new Literal name
|
||||
|
||||
@hoistDirectivePrologue()
|
||||
@setContext name
|
||||
@walkBody name, o
|
||||
@ensureConstructor name
|
||||
@body.spaced = yes
|
||||
@body.expressions.unshift new Extends lname, @parent if @parent
|
||||
@body.expressions.unshift @ctor unless @ctor instanceof Code
|
||||
@body.expressions.push lname
|
||||
@body.expressions.unshift @directives...
|
||||
@addBoundFunctions o
|
||||
|
||||
klass = new Parens Closure.wrap(@body), true
|
||||
call = Closure.wrap @body
|
||||
|
||||
if @parent
|
||||
@superClass = new Literal o.scope.freeVariable 'super', no
|
||||
@body.expressions.unshift new Extends lname, @superClass
|
||||
call.args.push @parent
|
||||
params = call.variable.params or call.variable.base.params
|
||||
params.push new Param @superClass
|
||||
|
||||
klass = new Parens call, yes
|
||||
klass = new Assign @variable, klass if @variable
|
||||
klass.compile o
|
||||
|
||||
@@ -930,6 +1003,9 @@ exports.Assign = class Assign extends Base
|
||||
constructor: (@variable, @value, @context, options) ->
|
||||
@param = options and options.param
|
||||
@subpattern = options and options.subpattern
|
||||
forbidden = (name = @variable.unwrapAll().value) in STRICT_PROSCRIBED
|
||||
if forbidden and @context isnt 'object'
|
||||
throw SyntaxError "variable name may not be \"#{name}\""
|
||||
|
||||
children: ['variable', 'value']
|
||||
|
||||
@@ -995,7 +1071,7 @@ exports.Assign = class Assign extends Base
|
||||
acc = IDENTIFIER.test idx.unwrap().value or 0
|
||||
value = new Value value
|
||||
value.properties.push new (if acc then Access else Index) idx
|
||||
if obj.unwrap().value in ['arguments','eval'].concat RESERVED
|
||||
if obj.unwrap().value in RESERVED
|
||||
throw new SyntaxError "assignment to a reserved word: #{obj.compile o} = #{value.compile o}"
|
||||
return new Assign(obj, value, null, param: @param).compile o, LEVEL_TOP
|
||||
vvar = value.compile o, LEVEL_LIST
|
||||
@@ -1040,7 +1116,7 @@ exports.Assign = class Assign extends Base
|
||||
else
|
||||
acc = isObject and IDENTIFIER.test idx.unwrap().value or 0
|
||||
val = new Value new Literal(vvar), [new (if acc then Access else Index) idx]
|
||||
if name? and name in ['arguments','eval'].concat RESERVED
|
||||
if name? and name in RESERVED
|
||||
throw new SyntaxError "assignment to a reserved word: #{obj.compile o} = #{val.compile o}"
|
||||
assigns.push new Assign(obj, val, null, param: @param, subpattern: yes).compile o, LEVEL_LIST
|
||||
assigns.push vvar unless top or @subpattern
|
||||
@@ -1051,9 +1127,13 @@ exports.Assign = class Assign extends Base
|
||||
# operands are only evaluated once, even though we have to reference them
|
||||
# more than once.
|
||||
compileConditional: (o) ->
|
||||
[left, rite] = @variable.cacheReference o
|
||||
[left, right] = @variable.cacheReference o
|
||||
# Disallow conditional assignment of undefined variables.
|
||||
if not left.properties.length and left.base instanceof Literal and
|
||||
left.base.value != "this" and not o.scope.check left.base.value
|
||||
throw new Error "the variable \"#{left.base.value}\" can't be assigned with #{@context} because it has not been defined."
|
||||
if "?" in @context then o.isExistentialEquals = true
|
||||
new Op(@context[0...-1], left, new Assign(rite, @value, '=') ).compile o
|
||||
new Op(@context[...-1], left, new Assign(right, @value, '=') ).compile o
|
||||
|
||||
# Compile the assignment from an array splice literal, using JavaScript's
|
||||
# `Array#splice` method.
|
||||
@@ -1102,10 +1182,15 @@ exports.Code = class Code extends Base
|
||||
o.scope.shared = del(o, 'sharedScope')
|
||||
o.indent += TAB
|
||||
delete o.bare
|
||||
vars = []
|
||||
delete o.isExistentialEquals
|
||||
params = []
|
||||
exprs = []
|
||||
for name in @paramNames() # this step must be performed before the others
|
||||
unless o.scope.check name then o.scope.parameter name
|
||||
for param in @params when param.splat
|
||||
o.scope.add p.name.value, 'var', yes for p in @params when p.name.value
|
||||
for {name: p} in @params
|
||||
if p.this then p = p.properties[0].name
|
||||
if p.value then o.scope.add p.value, 'var', yes
|
||||
splats = new Assign new Value(new Arr(p.asReference o for p in @params)),
|
||||
new Value new Literal 'arguments'
|
||||
break
|
||||
@@ -1120,26 +1205,36 @@ exports.Code = class Code extends Base
|
||||
lit = new Literal ref.name.value + ' == null'
|
||||
val = new Assign new Value(param.name), param.value, '='
|
||||
exprs.push new If lit, val
|
||||
vars.push ref unless splats
|
||||
params.push ref unless splats
|
||||
wasEmpty = @body.isEmpty()
|
||||
exprs.unshift splats if splats
|
||||
@body.expressions.unshift exprs... if exprs.length
|
||||
o.scope.parameter vars[i] = v.compile o for v, i in vars unless splats
|
||||
o.scope.parameter params[i] = p.compile o for p, i in params
|
||||
uniqs = []
|
||||
for name in @paramNames()
|
||||
throw SyntaxError "multiple parameters named '#{name}'" if name in uniqs
|
||||
uniqs.push name
|
||||
@body.makeReturn() unless wasEmpty or @noReturn
|
||||
if @bound
|
||||
if o.scope.parent.method?.bound
|
||||
@bound = o.scope.parent.method.context
|
||||
else
|
||||
@bound = @context = o.scope.parent.method.context
|
||||
else if not @static
|
||||
o.scope.parent.assign '_this', 'this'
|
||||
idt = o.indent
|
||||
code = 'function'
|
||||
code += ' ' + @name if @ctor
|
||||
code += '(' + vars.join(', ') + ') {'
|
||||
code += '(' + params.join(', ') + ') {'
|
||||
code += "\n#{ @body.compileWithDeclarations o }\n#{@tab}" unless @body.isEmpty()
|
||||
code += '}'
|
||||
return @tab + code if @ctor
|
||||
if @front or (o.level >= LEVEL_ACCESS) then "(#{code})" else code
|
||||
|
||||
# A list of parameter names, excluding those generated by the compiler.
|
||||
paramNames: ->
|
||||
names = []
|
||||
names.push param.names()... for param in @params
|
||||
names
|
||||
|
||||
# Short-circuit `traverseChildren` method to prevent it from crossing scope boundaries
|
||||
# unless `crossScope` is `true`.
|
||||
traverseChildren: (crossScope, func) ->
|
||||
@@ -1152,6 +1247,8 @@ exports.Code = class Code extends Base
|
||||
# as well as be a splat, gathering up a group of parameters into an array.
|
||||
exports.Param = class Param extends Base
|
||||
constructor: (@name, @value, @splat) ->
|
||||
if (name = @name.unwrapAll().value) in STRICT_PROSCRIBED
|
||||
throw SyntaxError "parameter name \"#{name}\" is not allowed"
|
||||
|
||||
children: ['name', 'value']
|
||||
|
||||
@@ -1163,7 +1260,8 @@ exports.Param = class Param extends Base
|
||||
node = @name
|
||||
if node.this
|
||||
node = node.properties[0].name
|
||||
node = new Literal '_' + node.value if node.value.reserved
|
||||
if node.value.reserved
|
||||
node = new Literal o.scope.freeVariable node.value
|
||||
else if node.isComplex()
|
||||
node = new Literal o.scope.freeVariable 'arg'
|
||||
node = new Value node
|
||||
@@ -1173,6 +1271,42 @@ exports.Param = class Param extends Base
|
||||
isComplex: ->
|
||||
@name.isComplex()
|
||||
|
||||
# Finds the name or names of a `Param`; useful for detecting duplicates.
|
||||
# In a sense, a destructured parameter represents multiple JS parameters,
|
||||
# thus this method returns an `Array` of names.
|
||||
# Reserved words used as param names, as well as the Object and Array
|
||||
# literals used for destructured params, get a compiler generated name
|
||||
# during the `Code` compilation step, so this is necessarily an incomplete
|
||||
# list of a parameter's names.
|
||||
names: (name = @name)->
|
||||
atParam = (obj) ->
|
||||
{value} = obj.properties[0].name
|
||||
return if value.reserved then [] else [value]
|
||||
# * simple literals `foo`
|
||||
return [name.value] if name instanceof Literal
|
||||
# * at-params `@foo`
|
||||
return atParam(name) if name instanceof Value
|
||||
names = []
|
||||
for obj in name.objects
|
||||
# * assignments within destructured parameters `{foo:bar}`
|
||||
if obj instanceof Assign
|
||||
names.push obj.value.unwrap().value
|
||||
# * splats within destructured parameters `[xs...]`
|
||||
else if obj instanceof Splat
|
||||
names.push obj.name.unwrap().value
|
||||
else if obj instanceof Value
|
||||
# * destructured parameters within destructured parameters `[{a}]`
|
||||
if obj.isArray() or obj.isObject()
|
||||
names.push @names(obj.base)...
|
||||
# * at-params within destructured parameters `{@foo}`
|
||||
else if obj.this
|
||||
names.push atParam(obj)...
|
||||
# * simple destructured parameters {foo}
|
||||
else names.push obj.base.value
|
||||
else
|
||||
throw SyntaxError "illegal parameter #{obj.compile()}"
|
||||
names
|
||||
|
||||
#### Splat
|
||||
|
||||
# A splat, either as a parameter to a function, an argument to a call,
|
||||
@@ -1191,7 +1325,7 @@ exports.Splat = class Splat extends Base
|
||||
|
||||
compile: (o) ->
|
||||
if @index? then @compileParam o else @name.compile o
|
||||
|
||||
|
||||
unwrap: -> @name
|
||||
|
||||
# Utility function that converts an arbitrary number of elements, mixed with
|
||||
@@ -1211,7 +1345,7 @@ exports.Splat = class Splat extends Base
|
||||
then "#{ utility 'slice' }.call(#{code})"
|
||||
else "[#{code}]"
|
||||
return args[0] + ".concat(#{ args[1..].join ', ' })" if index is 0
|
||||
base = (node.compile o, LEVEL_LIST for node in list[0...index])
|
||||
base = (node.compile o, LEVEL_LIST for node in list[...index])
|
||||
"[#{ base.join ', ' }].concat(#{ args.join ', ' })"
|
||||
|
||||
#### While
|
||||
@@ -1232,7 +1366,7 @@ exports.While = class While extends Base
|
||||
if res
|
||||
super
|
||||
else
|
||||
@returns = yes
|
||||
@returns = not @jumps loop: yes
|
||||
this
|
||||
|
||||
addBody: (@body) ->
|
||||
@@ -1277,9 +1411,7 @@ exports.Op = class Op extends Base
|
||||
constructor: (op, first, second, flip ) ->
|
||||
return new In first, second if op is 'in'
|
||||
if op is 'do'
|
||||
call = new Call first, first.params or []
|
||||
call.do = yes
|
||||
return call
|
||||
return @generateDo first
|
||||
if op is 'new'
|
||||
return first.newInstance() if first instanceof Call and not first.do and not first.isNew
|
||||
first = new Parens first if first instanceof Code and first.bound or first.do
|
||||
@@ -1345,11 +1477,31 @@ exports.Op = class Op extends Base
|
||||
unfoldSoak: (o) ->
|
||||
@operator in ['++', '--', 'delete'] and unfoldSoak o, this, 'first'
|
||||
|
||||
compileNode: (o) ->
|
||||
generateDo: (exp) ->
|
||||
passedParams = []
|
||||
func = if exp instanceof Assign and (ref = exp.value.unwrap()) instanceof Code
|
||||
ref
|
||||
else
|
||||
exp
|
||||
for param in func.params or []
|
||||
if param.value
|
||||
passedParams.push param.value
|
||||
delete param.value
|
||||
else
|
||||
passedParams.push param
|
||||
call = new Call exp, passedParams
|
||||
call.do = yes
|
||||
call
|
||||
|
||||
compileNode: (o) ->
|
||||
isChain = @isChainable() and @first.isChainable()
|
||||
# In chains, there's no need to wrap bare obj literals in parens,
|
||||
# In chains, there's no need to wrap bare obj literals in parens,
|
||||
# as the chained expression is wrapped.
|
||||
@first.front = @front unless isChain
|
||||
if @operator is 'delete' and o.scope.check(@first.unwrapAll().value)
|
||||
throw SyntaxError 'delete operand may not be argument or var'
|
||||
if @operator in ['--', '++'] and @first.unwrapAll().value in STRICT_PROSCRIBED
|
||||
throw SyntaxError 'prefix increment/decrement may not have eval or arguments operand'
|
||||
return @compileUnary o if @isUnary()
|
||||
return @compileChain o if isChain
|
||||
return @compileExistence o if @operator is '?'
|
||||
@@ -1379,12 +1531,14 @@ exports.Op = class Op extends Base
|
||||
|
||||
# Compile a unary **Op**.
|
||||
compileUnary: (o) ->
|
||||
if o.level >= LEVEL_ACCESS
|
||||
return (new Parens this).compile o
|
||||
parts = [op = @operator]
|
||||
plusMinus = op in ['+', '-']
|
||||
parts.push ' ' if op in ['new', 'typeof', 'delete'] or
|
||||
plusMinus and @first instanceof Op and @first.operator is op
|
||||
if (plusMinus && @first instanceof Op) or (op is 'new' and @first.isStatement o)
|
||||
@first = new Parens @first
|
||||
@first = new Parens @first
|
||||
parts.push @first.compile o, LEVEL_OP
|
||||
parts.reverse() if @flip
|
||||
parts.join ''
|
||||
@@ -1452,15 +1606,17 @@ exports.Try = class Try extends Base
|
||||
o.indent += TAB
|
||||
errorPart = if @error then " (#{ @error.compile o }) " else ' '
|
||||
tryPart = @attempt.compile o, LEVEL_TOP
|
||||
|
||||
|
||||
catchPart = if @recovery
|
||||
if @error.value in STRICT_PROSCRIBED
|
||||
throw SyntaxError "catch variable may not be \"#{@error.value}\""
|
||||
o.scope.add @error.value, 'param' unless o.scope.check @error.value
|
||||
" catch#{errorPart}{\n#{ @recovery.compile o, LEVEL_TOP }\n#{@tab}}"
|
||||
else unless @ensure or @recovery
|
||||
' catch (_error) {}'
|
||||
|
||||
|
||||
ensurePart = if @ensure then " finally {\n#{ @ensure.compile o, LEVEL_TOP }\n#{@tab}}" else ''
|
||||
|
||||
|
||||
"""#{@tab}try {
|
||||
#{tryPart}
|
||||
#{@tab}}#{ catchPart or '' }#{ensurePart}"""
|
||||
@@ -1567,10 +1723,12 @@ exports.For = class For extends While
|
||||
scope = o.scope
|
||||
name = @name and @name.compile o, LEVEL_LIST
|
||||
index = @index and @index.compile o, LEVEL_LIST
|
||||
scope.find(name, immediate: yes) if name and not @pattern
|
||||
scope.find(index, immediate: yes) if index
|
||||
scope.find(name) if name and not @pattern
|
||||
scope.find(index) if index
|
||||
rvar = scope.freeVariable 'results' if @returns
|
||||
ivar = (if @range then name else index) or scope.freeVariable 'i'
|
||||
ivar = (@object and index) or scope.freeVariable 'i'
|
||||
kvar = (@range and name) or index or ivar
|
||||
kvarAssign = if kvar isnt ivar then "#{kvar} = " else ""
|
||||
# the `_by` variable is created twice in `Range`s if we don't prevent it from being declared here
|
||||
stepvar = scope.freeVariable "step" if @step and not @range
|
||||
name = ivar if @pattern
|
||||
@@ -1579,18 +1737,19 @@ exports.For = class For extends While
|
||||
defPart = ''
|
||||
idt1 = @tab + TAB
|
||||
if @range
|
||||
forPart = source.compile merge(o, {index: ivar, @step})
|
||||
forPart = source.compile merge(o, {index: ivar, name, @step})
|
||||
else
|
||||
svar = @source.compile o, LEVEL_LIST
|
||||
if (name or @own) and not IDENTIFIER.test svar
|
||||
defPart = "#{@tab}#{ref = scope.freeVariable 'ref'} = #{svar};\n"
|
||||
svar = ref
|
||||
if name and not @pattern
|
||||
namePart = "#{name} = #{svar}[#{ivar}]"
|
||||
namePart = "#{name} = #{svar}[#{kvar}]"
|
||||
unless @object
|
||||
lvar = scope.freeVariable 'len'
|
||||
forVarPart = "#{ivar} = 0, #{lvar} = #{svar}.length" + if @step then ", #{stepvar} = #{@step.compile(o, LEVEL_OP)}" else ''
|
||||
stepPart = if @step then "#{ivar} += #{stepvar}" else "#{ivar}++"
|
||||
forVarPart = "#{kvarAssign}#{ivar} = 0, #{lvar} = #{svar}.length"
|
||||
forVarPart += ", #{stepvar} = #{@step.compile o, LEVEL_OP}" if @step
|
||||
stepPart = "#{kvarAssign}#{if @step then "#{ivar} += #{stepvar}" else (if kvar isnt ivar then "++#{ivar}" else "#{ivar}++")}"
|
||||
forPart = "#{forVarPart}; #{ivar} < #{lvar}; #{stepPart}"
|
||||
if @returns
|
||||
resultPart = "#{@tab}#{rvar} = [];\n"
|
||||
@@ -1602,12 +1761,12 @@ exports.For = class For extends While
|
||||
else
|
||||
body = Block.wrap [new If @guard, body] if @guard
|
||||
if @pattern
|
||||
body.expressions.unshift new Assign @name, new Literal "#{svar}[#{ivar}]"
|
||||
body.expressions.unshift new Assign @name, new Literal "#{svar}[#{kvar}]"
|
||||
defPart += @pluckDirectCall o, body
|
||||
varPart = "\n#{idt1}#{namePart};" if namePart
|
||||
if @object
|
||||
forPart = "#{ivar} in #{svar}"
|
||||
guardPart = "\n#{idt1}if (!#{utility 'hasProp'}.call(#{svar}, #{ivar})) continue;" if @own
|
||||
forPart = "#{kvar} in #{svar}"
|
||||
guardPart = "\n#{idt1}if (!#{utility 'hasProp'}.call(#{svar}, #{kvar})) continue;" if @own
|
||||
body = body.compile merge(o, indent: idt1), LEVEL_TOP
|
||||
body = '\n' + body + '\n' if body
|
||||
"""
|
||||
@@ -1731,17 +1890,7 @@ exports.If = class If extends Base
|
||||
cond = @condition.compile o, LEVEL_PAREN
|
||||
o.indent += TAB
|
||||
body = @ensureBlock(@body)
|
||||
bodyc = body.compile o
|
||||
if (
|
||||
1 is body.expressions?.length and
|
||||
!@elseBody and !child and
|
||||
bodyc and cond and
|
||||
-1 is (bodyc.indexOf '\n') and
|
||||
80 > cond.length + bodyc.length
|
||||
)
|
||||
return "#{@tab}if (#{cond}) #{bodyc.replace /^\s+/, ''}"
|
||||
bodyc = "\n#{bodyc}\n#{@tab}" if bodyc
|
||||
ifPart = "if (#{cond}) {#{bodyc}}"
|
||||
ifPart = "if (#{cond}) {\n#{body.compile(o)}\n#{@tab}}"
|
||||
ifPart = @tab + ifPart unless child
|
||||
return ifPart unless @elseBody
|
||||
ifPart + ' else ' + if @isChain
|
||||
@@ -1790,9 +1939,11 @@ Closure =
|
||||
|
||||
literalArgs: (node) ->
|
||||
node instanceof Literal and node.value is 'arguments' and not node.asKey
|
||||
|
||||
literalThis: (node) ->
|
||||
(node instanceof Literal and node.value is 'this' and not node.asKey) or
|
||||
(node instanceof Code and node.bound)
|
||||
(node instanceof Code and node.bound) or
|
||||
(node instanceof Call and node.isSuper)
|
||||
|
||||
# Unfold a node's child if soak, then tuck the node under created `If`
|
||||
unfoldSoak = (o, parent, name) ->
|
||||
@@ -1809,7 +1960,7 @@ UTILITIES =
|
||||
# Correctly set up a prototype chain for inheritance, including a reference
|
||||
# to the superclass for `super()` calls, and copies of any static properties.
|
||||
extends: -> """
|
||||
function(child, parent) { for (var key in parent) { if (#{utility 'hasProp'}.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; }
|
||||
function(child, parent) { for (var key in parent) { if (#{utility 'hasProp'}.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }
|
||||
"""
|
||||
|
||||
# Create a function bound to the current value of "this".
|
||||
@@ -1819,12 +1970,12 @@ UTILITIES =
|
||||
|
||||
# Discover if an item is in an array.
|
||||
indexOf: -> """
|
||||
Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (#{utility 'hasProp'}.call(this, i) && this[i] === item) return i; } return -1; }
|
||||
[].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }
|
||||
"""
|
||||
|
||||
# Shortcuts to speed up the lookup time for native functions.
|
||||
hasProp: -> 'Object.prototype.hasOwnProperty'
|
||||
slice : -> 'Array.prototype.slice'
|
||||
hasProp: -> '{}.hasOwnProperty'
|
||||
slice : -> '[].slice'
|
||||
|
||||
# Levels indicate a node's position in the AST. Useful for knowing if
|
||||
# parens are necessary or superfluous.
|
||||
|
||||
@@ -17,34 +17,42 @@ exports.OptionParser = class OptionParser
|
||||
@rules = buildRules rules
|
||||
|
||||
# Parse the list of arguments, populating an `options` object with all of the
|
||||
# specified options, and return it. `options.arguments` will be an array
|
||||
# containing the remaining non-option arguments. `options.literals` will be
|
||||
# an array of options that are meant to be passed through directly to the
|
||||
# executing script. This is a simpler API than many option parsers that allow
|
||||
# you to attach callback actions for every flag. Instead, you're responsible
|
||||
# for interpreting the options object.
|
||||
# specified options, and return it. Options after the first non-option
|
||||
# argument are treated as arguments. `options.arguments` will be an array
|
||||
# containing the remaining arguments. This is a simpler API than many option
|
||||
# parsers that allow you to attach callback actions for every flag. Instead,
|
||||
# you're responsible for interpreting the options object.
|
||||
parse: (args) ->
|
||||
options = arguments: [], literals: []
|
||||
options = arguments: []
|
||||
skippingArgument = no
|
||||
originalArgs = args
|
||||
args = normalizeArguments args
|
||||
for arg, i in args
|
||||
if skippingArgument
|
||||
skippingArgument = no
|
||||
continue
|
||||
if arg is '--'
|
||||
pos = originalArgs.indexOf '--'
|
||||
options.arguments = [originalArgs[1 + pos]]
|
||||
options.literals = originalArgs[(2 + pos)..]
|
||||
options.arguments = options.arguments.concat originalArgs[(pos + 1)..]
|
||||
break
|
||||
isOption = !!(arg.match(LONG_FLAG) or arg.match(SHORT_FLAG))
|
||||
matchedRule = no
|
||||
for rule in @rules
|
||||
if rule.shortFlag is arg or rule.longFlag is arg
|
||||
value = if rule.hasArgument then args[i += 1] else true
|
||||
options[rule.name] = if rule.isList then (options[rule.name] or []).concat value else value
|
||||
matchedRule = yes
|
||||
break
|
||||
throw new Error "unrecognized option: #{arg}" if isOption and not matchedRule
|
||||
if not isOption
|
||||
options.arguments = originalArgs[(originalArgs.indexOf arg)..]
|
||||
break
|
||||
# the CS option parser is a little odd; options after the first
|
||||
# non-option argument are treated as non-option arguments themselves
|
||||
seenNonOptionArg = options.arguments.length > 0
|
||||
unless seenNonOptionArg
|
||||
matchedRule = no
|
||||
for rule in @rules
|
||||
if rule.shortFlag is arg or rule.longFlag is arg
|
||||
value = true
|
||||
if rule.hasArgument
|
||||
skippingArgument = yes
|
||||
value = args[i + 1]
|
||||
options[rule.name] = if rule.isList then (options[rule.name] or []).concat value else value
|
||||
matchedRule = yes
|
||||
break
|
||||
throw new Error "unrecognized option: #{arg}" if isOption and not matchedRule
|
||||
if seenNonOptionArg or not isOption
|
||||
options.arguments.push arg
|
||||
options
|
||||
|
||||
# Return the help text for this **OptionParser**, listing and describing all
|
||||
@@ -63,8 +71,8 @@ exports.OptionParser = class OptionParser
|
||||
# -------
|
||||
|
||||
# Regex matchers for option flags.
|
||||
LONG_FLAG = /^(--\w[\w\-]+)/
|
||||
SHORT_FLAG = /^(-\w)/
|
||||
LONG_FLAG = /^(--\w[\w\-]*)/
|
||||
SHORT_FLAG = /^(-\w)$/
|
||||
MULTI_FLAG = /^-(\w{2,})/
|
||||
OPTIONAL = /\[(\w+(\*?))\]/
|
||||
|
||||
@@ -92,7 +100,7 @@ buildRule = (shortFlag, longFlag, description, options = {}) ->
|
||||
# Normalize arguments by expanding merged flags into multiple flags. This allows
|
||||
# you to have `-wl` be the same as `--watch --lint`.
|
||||
normalizeArguments = (args) ->
|
||||
args = args.slice 0
|
||||
args = args[..]
|
||||
result = []
|
||||
for arg in args
|
||||
if match = arg.match MULTI_FLAG
|
||||
|
||||
180
src/repl.coffee
180
src/repl.coffee
@@ -4,6 +4,10 @@
|
||||
#
|
||||
# coffee> console.log "#{num} bottles of beer" for num in [99..1]
|
||||
|
||||
# Start by opening up `stdin` and `stdout`.
|
||||
stdin = process.openStdin()
|
||||
stdout = process.stdout
|
||||
|
||||
# Require the **coffee-script** module to get access to the compiler.
|
||||
CoffeeScript = require './coffee-script'
|
||||
readline = require 'readline'
|
||||
@@ -15,19 +19,62 @@ Module = require 'module'
|
||||
|
||||
# Config
|
||||
REPL_PROMPT = 'coffee> '
|
||||
REPL_PROMPT_MULTILINE = '------> '
|
||||
REPL_PROMPT_CONTINUATION = '......> '
|
||||
enableColours = no
|
||||
unless process.platform is 'win32'
|
||||
enableColours = not process.env.NODE_DISABLE_COLORS
|
||||
|
||||
# Start by opening up `stdin` and `stdout`.
|
||||
stdin = process.openStdin()
|
||||
stdout = process.stdout
|
||||
|
||||
# Log an error.
|
||||
error = (err) ->
|
||||
stdout.write (err.stack or err.toString()) + '\n'
|
||||
|
||||
## Autocompletion
|
||||
|
||||
# Regexes to match complete-able bits of text.
|
||||
ACCESSOR = /\s*([\w\.]+)(?:\.(\w*))$/
|
||||
SIMPLEVAR = /(\w+)$/i
|
||||
|
||||
# Returns a list of completions, and the completed text.
|
||||
autocomplete = (text) ->
|
||||
completeAttribute(text) or completeVariable(text) or [[], text]
|
||||
|
||||
# Attempt to autocomplete a chained dotted attribute: `one.two.three`.
|
||||
completeAttribute = (text) ->
|
||||
if match = text.match ACCESSOR
|
||||
[all, obj, prefix] = match
|
||||
try obj = Script.runInThisContext obj
|
||||
catch e
|
||||
return
|
||||
return unless obj?
|
||||
obj = Object obj
|
||||
candidates = Object.getOwnPropertyNames obj
|
||||
while obj = Object.getPrototypeOf obj
|
||||
for key in Object.getOwnPropertyNames obj when key not in candidates
|
||||
candidates.push key
|
||||
completions = getCompletions prefix, candidates
|
||||
[completions, prefix]
|
||||
|
||||
# Attempt to autocomplete an in-scope free variable: `one`.
|
||||
completeVariable = (text) ->
|
||||
free = text.match(SIMPLEVAR)?[1]
|
||||
free = "" if text is ""
|
||||
if free?
|
||||
vars = Script.runInThisContext 'Object.getOwnPropertyNames(Object(this))'
|
||||
keywords = (r for r in CoffeeScript.RESERVED when r[..1] isnt '__')
|
||||
candidates = vars
|
||||
for key in keywords when key not in candidates
|
||||
candidates.push key
|
||||
completions = getCompletions free, candidates
|
||||
[completions, free]
|
||||
|
||||
# Return elements of candidates for which `prefix` is a prefix.
|
||||
getCompletions = (prefix, candidates) ->
|
||||
el for el in candidates when 0 is el.indexOf prefix
|
||||
|
||||
# Make sure that uncaught exceptions don't kill the REPL.
|
||||
process.on 'uncaughtException', error
|
||||
|
||||
# The current backlog of multi-line code.
|
||||
backlog = ''
|
||||
|
||||
@@ -35,6 +82,15 @@ backlog = ''
|
||||
# Attempt to evaluate the command. If there's an exception, print it out instead
|
||||
# of exiting.
|
||||
run = (buffer) ->
|
||||
# remove single-line comments
|
||||
buffer = buffer.replace /(^|[\r\n]+)(\s*)##?(?:[^#\r\n][^\r\n]*|)($|[\r\n])/, "$1$2$3"
|
||||
# remove trailing newlines
|
||||
buffer = buffer.replace /[\r\n]+$/, ""
|
||||
if multilineMode
|
||||
backlog += "#{buffer}\n"
|
||||
repl.setPrompt REPL_PROMPT_CONTINUATION
|
||||
repl.prompt()
|
||||
return
|
||||
if !buffer.toString().trim() and !backlog
|
||||
repl.prompt()
|
||||
return
|
||||
@@ -54,68 +110,86 @@ run = (buffer) ->
|
||||
}
|
||||
if returnValue is undefined
|
||||
global._ = _
|
||||
process.stdout.write inspect(returnValue, no, 2, enableColours) + '\n'
|
||||
repl.output.write "#{inspect returnValue, no, 2, enableColours}\n"
|
||||
catch err
|
||||
error err
|
||||
repl.prompt()
|
||||
|
||||
## Autocompletion
|
||||
|
||||
# Regexes to match complete-able bits of text.
|
||||
ACCESSOR = /\s*([\w\.]+)(?:\.(\w*))$/
|
||||
SIMPLEVAR = /\s*(\w*)$/i
|
||||
|
||||
# Returns a list of completions, and the completed text.
|
||||
autocomplete = (text) ->
|
||||
completeAttribute(text) or completeVariable(text) or [[], text]
|
||||
|
||||
# Attempt to autocomplete a chained dotted attribute: `one.two.three`.
|
||||
completeAttribute = (text) ->
|
||||
if match = text.match ACCESSOR
|
||||
[all, obj, prefix] = match
|
||||
try
|
||||
val = Script.runInThisContext obj
|
||||
catch error
|
||||
return
|
||||
completions = getCompletions prefix, Object.getOwnPropertyNames val
|
||||
[completions, prefix]
|
||||
|
||||
# Attempt to autocomplete an in-scope free variable: `one`.
|
||||
completeVariable = (text) ->
|
||||
free = (text.match SIMPLEVAR)?[1]
|
||||
if free?
|
||||
vars = Script.runInThisContext 'Object.getOwnPropertyNames(this)'
|
||||
keywords = (r for r in CoffeeScript.RESERVED when r[0..1] isnt '__')
|
||||
possibilities = vars.concat keywords
|
||||
completions = getCompletions free, possibilities
|
||||
[completions, free]
|
||||
|
||||
# Return elements of candidates for which `prefix` is a prefix.
|
||||
getCompletions = (prefix, candidates) ->
|
||||
(el for el in candidates when el.indexOf(prefix) is 0)
|
||||
|
||||
# Make sure that uncaught exceptions don't kill the REPL.
|
||||
process.on 'uncaughtException', error
|
||||
|
||||
# Create the REPL by listening to **stdin**.
|
||||
if readline.createInterface.length < 3
|
||||
repl = readline.createInterface stdin, autocomplete
|
||||
stdin.on 'data', (buffer) -> repl.write buffer
|
||||
if stdin.readable and stdin.isRaw
|
||||
# handle piped input
|
||||
pipedInput = ''
|
||||
repl =
|
||||
prompt: -> stdout.write @_prompt
|
||||
setPrompt: (p) -> @_prompt = p
|
||||
input: stdin
|
||||
output: stdout
|
||||
on: ->
|
||||
stdin.on 'data', (chunk) ->
|
||||
pipedInput += chunk
|
||||
return unless /\n/.test pipedInput
|
||||
lines = pipedInput.split "\n"
|
||||
pipedInput = lines[lines.length - 1]
|
||||
for line in lines[...-1] when line
|
||||
stdout.write "#{line}\n"
|
||||
run line
|
||||
return
|
||||
stdin.on 'end', ->
|
||||
for line in pipedInput.trim().split "\n" when line
|
||||
stdout.write "#{line}\n"
|
||||
run line
|
||||
stdout.write '\n'
|
||||
process.exit 0
|
||||
else
|
||||
repl = readline.createInterface stdin, stdout, autocomplete
|
||||
# Create the REPL by listening to **stdin**.
|
||||
if readline.createInterface.length < 3
|
||||
repl = readline.createInterface stdin, autocomplete
|
||||
stdin.on 'data', (buffer) -> repl.write buffer
|
||||
else
|
||||
repl = readline.createInterface stdin, stdout, autocomplete
|
||||
|
||||
multilineMode = off
|
||||
|
||||
# Handle multi-line mode switch
|
||||
repl.input.on 'keypress', (char, key) ->
|
||||
# test for Ctrl-v
|
||||
return unless key and key.ctrl and not key.meta and not key.shift and key.name is 'v'
|
||||
cursorPos = repl.cursor
|
||||
repl.output.cursorTo 0
|
||||
repl.output.clearLine 1
|
||||
multilineMode = not multilineMode
|
||||
repl._line() if not multilineMode and backlog
|
||||
backlog = ''
|
||||
repl.setPrompt (newPrompt = if multilineMode then REPL_PROMPT_MULTILINE else REPL_PROMPT)
|
||||
repl.prompt()
|
||||
repl.output.cursorTo newPrompt.length + (repl.cursor = cursorPos)
|
||||
|
||||
# Handle Ctrl-d press at end of last line in multiline mode
|
||||
repl.input.on 'keypress', (char, key) ->
|
||||
return unless multilineMode and repl.line
|
||||
# test for Ctrl-d
|
||||
return unless key and key.ctrl and not key.meta and not key.shift and key.name is 'd'
|
||||
multilineMode = off
|
||||
repl._line()
|
||||
|
||||
repl.on 'attemptClose', ->
|
||||
if backlog
|
||||
if multilineMode
|
||||
multilineMode = off
|
||||
repl.output.cursorTo 0
|
||||
repl.output.clearLine 1
|
||||
repl._onLine repl.line
|
||||
return
|
||||
if backlog or repl.line
|
||||
backlog = ''
|
||||
process.stdout.write '\n'
|
||||
repl.historyIndex = -1
|
||||
repl.setPrompt REPL_PROMPT
|
||||
repl.prompt()
|
||||
repl.output.write '\n(^C again to quit)'
|
||||
repl._line (repl.line = '')
|
||||
else
|
||||
repl.close()
|
||||
|
||||
repl.on 'close', ->
|
||||
process.stdout.write '\n'
|
||||
stdin.destroy()
|
||||
repl.output.write '\n'
|
||||
repl.input.destroy()
|
||||
|
||||
repl.on 'line', run
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user