mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-01-13 16:57:54 -05:00
Compare commits
276 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
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 | ||
|
|
7aaaac42bc | ||
|
|
65930224ee | ||
|
|
97d1eedd5a | ||
|
|
11544f2717 | ||
|
|
74501f643c | ||
|
|
cebfe394ad | ||
|
|
3e41659095 | ||
|
|
d592d2c9cb | ||
|
|
78491b3a58 | ||
|
|
426f51db21 | ||
|
|
8a41ee95c7 | ||
|
|
5ae4e06770 | ||
|
|
683b3afbc1 | ||
|
|
1c86aee7a4 | ||
|
|
11f048c368 | ||
|
|
f0043468a0 | ||
|
|
3564f51fb5 | ||
|
|
a6081caf50 | ||
|
|
c77f7737a5 | ||
|
|
91cb433b66 | ||
|
|
2cb42b502c | ||
|
|
64bd4b3f74 | ||
|
|
41f2d2f789 | ||
|
|
913171f708 | ||
|
|
3f4daaf2ad | ||
|
|
cf32ba0149 | ||
|
|
6bec372684 | ||
|
|
620d8ce9ed | ||
|
|
bf8062ce7f | ||
|
|
350e50600d | ||
|
|
938abae4b5 | ||
|
|
264f881a81 | ||
|
|
d359764fba | ||
|
|
4a937ec3b8 | ||
|
|
0ded5b3ff3 | ||
|
|
c20a8ff53d | ||
|
|
2f38ed5e69 | ||
|
|
054fe34434 | ||
|
|
e686e3f6e9 | ||
|
|
cf996d2c4a | ||
|
|
9fef66ffcf | ||
|
|
1627922060 | ||
|
|
981db17b8f | ||
|
|
52dd348289 | ||
|
|
f4c1b20ec2 | ||
|
|
08762a101c | ||
|
|
3b5c889040 | ||
|
|
0171204e50 | ||
|
|
dd82b15b78 | ||
|
|
3d91b10927 | ||
|
|
65b3bf0d4c | ||
|
|
4c0b2372c7 | ||
|
|
54110c98d9 | ||
|
|
a2c593bc2c | ||
|
|
de0122dc17 | ||
|
|
2c43a9d209 | ||
|
|
6da70168a6 | ||
|
|
0199515cef | ||
|
|
37705e712b | ||
|
|
d2b0404188 | ||
|
|
80f9a20bfd | ||
|
|
94a9551ffa | ||
|
|
4419f7ca0f | ||
|
|
19f77cfff5 | ||
|
|
3cdee749c6 | ||
|
|
d03d288a98 | ||
|
|
b8d60a9cf1 | ||
|
|
c5dbb1c933 | ||
|
|
85342f1e31 | ||
|
|
c1f9ae8208 | ||
|
|
bd1672621c | ||
|
|
2d6cda7f32 | ||
|
|
2c8690ee39 | ||
|
|
6c98480a1e | ||
|
|
98cc7eb149 | ||
|
|
6278930aef | ||
|
|
0b57b3136c | ||
|
|
46b7a2d17c | ||
|
|
588af1f6af | ||
|
|
34f99c4a79 | ||
|
|
a0d4242da4 | ||
|
|
447c3639e7 | ||
|
|
f0e276c63a | ||
|
|
7d4e693d20 | ||
|
|
03372c9b29 | ||
|
|
6d0ba4b3bd | ||
|
|
6622f015ab | ||
|
|
d6ec5e40cc | ||
|
|
c44b80b6b6 | ||
|
|
9db814f70d | ||
|
|
d7f9054108 | ||
|
|
2df9204104 | ||
|
|
ed4f7046d3 | ||
|
|
ad1bc1e0b8 | ||
|
|
2ea51b02cc | ||
|
|
036fc561a2 | ||
|
|
a8185407fa | ||
|
|
1cc85aad64 | ||
|
|
067cd4b4fe | ||
|
|
6d68b1f5ad | ||
|
|
e8b3e2f248 | ||
|
|
d5aad39b3f | ||
|
|
cce9ac28c9 | ||
|
|
49e3a91d67 | ||
|
|
76b6a1771b | ||
|
|
c88cb5c8b5 | ||
|
|
efd503f84a | ||
|
|
7ba52ae729 | ||
|
|
8ebda7ac02 | ||
|
|
43a8b46203 | ||
|
|
d1af5163eb | ||
|
|
ee6eccbfe1 | ||
|
|
d37cfc69d9 | ||
|
|
3a6c8c92b3 | ||
|
|
e17b67e6f2 | ||
|
|
c0e0ede09f | ||
|
|
a4425471fd | ||
|
|
b4e2240ede | ||
|
|
539b872e02 | ||
|
|
2ff6c4c3fc | ||
|
|
8686e31271 | ||
|
|
0bf0f6d721 | ||
|
|
3ef0c1c88a | ||
|
|
5b115ddb74 | ||
|
|
604e39b413 | ||
|
|
f3253f4f5c | ||
|
|
2fb2ddb9b4 | ||
|
|
7e4d6198d4 | ||
|
|
8c31f2ee44 | ||
|
|
9a026e51bd | ||
|
|
50982b668b | ||
|
|
c6c988ae28 | ||
|
|
306d84828d | ||
|
|
4710e744dc | ||
|
|
0b3029dd3f | ||
|
|
41b8b3256d | ||
|
|
42f2bd926b | ||
|
|
197d07cc85 | ||
|
|
c9fd0659c2 | ||
|
|
fa2fbf0c60 | ||
|
|
c3fe29455b | ||
|
|
df5aca9348 | ||
|
|
ab0b36a53f | ||
|
|
29a44b84d5 | ||
|
|
e5b77b180a | ||
|
|
fc1cdfc913 | ||
|
|
8c5027abb9 | ||
|
|
333daf33a3 | ||
|
|
064f2b5787 | ||
|
|
13ac72239a | ||
|
|
818216374c | ||
|
|
5a9cf5722f | ||
|
|
a5ba0c27ae | ||
|
|
f6d3953bc6 | ||
|
|
c9a5135e23 | ||
|
|
ab326aea4c | ||
|
|
7cf5988099 | ||
|
|
35a30fbd6d | ||
|
|
6608a7aa98 | ||
|
|
803a7d06e3 | ||
|
|
be4685589a | ||
|
|
bf7d62affb | ||
|
|
718b73a0ba | ||
|
|
c2a43f70f2 | ||
|
|
c222da9dd6 | ||
|
|
55e366f29c | ||
|
|
4e71aad124 | ||
|
|
a03f2fe937 | ||
|
|
5710992156 | ||
|
|
0ed9be4665 | ||
|
|
d665c3a75f | ||
|
|
48f3c70013 | ||
|
|
8a4ec8f562 | ||
|
|
15fed8d17f | ||
|
|
396f9b3a12 | ||
|
|
0e0d625adb | ||
|
|
638dbbecbc | ||
|
|
ab17f41652 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -5,4 +5,5 @@ parser.output
|
||||
test/fixtures/underscore
|
||||
test/*.js
|
||||
examples/beautiful_code/parse.coffee
|
||||
*.gem
|
||||
*.gem
|
||||
/node_modules
|
||||
|
||||
91
Cakefile
91
Cakefile
@@ -1,14 +1,20 @@
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
{extend} = require './lib/helpers'
|
||||
{extend} = require './lib/coffee-script/helpers'
|
||||
CoffeeScript = require './lib/coffee-script'
|
||||
{spawn, exec} = require 'child_process'
|
||||
|
||||
# ANSI Terminal Colors.
|
||||
bold = '\033[0;1m'
|
||||
red = '\033[0;31m'
|
||||
green = '\033[0;32m'
|
||||
reset = '\033[0m'
|
||||
enableColors = no
|
||||
unless process.platform is 'win32'
|
||||
enableColors = not process.env.NODE_DISABLE_COLORS
|
||||
|
||||
bold = red = green = reset = ''
|
||||
if enableColors
|
||||
bold = '\033[0;1m'
|
||||
red = '\033[0;31m'
|
||||
green = '\033[0;32m'
|
||||
reset = '\033[0m'
|
||||
|
||||
# Built file header.
|
||||
header = """
|
||||
@@ -22,10 +28,9 @@ header = """
|
||||
"""
|
||||
|
||||
sources = [
|
||||
'src/coffee-script.coffee', 'src/grammar.coffee'
|
||||
'src/helpers.coffee', 'src/lexer.coffee', 'src/nodes.coffee'
|
||||
'src/rewriter.coffee', 'src/scope.coffee'
|
||||
]
|
||||
'coffee-script', 'grammar', 'helpers'
|
||||
'lexer', 'nodes', 'rewriter', 'scope'
|
||||
].map (filename) -> "src/#{filename}.coffee"
|
||||
|
||||
# Run a CoffeeScript through our node/coffee interpreter.
|
||||
run = (args, cb) ->
|
||||
@@ -55,7 +60,7 @@ task 'install', 'install CoffeeScript into /usr/local (or --prefix)', (options)
|
||||
"ln -sfn #{lib}/bin/coffee #{bin}/coffee"
|
||||
"ln -sfn #{lib}/bin/cake #{bin}/cake"
|
||||
"mkdir -p ~/.node_libraries"
|
||||
"ln -sfn #{lib}/lib #{node}"
|
||||
"ln -sfn #{lib}/lib/coffee-script #{node}"
|
||||
].join(' && '), (err, stdout, stderr) ->
|
||||
if err then console.log stderr.trim() else log 'done', green
|
||||
)
|
||||
@@ -64,20 +69,23 @@ task 'install', 'install CoffeeScript into /usr/local (or --prefix)', (options)
|
||||
task 'build', 'build the CoffeeScript language from source', build = (cb) ->
|
||||
files = fs.readdirSync 'src'
|
||||
files = ('src/' + file for file in files when file.match(/\.coffee$/))
|
||||
run ['-c', '-o', 'lib'].concat(files), cb
|
||||
run ['-c', '-o', 'lib/coffee-script'].concat(files), cb
|
||||
|
||||
|
||||
task 'build:full', 'rebuild the source twice, and run the tests', ->
|
||||
build ->
|
||||
build ->
|
||||
process.exit 1 unless runTests CoffeeScript
|
||||
csPath = './lib/coffee-script'
|
||||
delete require.cache[require.resolve csPath]
|
||||
unless runTests require csPath
|
||||
process.exit 1
|
||||
|
||||
|
||||
task 'build:parser', 'rebuild the Jison parser (run build first)', ->
|
||||
extend global, require('util')
|
||||
require 'jison'
|
||||
parser = require('./lib/grammar').parser
|
||||
fs.writeFile 'lib/parser.js', parser.generate()
|
||||
parser = require('./lib/coffee-script/grammar').parser
|
||||
fs.writeFile 'lib/coffee-script/parser.js', parser.generate()
|
||||
|
||||
|
||||
task 'build:ultraviolet', 'build and install the Ultraviolet syntax highlighter', ->
|
||||
@@ -92,15 +100,23 @@ task 'build:browser', 'rebuild the merged script for inclusion in the browser',
|
||||
code += """
|
||||
require['./#{name}'] = new function() {
|
||||
var exports = this;
|
||||
#{fs.readFileSync "lib/#{name}.js"}
|
||||
#{fs.readFileSync "lib/coffee-script/#{name}.js"}
|
||||
};
|
||||
"""
|
||||
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'
|
||||
@@ -125,7 +141,7 @@ task 'doc:underscore', 'rebuild the Underscore.coffee documentation page', ->
|
||||
throw err if err
|
||||
|
||||
task 'bench', 'quick benchmark of compilation time', ->
|
||||
{Rewriter} = require './lib/rewriter'
|
||||
{Rewriter} = require './lib/coffee-script/rewriter'
|
||||
co = sources.map((name) -> fs.readFileSync name).join '\n'
|
||||
fmt = (ms) -> " #{bold}#{ " #{ms}".slice -4 }#{reset} ms"
|
||||
total = 0
|
||||
@@ -153,19 +169,9 @@ runTests = (CoffeeScript) ->
|
||||
passedTests = 0
|
||||
failures = []
|
||||
|
||||
# Make "global" reference available to tests
|
||||
global.global = global
|
||||
|
||||
# Mix in the assert module globally, to make it available for tests.
|
||||
addGlobal = (name, func) ->
|
||||
global[name] = ->
|
||||
passedTests += 1
|
||||
func arguments...
|
||||
|
||||
addGlobal name, func for name, func of require 'assert'
|
||||
global[name] = func for name, func of require 'assert'
|
||||
|
||||
# Convenience aliases.
|
||||
global.eq = global.strictEqual
|
||||
global.CoffeeScript = CoffeeScript
|
||||
|
||||
# Our test helper function for delimiting different test cases.
|
||||
@@ -173,26 +179,29 @@ runTests = (CoffeeScript) ->
|
||||
try
|
||||
fn.test = {description, currentFile}
|
||||
fn.call(fn)
|
||||
++passedTests
|
||||
catch e
|
||||
e.description = description if description?
|
||||
e.source = fn.toString() if fn.toString?
|
||||
failures.push filename: currentFile, error: e
|
||||
|
||||
# A recursive functional equivalence helper; uses egal for testing equivalence.
|
||||
# See http://wiki.ecmascript.org/doku.php?id=harmony:egal
|
||||
arrayEqual = (a, b) ->
|
||||
egal = (a, b) ->
|
||||
if a is b
|
||||
# 0 isnt -0
|
||||
a isnt 0 or 1/a is 1/b
|
||||
else if a instanceof Array and b instanceof Array
|
||||
return no unless a.length is b.length
|
||||
return no for el, idx in a when not arrayEqual el, b[idx]
|
||||
yes
|
||||
else
|
||||
# NaN is NaN
|
||||
a isnt a and b isnt b
|
||||
|
||||
global.arrayEq = (a, b, msg) -> ok arrayEqual(a,b), msg
|
||||
# A recursive functional equivalence helper; uses egal for testing equivalence.
|
||||
arrayEgal = (a, b) ->
|
||||
if egal a, b then yes
|
||||
else if a instanceof Array and b instanceof Array
|
||||
return no unless a.length is b.length
|
||||
return no for el, idx in a when not arrayEgal el, b[idx]
|
||||
yes
|
||||
|
||||
global.eq = (a, b, msg) -> ok egal(a, b), msg
|
||||
global.arrayEq = (a, b, msg) -> ok arrayEgal(a,b), msg
|
||||
|
||||
# When all the tests have run, collect and print errors.
|
||||
# If a stacktrace is available, output the compiled function source.
|
||||
|
||||
7
README
7
README
@@ -1,4 +1,4 @@
|
||||
=
|
||||
|
||||
{
|
||||
} } {
|
||||
{ { } }
|
||||
@@ -29,9 +29,12 @@
|
||||
npm install -g coffee-script
|
||||
(Leave off the -g if you don't wish to install globally.)
|
||||
|
||||
Compile a script:
|
||||
Execute a script:
|
||||
coffee /path/to/script.coffee
|
||||
|
||||
Compile a script:
|
||||
coffee -c /path/to/script.coffee
|
||||
|
||||
For documentation, usage, and examples, see:
|
||||
http://coffeescript.org/
|
||||
|
||||
|
||||
2
bin/cake
2
bin/cake
@@ -4,4 +4,4 @@ var path = require('path');
|
||||
var fs = require('fs');
|
||||
var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
|
||||
|
||||
require(lib + '/cake').run();
|
||||
require(lib + '/coffee-script/cake').run();
|
||||
|
||||
@@ -4,4 +4,4 @@ var path = require('path');
|
||||
var fs = require('fs');
|
||||
var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
|
||||
|
||||
require(lib + '/command').run();
|
||||
require(lib + '/coffee-script/command').run();
|
||||
|
||||
@@ -1,2 +1,10 @@
|
||||
# Eat lunch.
|
||||
eat food for food in ['toast', 'cheese', 'wine']
|
||||
|
||||
# Fine five course dining.
|
||||
courses = ['greens', 'caviar', 'truffles', 'roast', 'cake']
|
||||
menu i + 1, dish for dish, i in courses
|
||||
|
||||
# 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.2
|
||||
CoffeeScript Compiler v1.2.0
|
||||
Released under the MIT License
|
||||
###
|
||||
|
||||
|
||||
@@ -3,3 +3,4 @@ hi = `function() {
|
||||
}`
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,3 +8,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>"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,3 +3,5 @@ numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
numbers[3..6] = [-3, -4, -5, -6]
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -264,6 +264,10 @@ div.code {
|
||||
width: 40px;
|
||||
text-transform: none;
|
||||
}
|
||||
.navigation .code a.minibutton.permalink {
|
||||
top: 38px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.bookmark {
|
||||
display: block;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<!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>
|
||||
<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="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="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="nf">(url, callback) -></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>
|
||||
|
||||
@@ -12,32 +12,45 @@ current directory's Cakefile.</p> </td> <td class="code"
|
||||
<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>
|
||||
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="nx">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>
|
||||
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="nx">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.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.run = </span><span class="o">-></span>
|
||||
<span class="nx">path</span><span class="p">.</span><span class="nx">exists</span> <span class="s1">'Cakefile'</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">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s2">"Cakefile not found in #{process.cwd()}"</span><span class="p">)</span> <span class="nx">unless</span> <span class="nx">exists</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">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>
|
||||
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>
|
||||
<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="nv">filename: </span><span class="s1">'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="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="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">catch</span> <span class="nx">e</span>
|
||||
<span class="k">return</span> <span class="nx">fatalError</span> <span class="s2">"#{e}"</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="nv">cakefilePath = </span><span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">path</span><span class="p">.</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="s1">'Cakefile'</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s2">"#{cakefilePath} 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">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="s1">'\n'</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s1">'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="s2">"No such task: #{task}"</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">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>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -6,66 +6,71 @@ 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">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>
|
||||
<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></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="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="nf">(module, filename) -></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.2'</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>
|
||||
<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="nf">(content) -></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.2.0'</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="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="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">merge</span> <span class="p">{},</span> <span class="nx">options</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="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="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-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
|
||||
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>
|
||||
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="s1">'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>
|
||||
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-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="k">if</span> <span class="nx">process</span><span class="p">.</span><span class="nx">binding</span><span class="p">(</span><span class="s1">'natives'</span><span class="p">).</span><span class="nx">module</span>
|
||||
<span class="p">{</span><span class="nx">Module</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'module'</span>
|
||||
<span class="nv">mainModule.paths = </span><span class="nx">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="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">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>
|
||||
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="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="nv">sandbox = </span><span class="nx">Script</span><span class="p">.</span><span class="nx">createContext</span><span class="p">()</span>
|
||||
<span class="nv">sandbox.global = sandbox.root = sandbox.GLOBAL = </span><span class="nx">sandbox</span>
|
||||
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sandbox</span><span class="o">?</span>
|
||||
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sandbox</span> <span class="k">instanceof</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">constructor</span>
|
||||
<span class="nv">sandbox = </span><span class="nx">options</span><span class="p">.</span><span class="nx">sandbox</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>
|
||||
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sandbox</span> <span class="k">instanceof</span> <span class="nx">Script</span><span class="p">.</span><span class="nx">createContext</span><span class="p">().</span><span class="nx">constructor</span>
|
||||
<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="nv">sandbox.global = sandbox.root = sandbox.GLOBAL = </span><span class="nx">sandbox</span>
|
||||
<span class="k">else</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="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="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="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></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="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="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="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="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="nx">Script</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="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
|
||||
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="nv">lex: </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="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="nv">upcomingInput: </span><span class="o">-></span>
|
||||
<span class="s2">""</span>
|
||||
|
||||
<span class="nv">parser.yy = </span><span class="nx">require</span> <span class="s1">'./nodes'</span>
|
||||
|
||||
@@ -10,29 +10,33 @@ interactive REPL.</p> </td> <td class="code">
|
||||
<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>
|
||||
|
||||
<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">binding</span><span class="p">(</span><span class="s1">'stdio'</span><span class="p">).</span><span class="nx">writeError</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="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="s1">'\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="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="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">'-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">'-o'</span><span class="p">,</span> <span class="s1">'--output [DIR]'</span><span class="p">,</span> <span class="s1">'set the directory for compiled JavaScript'</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 scripts before compiling'</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 recompile'</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 the compiled JavaScript to stdout'</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">'-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">'-e'</span><span class="p">,</span> <span class="s1">'--eval'</span><span class="p">,</span> <span class="s1">'compile a string from the command line'</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">'-b'</span><span class="p">,</span> <span class="s1">'--bare'</span><span class="p">,</span> <span class="s1">'compile without the top-level function wrapper'</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 the tokens that the lexer produces'</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 the parse tree that Jison 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 through to the "node" binary'</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 CoffeeScript version'</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="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>
|
||||
@@ -42,57 +46,51 @@ Many flags cause us to divert before compiling anything. Flags passed after
|
||||
<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">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="nx">printWarn</span> <span class="s2">"The --watch feature depends on Node v0.6.0+. You are running #{process.version}."</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 = 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="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="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="k">for</span> <span class="nx">source</span> <span class="k">in</span> <span class="nx">sources</span>
|
||||
<span class="nx">unprocessed</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="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="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="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">unprocessed</span><span class="p">[</span><span class="nx">sourceIndex</span><span class="p">]</span> <span class="o">+=</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">unprocessed</span><span class="p">[</span><span class="nx">sourceIndex</span><span class="p">]</span> <span class="o">-=</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="nx">unprocessed</span><span class="p">[</span><span class="nx">sourceIndex</span><span class="p">]</span> <span class="o">-=</span> <span class="mi">1</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">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">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">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">unprocessed</span><span class="p">[</span><span class="nx">sourceIndex</span><span class="p">]</span> <span class="o">-=</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="s1">'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="s1">'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="s1">'.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="s2">"#{source}.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="s2">"File not found: #{source}"</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="s1">'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="s1">'ENOENT'</span>
|
||||
<span class="nv">files = </span><span class="nx">files</span><span class="p">.</span><span class="nx">map</span> <span class="nf">(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="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">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="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="o">-></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">for</span> <span class="nx">file</span> <span class="k">in</span> <span class="nx">files</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">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="s1">'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="s1">'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>
|
||||
@@ -101,6 +99,9 @@ requested options. If evaluating the script directly sets <code>__filename</code
|
||||
<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>
|
||||
@@ -111,74 +112,157 @@ requested options. If evaluating the script directly sets <code>__filename</code
|
||||
<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="p">.</span><span class="nx">stack</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">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>
|
||||
<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="kc">on</span> <span class="s1">'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">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="o">-></span>
|
||||
<span class="k">return</span> <span class="nx">unless</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span>
|
||||
<span class="nx">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="o">-></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="s1">'\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="o">-></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="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.watchFile</code>, recompiling it every
|
||||
<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">watchFile</span> <span class="nx">source</span><span class="p">,</span> <span class="p">{</span><span class="nx">persistent</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">interval</span><span class="o">:</span> <span class="mi">500</span><span class="p">},</span> <span class="p">(</span><span class="nx">curr</span><span class="p">,</span> <span class="nx">prev</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">curr</span><span class="p">.</span><span class="nx">size</span> <span class="o">is</span> <span class="nx">prev</span><span class="p">.</span><span class="nx">size</span> <span class="o">and</span> <span class="nx">curr</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">prev</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="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>
|
||||
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="s1">'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="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="o">-></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="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="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="k">if</span> <span class="nx">prevStats</span> <span class="o">and</span> <span class="p">(</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="nv">watchErr = </span><span class="nf">(e) -></span>
|
||||
<span class="k">throw</span> <span class="nx">e</span> <span class="nx">unless</span> <span class="nx">e</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s1">'ENOENT'</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">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="nv">callback = </span><span class="nf">(event) -></span>
|
||||
<span class="k">if</span> <span class="nx">event</span> <span class="o">is</span> <span class="s1">'change'</span>
|
||||
<span class="nx">compile</span><span class="p">()</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">event</span> <span class="o">is</span> <span class="s1">'rename'</span>
|
||||
<span class="nx">watcher</span><span class="p">.</span><span class="nx">close</span><span class="p">()</span>
|
||||
<span class="nx">wait</span> <span class="mi">250</span><span class="p">,</span> <span class="o">-></span>
|
||||
<span class="nx">compile</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">callback</span>
|
||||
<span class="k">catch</span> <span class="nx">e</span>
|
||||
<span class="nx">watchErr</span> <span class="nx">e</span>
|
||||
<span class="k">catch</span> <span class="nx">e</span>
|
||||
<span class="nx">watchErr</span> <span class="nx">e</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="o">-></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="o">-></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="nx">unless</span> <span class="nx">err</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s1">'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="nv">files = </span><span class="nx">files</span><span class="p">.</span><span class="nx">map</span> <span class="nf">(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">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">notSources</span><span class="p">[</span><span class="nx">file</span><span class="p">]</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="nx">unless</span> <span class="nx">e</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s1">'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="nx">slice</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="nx">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">path</span><span class="p">.</span><span class="nx">exists</span> <span class="nx">jsPath</span><span class="p">,</span> <span class="nf">(exists) -></span>
|
||||
<span class="k">if</span> <span class="nx">exists</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="s1">'ENOENT'</span>
|
||||
<span class="nx">timeLog</span> <span class="s2">"removed #{source}"</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="s1">'.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">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="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="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">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="nx">timeLog</span> <span class="s2">"compiled #{source}"</span>
|
||||
<span class="nx">path</span><span class="p">.</span><span class="nx">exists</span> <span class="nx">jsDir</span><span class="p">,</span> <span class="nf">(exists) -></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 #{jsDir}"</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="s2">"#{(new Date).toLocaleTimeString()} - #{message}"</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="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">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
|
||||
<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-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="o">-></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="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
|
||||
<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></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="o">-></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">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
|
||||
<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="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="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="o">-></span>
|
||||
<span class="nx">printLine</span> <span class="s2">"CoffeeScript version #{CoffeeScript.VERSION}"</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -18,7 +18,7 @@ wrapper and just returning the value directly.</p> </td>
|
||||
<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>
|
||||
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="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>
|
||||
@@ -35,26 +35,25 @@ 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>
|
||||
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="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="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="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="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="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="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="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>
|
||||
<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>
|
||||
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="s1">'Value'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Invocation'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Code'</span>
|
||||
@@ -66,31 +65,34 @@ them somewhat circular.</p> </td> <td class="code">
|
||||
<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>
|
||||
<span class="nx">o</span> <span class="s1">'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>
|
||||
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="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="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="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>
|
||||
<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>
|
||||
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="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>
|
||||
<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>
|
||||
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="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">'DEBUGGER'</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="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="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 = TERMINATOR 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">$4</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>
|
||||
<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>
|
||||
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="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>
|
||||
@@ -98,240 +100,239 @@ the ordinary <strong>Assign</strong> is that these allow numbers and strings as
|
||||
<span class="nx">o</span> <span class="s1">'Comment'</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nx">ObjAssignable</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nv">ObjAssignable: </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="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="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="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="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="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>
|
||||
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="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>
|
||||
<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>
|
||||
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="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="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="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="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="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>
|
||||
<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>
|
||||
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="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="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="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="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="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="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="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">push</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">'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">concat</span> <span class="nx">$2</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="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="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>
|
||||
<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>
|
||||
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="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>
|
||||
<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>
|
||||
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="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="k">new</span> <span class="nx">Access</span> <span class="nx">$2</span><span class="p">,</span> <span class="s1">'proto'</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="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="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>
|
||||
<span class="nx">o</span> <span class="s1">'INDEX_PROTO 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">proto</span><span class="o">:</span> <span class="kc">yes</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="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="nv">IndexValue: </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="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="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>
|
||||
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="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>
|
||||
<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 Value'</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 Value 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 Value'</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 Value 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>
|
||||
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="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="nv">Invocation: </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="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="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="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="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="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="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="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="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>
|
||||
<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="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="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="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="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="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="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="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>
|
||||
(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="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="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="s1">'Expression'</span>
|
||||
<span class="nx">o</span> <span class="s1">'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>
|
||||
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="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="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="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="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="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="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="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>
|
||||
<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>
|
||||
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="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="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="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>
|
||||
<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="nv">guard: </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="nv">invert: </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="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>
|
||||
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="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>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nx">Loop</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nv">Loop: </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="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>
|
||||
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="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>
|
||||
<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="nv">ForBody: </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="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="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="p">]</span>
|
||||
|
||||
<span class="nx">ForStart</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nv">ForStart: </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="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>
|
||||
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="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>
|
||||
<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>
|
||||
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="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>
|
||||
<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="s1">'FORIN Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="nv">source: </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="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="s1">'FORIN Expression WHEN Expression'</span><span class="p">,</span> <span class="o">-></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="s1">'FOROF Expression WHEN Expression'</span><span class="p">,</span> <span class="o">-></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="s1">'FORIN Expression BY Expression'</span><span class="p">,</span> <span class="o">-></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="s1">'FORIN Expression WHEN Expression BY Expression'</span><span class="p">,</span> <span class="o">-></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="s1">'FORIN Expression BY Expression WHEN Expression'</span><span class="p">,</span> <span class="o">-></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="nv">Switch: </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="p">]</span>
|
||||
|
||||
<span class="nx">Whens</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nv">Whens: </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="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="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="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="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="nv">type: </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="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>
|
||||
<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="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>
|
||||
<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="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="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="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>
|
||||
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="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>
|
||||
<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="nv">prec: </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="nv">prec: </span><span class="s1">'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>
|
||||
@@ -395,9 +396,9 @@ as "tokens".</p> </td> <td class="code"> <
|
||||
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="s1">' '</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="s1">'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="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,9 @@ 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> </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,24 +6,27 @@ 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>
|
||||
<span class="nv">args = </span><span class="nx">normalizeArguments</span> <span class="nx">args</span>
|
||||
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">literals: </span><span class="p">[]</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">options.literals = </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="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">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>
|
||||
@@ -35,10 +38,10 @@ for interpreting the options object.</p> </td> <td class
|
||||
<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">args</span><span class="p">.</span><span class="nx">slice</span> <span class="nx">i</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>
|
||||
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="o">-></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="k">for</span> <span class="nx">rule</span> <span class="k">in</span> <span class="nx">@rules</span>
|
||||
@@ -50,22 +53,22 @@ of the valid options, for <code>--help</code> and such.</p> </td>
|
||||
<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>
|
||||
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>
|
||||
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="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-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>
|
||||
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="nx">slice</span> <span class="mi">0</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>
|
||||
|
||||
@@ -12,17 +12,10 @@ Using it looks like this:</p>
|
||||
<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\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 REPL context; must be visible outside <code>run</code> to allow for tab completion</p> </td> <td class="code"> <div class="highlight"><pre><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="nv">nonContextGlobals = </span><span class="p">[</span>
|
||||
<span class="s1">'Buffer'</span><span class="p">,</span> <span class="s1">'console'</span><span class="p">,</span> <span class="s1">'process'</span>
|
||||
<span class="s1">'setInterval'</span><span class="p">,</span> <span class="s1">'clearInterval'</span>
|
||||
<span class="s1">'setTimeout'</span><span class="p">,</span> <span class="s1">'clearTimeout'</span>
|
||||
<span class="p">]</span>
|
||||
<span class="nx">sandbox</span><span class="p">[</span><span class="nx">g</span><span class="p">]</span> <span class="o">=</span> <span class="nx">global</span><span class="p">[</span><span class="nx">g</span><span class="p">]</span> <span class="k">for</span> <span class="nx">g</span> <span class="k">in</span> <span class="nx">nonContextGlobals</span>
|
||||
<span class="nv">sandbox.global = sandbox.root = sandbox.GLOBAL = </span><span class="nx">sandbox</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 main REPL function. <strong>run</strong> is called every time a line of code is entered.
|
||||
<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="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="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.
|
||||
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>
|
||||
<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>
|
||||
@@ -35,37 +28,37 @@ of exiting.</p> </td> <td class="code"> <d
|
||||
<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="k">try</span>
|
||||
<span class="nv">_ = </span><span class="nx">sandbox</span><span class="p">.</span><span class="nx">_</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">sandbox</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">filename: </span><span class="s1">'repl'</span>
|
||||
<span class="nv">modulename: </span><span class="s1">'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">sandbox._ = </span><span class="nx">_</span>
|
||||
<span class="k">else</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="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="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-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <h1>Autocompletion</h1> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</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-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</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-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</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="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="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-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="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">val = </span><span class="nx">Script</span><span class="p">.</span><span class="nx">runInContext</span> <span class="nx">obj</span><span class="p">,</span> <span class="nx">sandbox</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-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</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="k">if</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="nv">vars = </span><span class="nx">Script</span><span class="p">.</span><span class="nx">runInContext</span> <span class="s1">'Object.getOwnPropertyNames(this)'</span><span class="p">,</span> <span class="nx">sandbox</span>
|
||||
<span class="nv">possibilities = </span><span class="nx">vars</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">RESERVED</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="nf">(text) -></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-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</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-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</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-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</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="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="nf">(prefix, candidates) -></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="nx">stdin</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'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>
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@ and shorthand syntax. This can greatly complicate a grammar and bloat
|
||||
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, balance incorrect nestings, 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:
|
||||
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="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>
|
||||
@@ -18,19 +18,17 @@ corrected before implicit parentheses can be wrapped around blocks of code.</p>
|
||||
<span class="nx">@tagPostfixConditionals</span><span class="p">()</span>
|
||||
<span class="nx">@addImplicitBraces</span><span class="p">()</span>
|
||||
<span class="nx">@addImplicitParentheses</span><span class="p">()</span>
|
||||
<span class="nx">@ensureBalance</span> <span class="nx">BALANCED_PAIRS</span>
|
||||
<span class="nx">@rewriteClosingParens</span><span class="p">()</span>
|
||||
<span class="nx">@tokens</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Rewrite the token stream, looking one token ahead and behind.
|
||||
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>
|
||||
@@ -42,47 +40,63 @@ 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>
|
||||
dispatch them here.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">removeLeadingNewlines: </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>
|
||||
<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>
|
||||
this, remove their trailing newlines.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">removeMidExpressionNewlines: </span><span class="o">-></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="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>
|
||||
<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>
|
||||
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="o">-></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="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="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="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">@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="s1">'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>
|
||||
Match it with its paired close.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">closeOpenIndexes: </span><span class="o">-></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="s1">']'</span><span class="p">,</span> <span class="s1">'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="s1">'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="s1">'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="o">-></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">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="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="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="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="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">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="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="s1">','</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="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">action = </span><span class="nf">(token, i) -></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="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="k">return</span> <span class="mi">1</span>
|
||||
@@ -91,9 +105,12 @@ Insert the missing braces here, so that the parser doesn't have to.</p>
|
||||
<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="nv">sameLine = </span><span class="kc">yes</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">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="s1">'{'</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>
|
||||
@@ -102,12 +119,26 @@ Insert the missing braces here, so that the parser doesn't have to.</p>
|
||||
<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="nv">idx = </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="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="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="o">-></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="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="s1">'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="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="s1">'='</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">not</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'CLASS'</span><span class="p">,</span> <span class="s1">'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="s1">'{'</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="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="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="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>
|
||||
@@ -123,24 +154,23 @@ deal with them.</p> </td> <td class="code">
|
||||
<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">@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="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="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="o">-></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="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="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="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">@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="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>
|
||||
@@ -158,80 +188,27 @@ but we need to make sure it's balanced.</p> </td> <td cl
|
||||
<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="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="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>
|
||||
different precedence.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tagPostfixConditionals: </span><span class="o">-></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="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'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="s1">'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="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="nx">@scanTokens</span> <span class="nf">(token, i) -></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>
|
||||
<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>Ensure that all listed pairs of tokens are correctly balanced throughout
|
||||
the course of the token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ensureBalance</span><span class="o">:</span> <span class="p">(</span><span class="nx">pairs</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">levels = </span><span class="p">{}</span>
|
||||
<span class="nv">openLine = </span><span class="p">{}</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="o">=</span> <span class="nx">token</span>
|
||||
<span class="k">for</span> <span class="p">[</span><span class="nx">open</span><span class="p">,</span> <span class="nx">close</span><span class="p">]</span> <span class="k">in</span> <span class="nx">pairs</span>
|
||||
<span class="nx">levels</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span> <span class="o">|=</span> <span class="mi">0</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="nx">open</span>
|
||||
<span class="nx">openLine</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span> <span class="o">=</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="k">if</span> <span class="nx">levels</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span><span class="o">++</span> <span class="o">is</span> <span class="mi">0</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="nx">close</span> <span class="o">and</span> <span class="o">--</span><span class="nx">levels</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span> <span class="o"><</span> <span class="mi">0</span>
|
||||
<span class="k">throw</span> <span class="nb">Error</span> <span class="s2">"too many #{token[1]} on line #{token[2] + 1}"</span>
|
||||
<span class="k">for</span> <span class="nx">open</span><span class="p">,</span> <span class="nx">level</span> <span class="k">of</span> <span class="nx">levels</span> <span class="k">when</span> <span class="nx">level</span> <span class="o">></span> <span class="mi">0</span>
|
||||
<span class="k">throw</span> <span class="nb">Error</span> <span class="s2">"unclosed #{ open } on line #{openLine[open] + 1}"</span>
|
||||
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>We'd like to support syntax like this:</p>
|
||||
|
||||
<pre><code>el.click((event) ->
|
||||
el.hide())
|
||||
</code></pre>
|
||||
|
||||
<p>In order to accomplish this, move outdents that follow closing parens
|
||||
inwards, safely. The steps to accomplish this are:</p>
|
||||
|
||||
<ol>
|
||||
<li>Check that all paired tokens are balanced and in order.</li>
|
||||
<li>Rewrite the stream with a stack: if you see an <code>EXPRESSION_START</code>, add it
|
||||
to the stack. If you see an <code>EXPRESSION_END</code>, pop the stack and replace
|
||||
it with the inverse of what we've just popped.</li>
|
||||
<li>Keep track of "debt" for tokens that we manufacture, to make sure we end
|
||||
up balanced in the end.</li>
|
||||
<li>Be careful not to alter array or parentheses delimiters with overzealous
|
||||
rewriting.</li>
|
||||
</ol> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">rewriteClosingParens</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nv">stack = </span><span class="p">[]</span>
|
||||
<span class="nv">debt = </span><span class="p">{}</span>
|
||||
<span class="nx">debt</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">for</span> <span class="nx">key</span> <span class="k">of</span> <span class="nx">INVERSES</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">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="nx">token</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="k">in</span> <span class="nx">EXPRESSION_END</span>
|
||||
<span class="k">if</span> <span class="nx">debt</span><span class="p">[</span><span class="nv">inv = </span><span class="nx">INVERSES</span><span class="p">[</span><span class="nx">tag</span><span class="p">]]</span> <span class="o">></span> <span class="mi">0</span>
|
||||
<span class="nx">debt</span><span class="p">[</span><span class="nx">inv</span><span class="p">]</span> <span class="o">-=</span> <span class="mi">1</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="nv">match = </span><span class="nx">stack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="nv">mtag = </span><span class="nx">match</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nv">oppos = </span><span class="nx">INVERSES</span><span class="p">[</span><span class="nx">mtag</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="o">is</span> <span class="nx">oppos</span>
|
||||
<span class="nx">debt</span><span class="p">[</span><span class="nx">mtag</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
|
||||
<span class="nv">val = </span><span class="p">[</span><span class="nx">oppos</span><span class="p">,</span> <span class="k">if</span> <span class="nx">mtag</span> <span class="o">is</span> <span class="s1">'INDENT'</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="nx">oppos</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">2</span><span class="p">)</span> <span class="o">is</span> <span class="nx">mtag</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">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">val</span>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="nx">match</span>
|
||||
<span class="k">else</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">val</span>
|
||||
<span class="mi">1</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</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-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</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-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</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="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) -></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="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-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>
|
||||
@@ -239,20 +216,20 @@ rewriting.</li>
|
||||
<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-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">¶</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">INVERSES = </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 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="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="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-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">¶</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-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">¶</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-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">¶</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="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="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-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">¶</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-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">¶</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-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">¶</a> </div> <p>Single-line flavors of block expressions that have unclosed endings.
|
||||
<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-28"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-28">¶</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">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>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -5,50 +5,50 @@ 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>
|
||||
|
||||
<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="s1">'arguments'</span><span class="p">,</span> <span class="nv">type: </span><span class="s1">'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="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="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>
|
||||
already exist.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">find: </span><span class="nf">(name, options) -></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>
|
||||
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>
|
||||
walks up to the root scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">check: </span><span class="nf">(name, immediate) -></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="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="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="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="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="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>
|
||||
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">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="s1">'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-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>
|
||||
(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-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="nv">hasDeclarations: </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="nv">declaredVariables: </span><span class="o">-></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>
|
||||
of this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">assignedVariables: </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>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
File diff suppressed because one or more lines are too long
@@ -44,7 +44,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>
|
||||
@@ -64,8 +65,8 @@
|
||||
<a href="#regexes">Extended Regular Expressions</a>
|
||||
<a href="#cake">Cake, and Cakefiles</a>
|
||||
<a href="#scripts">"text/coffeescript" Script Tags</a>
|
||||
<a href="#resources">Examples and Resources</a>
|
||||
<a href="#change_log">Change Log</a>
|
||||
<a href="#resources">Books, Screencasts, Examples and Resources</a>
|
||||
<a href="#changelog">Change Log</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navigation try">
|
||||
@@ -84,6 +85,7 @@
|
||||
</div>
|
||||
<div id="repl_results_wrap"><pre id="repl_results"></pre></div>
|
||||
<div class="minibutton dark run" title="Ctrl-Enter">Run</div>
|
||||
<a class="minibutton permalink" id="repl_permalink">Link</a>
|
||||
<br class="clear" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -114,7 +116,7 @@
|
||||
|
||||
<p>
|
||||
<b>CoffeeScript is a little language that compiles into JavaScript.</b> Underneath
|
||||
all of those embarrassing braces and semicolons, JavaScript has always had
|
||||
all those awkward braces and semicolons, JavaScript has always had
|
||||
a gorgeous object model at its heart. CoffeeScript is an attempt to expose
|
||||
the good parts of JavaScript in a simple way.
|
||||
</p>
|
||||
@@ -123,15 +125,16 @@
|
||||
The golden rule of CoffeeScript is: <i>"It's just JavaScript"</i>. The code
|
||||
compiles one-to-one into the equivalent JS, and there is
|
||||
no interpretation at runtime. You can use any existing JavaScript library
|
||||
seamlessly (and vice-versa). The compiled output is readable and pretty-printed,
|
||||
passes through <a href="http://www.javascriptlint.com/">JavaScript Lint</a>
|
||||
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
|
||||
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.2">1.1.2</a>
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/1.2.0">1.2.0</a>
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
@@ -145,7 +148,7 @@
|
||||
|
||||
<h2>
|
||||
<span id="installation" class="bookmark"></span>
|
||||
Installation and Usage
|
||||
Installation
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
@@ -171,7 +174,7 @@ 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
|
||||
can clone the CoffeeScript
|
||||
@@ -187,13 +190,18 @@ 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
|
||||
<a href="http://opinionatedprogrammer.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
|
||||
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,
|
||||
which can execute scripts, compile <tt>.coffee</tt> files into <tt>.js</tt>,
|
||||
@@ -213,8 +221,7 @@ sudo bin/cake install</pre>
|
||||
<td width="25%"><code>-i, --interactive</code></td>
|
||||
<td>
|
||||
Launch an interactive CoffeeScript session to try short snippets.
|
||||
More pleasant if wrapped with
|
||||
<a href="http://utopia.knoware.nl/~hlub/uck/rlwrap/rlwrap.html">rlwrap</a>.
|
||||
Identical to calling <tt>coffee</tt> with no arguments.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -228,15 +235,15 @@ sudo bin/cake install</pre>
|
||||
<td><code>-j, --join [FILE]</code></td>
|
||||
<td>
|
||||
Before compiling, concatenate all scripts together in the order they
|
||||
were passed, and write them into the specified file.
|
||||
were passed, and write them into the specified file.
|
||||
Useful for building large projects.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>-w, --watch</code></td>
|
||||
<td>
|
||||
Watch the modification times of the coffee-scripts, recompiling as
|
||||
soon as a change occurs.
|
||||
Watch files for changes, rerunning the specified command when any
|
||||
file is updated.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -281,8 +288,8 @@ sudo bin/cake install</pre>
|
||||
<tr>
|
||||
<td><code>-b, --bare</code></td>
|
||||
<td>
|
||||
Compile the JavaScript without the top-level function safety wrapper.
|
||||
(Used for CoffeeScript as a Node.js module.)
|
||||
Compile the JavaScript without the
|
||||
<a href="#lexical_scope">top-level function safety wrapper</a>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -323,9 +330,9 @@ Expressions
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Compile a directory tree of <tt>.coffee</tt> files into a parallel
|
||||
tree of <tt>.js</tt>, in <tt>lib</tt>:<br />
|
||||
<tt>coffee -o lib/ -c src/</tt>
|
||||
Compile a directory tree of <tt>.coffee</tt> files in <tt>src</tt> into a parallel
|
||||
tree of <tt>.js</tt> files in <tt>lib</tt>:<br />
|
||||
<tt>coffee --compile --output lib/ src/</tt>
|
||||
</li>
|
||||
<li>
|
||||
Watch a file for changes, and recompile it every time the file is saved:<br />
|
||||
@@ -339,6 +346,10 @@ Expressions
|
||||
Print out the compiled JS from a one-liner:<br />
|
||||
<tt>coffee -bpe "alert i for i in [0..10]"</tt>
|
||||
</li>
|
||||
<li>
|
||||
All together now, watch and recompile an entire project as you work on it:<br />
|
||||
<tt>coffee -o lib/ -cw src/</tt>
|
||||
</li>
|
||||
<li>
|
||||
Start the CoffeeScript REPL:<br />
|
||||
<tt>coffee</tt>
|
||||
@@ -491,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
|
||||
@@ -627,7 +638,7 @@ Expressions
|
||||
are the same as boolean <tt>true</tt>, while <tt>off</tt> and <tt>no</tt> are boolean <tt>false</tt>.
|
||||
</p>
|
||||
<p>
|
||||
For single-line statements, <tt>unless</tt> can be used as the inverse of <tt>if</tt>.
|
||||
<tt>unless</tt> can be used as the inverse of <tt>if</tt>.
|
||||
</p>
|
||||
<p>
|
||||
As a shortcut for <tt>this.property</tt>, you can use <tt>@property</tt>.
|
||||
@@ -775,10 +786,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>
|
||||
@@ -842,7 +858,7 @@ Expressions
|
||||
indentation level that begins the heredoc is maintained throughout, so
|
||||
you can keep it all aligned with the body of your code.
|
||||
</p>
|
||||
<%= code_for('heredocs') %>
|
||||
<%= code_for('heredocs', 'html') %>
|
||||
<p>
|
||||
Double-quoted heredocs, like double-quoted strings, allow interpolation.
|
||||
</p>
|
||||
@@ -872,13 +888,13 @@ Expressions
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
CoffeeScript includes a simple build system similar to
|
||||
CoffeeScript includes a (very) simple build system similar to
|
||||
<a href="http://www.gnu.org/software/make/">Make</a> and
|
||||
<a href="http://rake.rubyforge.org/">Rake</a>. Naturally,
|
||||
it's called Cake, and is used for the build and test tasks for the CoffeeScript
|
||||
it's called Cake, and is used for the tasks that build and test the CoffeeScript
|
||||
language itself. Tasks are defined in a file named <tt>Cakefile</tt>, and
|
||||
can be invoked by running <tt>cake taskname</tt> from within the directory.
|
||||
To print a list of all the tasks and options, just run <tt>cake</tt>.
|
||||
can be invoked by running <tt>cake [task]</tt> from within the directory.
|
||||
To print a list of all the tasks and options, just type <tt>cake</tt>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -893,7 +909,11 @@ Expressions
|
||||
<p>
|
||||
If you need to invoke one task before another — for example, running
|
||||
<tt>build</tt> before <tt>test</tt>, you can use the <tt>invoke</tt> function:
|
||||
<tt>invoke 'build'</tt>
|
||||
<tt>invoke 'build'</tt>. Cake tasks are a minimal way to expose your
|
||||
CoffeeScript functions to the command line, so
|
||||
<a href="documentation/docs/cake.html">don't expect any fanciness built-in</a>.
|
||||
If you need dependencies, or async callbacks, it's best to put them in your
|
||||
code itself — not the cake task.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
@@ -926,10 +946,65 @@ Expressions
|
||||
|
||||
<h2>
|
||||
<span id="resources" class="bookmark"></span>
|
||||
Examples
|
||||
Books and Screencasts
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
There are a number of excellent books and screencasts to help you get
|
||||
started with CoffeeScript, some of which are freely available online.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="http://arcturo.github.com/library/coffeescript/">The Little Book on CoffeeScript</a>
|
||||
is a brief 5-chapter introduction to CoffeeScript, written with great
|
||||
clarity and precision by
|
||||
<a href="http://alexmaccaw.co.uk/">Alex MacCaw</a>.
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://autotelicum.github.com/Smooth-CoffeeScript/">Smooth CoffeeScript</a>
|
||||
is a reimagination of the excellent book
|
||||
<a href="http://eloquentjavascript.net/">Eloquent JavaScript</a>, as if
|
||||
it had been written in CoffeeScript instead. Covers language features
|
||||
as well a the functional and object oriented programming styles. By
|
||||
<a href="https://github.com/autotelicum">E. Hoigaard</a>.
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://pragprog.com/book/tbcoffee/coffeescript">CoffeeScript: Accelerated JavaScript Development</a>
|
||||
is <a href="http://trevorburnham.com/">Trevor Burnham</a>'s thorough
|
||||
introduction to the language. By the end of the book, you'll have built
|
||||
a fast-paced multiplayer word game, writing both the client-side and Node.js
|
||||
portions in CoffeeScript.
|
||||
</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>.
|
||||
Highly memorable for its animations which demonstrate transforming CoffeeScript
|
||||
into the equivalent JS.
|
||||
</li>
|
||||
<li>
|
||||
If you're looking for less of a time commitment, RailsCasts'
|
||||
<a href="http://railscasts.com/episodes/267-coffeescript-basics">CoffeeScript Basics</a>
|
||||
should have you covered, hitting all of the important notes about CoffeeScript
|
||||
in 11 minutes.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
Examples
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
The <a href="https://github.com/languages/coffeescript">best list of
|
||||
open-source CoffeeScript examples</a> can be found on GitHub. But just
|
||||
to throw out few more:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<b>github</b>'s <a href="http://hubot.github.com/">Hubot</a>,
|
||||
a friendly IRC robot that can perform any number of useful and useless tasks.
|
||||
</li>
|
||||
<li>
|
||||
<b>sstephenson</b>'s <a href="http://pow.cx/">Pow</a>,
|
||||
a zero-configuration Rack server, with comprehensive annotated source.
|
||||
@@ -945,7 +1020,7 @@ Expressions
|
||||
</li>
|
||||
<li>
|
||||
<b>assaf</b>'s <a href="http://zombie.labnotes.org/">Zombie.js</a>,
|
||||
A headless, full-stack, faux-browser testing library for Node.js.
|
||||
a headless, full-stack, faux-browser testing library for Node.js.
|
||||
</li>
|
||||
<li>
|
||||
<b>jashkenas</b>' <a href="documentation/docs/underscore.html">Underscore.coffee</a>, a port
|
||||
@@ -991,7 +1066,7 @@ Expressions
|
||||
<li>
|
||||
<a href="http://github.com/jashkenas/coffee-script/wiki">The CoffeeScript Wiki</a><br />
|
||||
If you've ever learned a neat CoffeeScript tip or trick, or ran into a gotcha — share it on the wiki.
|
||||
The wiki also serves as a directory of handy
|
||||
The wiki also serves as a directory of handy
|
||||
<a href="http://github.com/jashkenas/coffee-script/wiki/Text-editor-plugins">text editor extensions</a>,
|
||||
<a href="http://github.com/jashkenas/coffee-script/wiki/Web-framework-plugins">web framework plugins</a>,
|
||||
and general <a href="http://github.com/jashkenas/coffee-script/wiki/Build-tools">CoffeeScript build tools</a>.
|
||||
@@ -1018,39 +1093,107 @@ 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.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>
|
||||
<span class="timestamp"> – <small>Nov. 8, 2011</small></span>
|
||||
</b>
|
||||
<ul>
|
||||
<li>
|
||||
Ahh, whitespace. CoffeeScript's compiled JS now tries to space things
|
||||
out and keep it readable, as you can see in the examples on this page.
|
||||
</li>
|
||||
<li>
|
||||
You can now call <tt>super</tt> in class level methods in class bodies,
|
||||
and bound class methods now preserve their correct context.
|
||||
</li>
|
||||
<li>
|
||||
JavaScript has always supported octal numbers <tt>010 is 8</tt>,
|
||||
and hexadecimal numbers <tt>0xf is 15</tt>, but CoffeeScript now
|
||||
also supports binary numbers: <tt>0b10 is 2</tt>.
|
||||
</li>
|
||||
<li>
|
||||
The CoffeeScript module has been nested under a subdirectory to make
|
||||
it easier to <tt>require</tt> individual components separately, without
|
||||
having to use <b>npm</b>. For example, after adding the CoffeeScript
|
||||
folder to your path: <tt>require('coffee-script/lexer')</tt>
|
||||
</li>
|
||||
<li>
|
||||
There's a new "link" feature in Try CoffeeScript on this webpage. Use
|
||||
it to get a shareable permalink for your example script.
|
||||
</li>
|
||||
<li>
|
||||
The <tt>coffee --watch</tt> feature now only works on Node.js 0.6.0
|
||||
and higher, but now also works properly on Windows.
|
||||
</li>
|
||||
<li>
|
||||
Lots of small bug fixes from
|
||||
<b><a href="https://github.com/michaelficarra">@michaelficarra</a></b>,
|
||||
<b><a href="https://github.com/geraldalewis">@geraldalewis</a></b>,
|
||||
<b><a href="https://github.com/satyr">@satyr</a></b>, and
|
||||
<b><a href="https://github.com/trevorburnham">@trevorburnham</a></b>.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">
|
||||
<a href="https://github.com/jashkenas/coffee-script/compare/1.1.1...1.1.2">1.1.2</a>
|
||||
<span class="timestamp"> – <small>August 4, 2011</small></span>
|
||||
</b>
|
||||
We now use the native <tt>Function.prototype.bind</tt> for bound function
|
||||
literals where available.
|
||||
Fixes for: block comment formatting, <tt>?=</tt> compilation, implicit calls
|
||||
Fixes for block comment formatting, <tt>?=</tt> compilation, implicit calls
|
||||
against control structures, implicit invocation of a try/catch block,
|
||||
variadic arguments leaking from local scope, line numbers in syntax errors
|
||||
following heregexes, property access on parenthesized number literals,
|
||||
bound class methods and super with reserved names, a REPL overhaul,
|
||||
bound class methods and super with reserved names, a REPL overhaul,
|
||||
consecutive compiled semicolons, block comments in implicitly called objects,
|
||||
and a Chrome bug.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">1.1.1
|
||||
<span class="timestamp"> – <small>May 10, 2011</small></span>
|
||||
</b>
|
||||
Bugfix release for classes with external constructor functions, see
|
||||
Bugfix release for classes with external constructor functions, see
|
||||
issue #1182.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">1.1.0
|
||||
<span class="timestamp"> – <small>May 1, 2011</small></span>
|
||||
</b>
|
||||
When running via the <tt>coffee</tt> executable, <tt>process.argv</tt> and
|
||||
When running via the <tt>coffee</tt> executable, <tt>process.argv</tt> and
|
||||
friends now report <tt>coffee</tt> instead of <tt>node</tt>.
|
||||
Better compatibility with <b>Node.js 0.4.x</b> module lookup changes.
|
||||
The output in the REPL is now colorized, like Node's is.
|
||||
@@ -1530,6 +1673,7 @@ Expressions
|
||||
</div>
|
||||
|
||||
<script type="text/coffeescript">
|
||||
sourceFragment = "try:"
|
||||
|
||||
# Set up the compilation function, to run when you stop typing.
|
||||
compileSource = ->
|
||||
@@ -1546,6 +1690,9 @@ Expressions
|
||||
catch error
|
||||
$('#error').text(error.message).show()
|
||||
|
||||
# Update permalink
|
||||
$('#repl_permalink').attr 'href', "##{sourceFragment}#{encodeURIComponent source}"
|
||||
|
||||
# Listen for keypresses and recompile.
|
||||
$('#repl_source').keyup -> compileSource()
|
||||
|
||||
@@ -1592,11 +1739,21 @@ Expressions
|
||||
$('#open_webchat').click ->
|
||||
$(this).replaceWith $('<iframe src="http://webchat.freenode.net/?channels=coffeescript" width="625" height="400"></iframe>')
|
||||
|
||||
$("#repl_permalink").click (e) ->
|
||||
window.location = $(this).attr("href")
|
||||
false
|
||||
|
||||
# If source code is included in location.hash, display it.
|
||||
hash = decodeURIComponent location.hash.replace(/^#/, '')
|
||||
if hash.indexOf(sourceFragment) == 0
|
||||
src = hash.substr sourceFragment.length
|
||||
loadConsole src
|
||||
|
||||
compileSource()
|
||||
|
||||
</script>
|
||||
|
||||
<script src="documentation/vendor/jquery-1.4.2.js"></script>
|
||||
<script src="documentation/vendor/jquery-1.6.4.js"></script>
|
||||
<script src="extras/coffee-script.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
var volume, winner;
|
||||
if (ignition === true) {
|
||||
launch();
|
||||
}
|
||||
if (band !== SpinalTap) {
|
||||
volume = 10;
|
||||
}
|
||||
if (answer !== false) {
|
||||
letTheWildRumpusBegin();
|
||||
}
|
||||
if (car.speed < limit) {
|
||||
accelerate();
|
||||
}
|
||||
if (pick === 47 || pick === 92 || pick === 13) {
|
||||
winner = true;
|
||||
}
|
||||
print(inspect("My name is " + this.name));
|
||||
|
||||
if (ignition === true) launch();
|
||||
|
||||
if (band !== SpinalTap) volume = 10;
|
||||
|
||||
if (answer !== false) letTheWildRumpusBegin();
|
||||
|
||||
if (car.speed < limit) accelerate();
|
||||
|
||||
if (pick === 47 || pick === 92 || pick === 13) winner = true;
|
||||
|
||||
print(inspect("My name is " + this.name));
|
||||
|
||||
@@ -1,6 +1,21 @@
|
||||
var food, _i, _len, _ref;
|
||||
var courses, dish, food, foods, i, _i, _j, _len, _len2, _len3, _ref;
|
||||
|
||||
_ref = ['toast', 'cheese', 'wine'];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
food = _ref[_i];
|
||||
eat(food);
|
||||
}
|
||||
}
|
||||
|
||||
courses = ['greens', 'caviar', 'truffles', 'roast', 'cake'];
|
||||
|
||||
for (i = 0, _len2 = courses.length; i < _len2; i++) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
CoffeeScript Compiler v1.1.2
|
||||
CoffeeScript Compiler v1.2.0
|
||||
Released under the MIT License
|
||||
*/
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
var fs;
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
option('-o', '--output [DIR]', 'directory for compiled code');
|
||||
|
||||
task('build:parser', 'rebuild the Jison parser', function(options) {
|
||||
var code, dir;
|
||||
require('jison');
|
||||
code = require('./lib/grammar').parser.generate();
|
||||
dir = options.output || 'lib';
|
||||
return fs.writeFile("" + dir + "/parser.js", code);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,44 +1,59 @@
|
||||
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;
|
||||
};
|
||||
var Animal, Horse, Snake, sam, tom,
|
||||
__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; };
|
||||
|
||||
Animal = (function() {
|
||||
|
||||
function Animal(name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
Animal.prototype.move = function(meters) {
|
||||
return alert(this.name + (" moved " + meters + "m."));
|
||||
};
|
||||
|
||||
return Animal;
|
||||
|
||||
})();
|
||||
Snake = (function() {
|
||||
__extends(Snake, Animal);
|
||||
|
||||
Snake = (function(_super) {
|
||||
|
||||
__extends(Snake, _super);
|
||||
|
||||
function Snake() {
|
||||
Snake.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
Snake.prototype.move = function() {
|
||||
alert("Slithering...");
|
||||
return Snake.__super__.move.call(this, 5);
|
||||
};
|
||||
|
||||
return Snake;
|
||||
})();
|
||||
Horse = (function() {
|
||||
__extends(Horse, Animal);
|
||||
|
||||
})(Animal);
|
||||
|
||||
Horse = (function(_super) {
|
||||
|
||||
__extends(Horse, _super);
|
||||
|
||||
function Horse() {
|
||||
Horse.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
Horse.prototype.move = function() {
|
||||
alert("Galloping...");
|
||||
return Horse.__super__.move.call(this, 45);
|
||||
};
|
||||
|
||||
return Horse;
|
||||
})();
|
||||
|
||||
})(Animal);
|
||||
|
||||
sam = new Snake("Sammy the Python");
|
||||
|
||||
tom = new Horse("Tommy the Palomino");
|
||||
|
||||
sam.move();
|
||||
tom.move();
|
||||
|
||||
tom.move();
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
var cholesterol, healthy;
|
||||
|
||||
cholesterol = 127;
|
||||
healthy = (200 > cholesterol && cholesterol > 60);
|
||||
|
||||
healthy = (200 > cholesterol && cholesterol > 60);
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
var date, mood;
|
||||
if (singing) {
|
||||
mood = greatlyImproved;
|
||||
}
|
||||
|
||||
if (singing) mood = greatlyImproved;
|
||||
|
||||
if (happy && knowsIt) {
|
||||
clapsHands();
|
||||
chaChaCha();
|
||||
} else {
|
||||
showIt();
|
||||
}
|
||||
|
||||
date = friday ? sue : jill;
|
||||
options || (options = defaults);
|
||||
|
||||
options || (options = defaults);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
var fill;
|
||||
|
||||
fill = function(container, liquid) {
|
||||
if (liquid == null) {
|
||||
liquid = "coffee";
|
||||
}
|
||||
if (liquid == null) liquid = "coffee";
|
||||
return "Filling the " + container + " with " + liquid + "...";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
var filename, _fn, _i, _len;
|
||||
|
||||
_fn = function(filename) {
|
||||
return fs.readFile(filename, function(err, contents) {
|
||||
return compile(filename, contents.toString());
|
||||
@@ -7,4 +8,4 @@ _fn = function(filename) {
|
||||
for (_i = 0, _len = list.length; _i < _len; _i++) {
|
||||
filename = list[_i];
|
||||
_fn(filename);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
var hi;
|
||||
|
||||
hi = function() {
|
||||
return [document.title, "Hello JavaScript"].join(": ");
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
var footprints, solipsism;
|
||||
|
||||
if ((typeof mind !== "undefined" && mind !== null) && !(typeof world !== "undefined" && world !== null)) {
|
||||
solipsism = true;
|
||||
}
|
||||
if (typeof speed === "undefined" || speed === null) {
|
||||
speed = 75;
|
||||
}
|
||||
footprints = typeof yeti !== "undefined" && yeti !== null ? yeti : "bear";
|
||||
|
||||
if (typeof speed === "undefined" || speed === null) speed = 75;
|
||||
|
||||
footprints = typeof yeti !== "undefined" && yeti !== null ? yeti : "bear";
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
var eldest, grade;
|
||||
|
||||
grade = function(student) {
|
||||
if (student.excellentWork) {
|
||||
return "A+";
|
||||
@@ -12,4 +13,5 @@ grade = function(student) {
|
||||
return "C";
|
||||
}
|
||||
};
|
||||
eldest = 24 > 21 ? "Liz" : "Ike";
|
||||
|
||||
eldest = 24 > 21 ? "Liz" : "Ike";
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
var one, six, three, two;
|
||||
six = (one = 1) + (two = 2) + (three = 3);
|
||||
|
||||
six = (one = 1) + (two = 2) + (three = 3);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
var globals, name;
|
||||
|
||||
globals = ((function() {
|
||||
var _results;
|
||||
_results = [];
|
||||
@@ -6,4 +7,4 @@ globals = ((function() {
|
||||
_results.push(name);
|
||||
}
|
||||
return _results;
|
||||
})()).slice(0, 10);
|
||||
})()).slice(0, 10);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
|
||||
alert((function() {
|
||||
try {
|
||||
return nonexistent / void 0;
|
||||
} catch (error) {
|
||||
return "And the error is ... " + error;
|
||||
}
|
||||
})());
|
||||
})());
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
var Account;
|
||||
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||||
|
||||
Account = function(customer, cart) {
|
||||
var _this = this;
|
||||
this.customer = customer;
|
||||
this.cart = cart;
|
||||
return $('.shopping_cart').bind('click', __bind(function(event) {
|
||||
return this.customer.purchase(this.cart);
|
||||
}, this));
|
||||
};
|
||||
return $('.shopping_cart').bind('click', function(event) {
|
||||
return _this.customer.purchase(_this.cart);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
var cube, square;
|
||||
|
||||
square = function(x) {
|
||||
return x * x;
|
||||
};
|
||||
|
||||
cube = function(x) {
|
||||
return square(x) * x;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
var html;
|
||||
html = '<strong>\n cup of coffeescript\n</strong>';
|
||||
|
||||
html = "<strong>\n cup of coffeescript\n</strong>";
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
var OPERATOR;
|
||||
OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/;
|
||||
|
||||
OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/;
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
var author, quote, sentence;
|
||||
|
||||
author = "Wittgenstein";
|
||||
|
||||
quote = "A picture is a fact. -- " + author;
|
||||
sentence = "" + (22 / 7) + " is a decent approximation of π";
|
||||
|
||||
sentence = "" + (22 / 7) + " is a decent approximation of π";
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
var city, forecast, temp, weatherReport, _ref;
|
||||
|
||||
weatherReport = function(location) {
|
||||
return [location, 72, "Mostly Sunny"];
|
||||
};
|
||||
_ref = weatherReport("Berkeley, CA"), city = _ref[0], temp = _ref[1], forecast = _ref[2];
|
||||
|
||||
_ref = weatherReport("Berkeley, CA"), city = _ref[0], temp = _ref[1], forecast = _ref[2];
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
var age, ages, child, yearsOld;
|
||||
|
||||
yearsOld = {
|
||||
max: 10,
|
||||
ida: 9,
|
||||
tim: 11
|
||||
};
|
||||
|
||||
ages = (function() {
|
||||
var _results;
|
||||
_results = [];
|
||||
@@ -12,4 +14,4 @@ ages = (function() {
|
||||
_results.push("" + child + " is " + age);
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
var city, futurists, name, street, _ref, _ref2;
|
||||
|
||||
futurists = {
|
||||
sculptor: "Umberto Boccioni",
|
||||
painter: "Vladimir Burliuk",
|
||||
@@ -7,4 +8,5 @@ futurists = {
|
||||
address: ["Via Roma 42R", "Bellagio, Italy 22021"]
|
||||
}
|
||||
};
|
||||
_ref = futurists.poet, name = _ref.name, _ref2 = _ref.address, street = _ref2[0], city = _ref2[1];
|
||||
|
||||
_ref = futurists.poet, name = _ref.name, (_ref2 = _ref.address, street = _ref2[0], city = _ref2[1]);
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
var bitlist, kids, singers, song;
|
||||
|
||||
song = ["do", "re", "mi", "fa", "so"];
|
||||
|
||||
singers = {
|
||||
Jagger: "Rock",
|
||||
Elvis: "Roll"
|
||||
};
|
||||
|
||||
bitlist = [1, 0, 1, 0, 0, 1, 1, 1, 0];
|
||||
|
||||
kids = {
|
||||
brother: {
|
||||
name: "Max",
|
||||
@@ -14,4 +18,4 @@ kids = {
|
||||
name: "Ida",
|
||||
age: 9
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
$('.account').attr({
|
||||
"class": 'active'
|
||||
});
|
||||
log(object["class"]);
|
||||
|
||||
log(object["class"]);
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
var cubes, list, math, num, number, opposite, race, square;
|
||||
var __slice = Array.prototype.slice;
|
||||
var cubes, list, math, num, number, opposite, race, square,
|
||||
__slice = Array.prototype.slice;
|
||||
|
||||
number = 42;
|
||||
|
||||
opposite = true;
|
||||
if (opposite) {
|
||||
number = -42;
|
||||
}
|
||||
|
||||
if (opposite) number = -42;
|
||||
|
||||
square = function(x) {
|
||||
return x * x;
|
||||
};
|
||||
|
||||
list = [1, 2, 3, 4, 5];
|
||||
|
||||
math = {
|
||||
root: Math.sqrt,
|
||||
square: square,
|
||||
@@ -16,14 +20,15 @@ math = {
|
||||
return x * square(x);
|
||||
}
|
||||
};
|
||||
|
||||
race = function() {
|
||||
var runners, winner;
|
||||
winner = arguments[0], runners = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
|
||||
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;
|
||||
_results = [];
|
||||
@@ -32,4 +37,4 @@ cubes = (function() {
|
||||
_results.push(math.cube(num));
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
var theBait, theSwitch, _ref;
|
||||
|
||||
theBait = 1000;
|
||||
|
||||
theSwitch = 0;
|
||||
_ref = [theSwitch, theBait], theBait = _ref[0], theSwitch = _ref[1];
|
||||
|
||||
_ref = [theSwitch, theBait], theBait = _ref[0], theSwitch = _ref[1];
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
var close, contents, open, tag, _i, _ref;
|
||||
var __slice = Array.prototype.slice;
|
||||
var close, contents, open, tag, _i, _ref,
|
||||
__slice = Array.prototype.slice;
|
||||
|
||||
tag = "<impossible>";
|
||||
_ref = tag.split(""), open = _ref[0], contents = 3 <= _ref.length ? __slice.call(_ref, 1, _i = _ref.length - 1) : (_i = 1, []), close = _ref[_i++];
|
||||
|
||||
_ref = tag.split(""), open = _ref[0], contents = 3 <= _ref.length ? __slice.call(_ref, 1, _i = _ref.length - 1) : (_i = 1, []), close = _ref[_i++];
|
||||
|
||||
3
documentation/js/prototypes.js
vendored
3
documentation/js/prototypes.js
vendored
@@ -1,3 +1,4 @@
|
||||
|
||||
String.prototype.dasherize = function() {
|
||||
return this.replace(/_/g, "-");
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
var countdown, num;
|
||||
|
||||
countdown = (function() {
|
||||
var _results;
|
||||
_results = [];
|
||||
@@ -6,4 +7,4 @@ countdown = (function() {
|
||||
_results.push(num);
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
var changeNumbers, inner, outer;
|
||||
|
||||
outer = 1;
|
||||
|
||||
changeNumbers = function() {
|
||||
var inner;
|
||||
inner = -1;
|
||||
return outer = 10;
|
||||
};
|
||||
inner = changeNumbers();
|
||||
|
||||
inner = changeNumbers();
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
var copy, middle, numbers;
|
||||
|
||||
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
|
||||
copy = numbers.slice(0, numbers.length);
|
||||
middle = copy.slice(3, 7);
|
||||
|
||||
middle = copy.slice(3, 7);
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
var zip, _ref;
|
||||
zip = typeof lottery.drawWinner === "function" ? (_ref = lottery.drawWinner().address) != null ? _ref.zipcode : void 0 : void 0;
|
||||
|
||||
zip = typeof lottery.drawWinner === "function" ? (_ref = lottery.drawWinner().address) != null ? _ref.zipcode : void 0 : void 0;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
var awardMedals, contenders, gold, rest, silver;
|
||||
var __slice = Array.prototype.slice;
|
||||
var awardMedals, contenders, gold, rest, silver,
|
||||
__slice = Array.prototype.slice;
|
||||
|
||||
gold = silver = rest = "unknown";
|
||||
|
||||
awardMedals = function() {
|
||||
var first, others, second;
|
||||
first = arguments[0], second = arguments[1], others = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
|
||||
@@ -8,8 +10,13 @@ awardMedals = function() {
|
||||
silver = second;
|
||||
return rest = others;
|
||||
};
|
||||
|
||||
contenders = ["Michael Phelps", "Liu Xiang", "Yao Ming", "Allyson Felix", "Shawn Johnson", "Roman Sebrle", "Guo Jingjing", "Tyson Gay", "Asafa Powell", "Usain Bolt"];
|
||||
|
||||
awardMedals.apply(null, contenders);
|
||||
|
||||
alert("Gold: " + gold);
|
||||
|
||||
alert("Silver: " + silver);
|
||||
alert("The Field: " + rest);
|
||||
|
||||
alert("The Field: " + rest);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
var numbers, _ref;
|
||||
|
||||
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
[].splice.apply(numbers, [3, 4].concat(_ref = [-3, -4, -5, -6])), _ref;
|
||||
|
||||
[].splice.apply(numbers, [3, 4].concat(_ref = [-3, -4, -5, -6])), _ref;
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
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...";
|
||||
|
||||
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 @@
|
||||
|
||||
switch (day) {
|
||||
case "Mon":
|
||||
go(work);
|
||||
@@ -20,4 +21,4 @@ switch (day) {
|
||||
break;
|
||||
default:
|
||||
go(work);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
try {
|
||||
allHellBreaksLoose();
|
||||
catsAndDogsLivingTogether();
|
||||
@@ -5,4 +6,4 @@ try {
|
||||
print(error);
|
||||
} finally {
|
||||
cleanUp();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
var lyrics, num;
|
||||
|
||||
if (this.studyingEconomics) {
|
||||
while (supply > demand) {
|
||||
buy();
|
||||
@@ -7,7 +8,9 @@ if (this.studyingEconomics) {
|
||||
sell();
|
||||
}
|
||||
}
|
||||
|
||||
num = 6;
|
||||
|
||||
lyrics = (function() {
|
||||
var _results;
|
||||
_results = [];
|
||||
@@ -15,4 +18,4 @@ lyrics = (function() {
|
||||
_results.push("" + num + " little monkeys, jumping on the bed. One fell out and bumped his head.");
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
})();
|
||||
|
||||
6240
documentation/vendor/jquery-1.4.2.js
vendored
6240
documentation/vendor/jquery-1.4.2.js
vendored
File diff suppressed because it is too large
Load Diff
9046
documentation/vendor/jquery-1.6.4.js
vendored
Normal file
9046
documentation/vendor/jquery-1.6.4.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@ selection_sort = (list) ->
|
||||
min = i
|
||||
|
||||
# Check the rest of the array to see if anything is smaller.
|
||||
min = j if list[j] < list[min] for j in [i + 1...len]
|
||||
min = k for v, k in list[i+1...] when v < list[min]
|
||||
|
||||
# Swap if a smaller item has been found.
|
||||
[list[i], list[min]] = [list[min], list[i]] if i isnt min
|
||||
|
||||
File diff suppressed because one or more lines are too long
723
index.html
723
index.html
File diff suppressed because it is too large
Load Diff
76
lib/cake.js
76
lib/cake.js
@@ -1,76 +0,0 @@
|
||||
(function() {
|
||||
var CoffeeScript, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks;
|
||||
fs = require('fs');
|
||||
path = require('path');
|
||||
helpers = require('./helpers');
|
||||
optparse = require('./optparse');
|
||||
CoffeeScript = require('./coffee-script');
|
||||
tasks = {};
|
||||
options = {};
|
||||
switches = [];
|
||||
oparse = null;
|
||||
helpers.extend(global, {
|
||||
task: function(name, description, action) {
|
||||
var _ref;
|
||||
if (!action) {
|
||||
_ref = [description, action], action = _ref[0], description = _ref[1];
|
||||
}
|
||||
return tasks[name] = {
|
||||
name: name,
|
||||
description: description,
|
||||
action: action
|
||||
};
|
||||
},
|
||||
option: function(letter, flag, description) {
|
||||
return switches.push([letter, flag, description]);
|
||||
},
|
||||
invoke: function(name) {
|
||||
if (!tasks[name]) {
|
||||
missingTask(name);
|
||||
}
|
||||
return tasks[name].action(options);
|
||||
}
|
||||
});
|
||||
exports.run = function() {
|
||||
return path.exists('Cakefile', function(exists) {
|
||||
var arg, args, _i, _len, _ref, _results;
|
||||
if (!exists) {
|
||||
throw new Error("Cakefile not found in " + (process.cwd()));
|
||||
}
|
||||
args = process.argv.slice(2);
|
||||
CoffeeScript.run(fs.readFileSync('Cakefile').toString(), {
|
||||
filename: 'Cakefile'
|
||||
});
|
||||
oparse = new optparse.OptionParser(switches);
|
||||
if (!args.length) {
|
||||
return printTasks();
|
||||
}
|
||||
options = oparse.parse(args);
|
||||
_ref = options.arguments;
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
arg = _ref[_i];
|
||||
_results.push(invoke(arg));
|
||||
}
|
||||
return _results;
|
||||
});
|
||||
};
|
||||
printTasks = function() {
|
||||
var desc, name, spaces, task;
|
||||
console.log('');
|
||||
for (name in tasks) {
|
||||
task = tasks[name];
|
||||
spaces = 20 - name.length;
|
||||
spaces = spaces > 0 ? Array(spaces + 1).join(' ') : '';
|
||||
desc = task.description ? "# " + task.description : '';
|
||||
console.log("cake " + name + spaces + " " + desc);
|
||||
}
|
||||
if (switches.length) {
|
||||
return console.log(oparse.help());
|
||||
}
|
||||
};
|
||||
missingTask = function(task) {
|
||||
console.log("No such task: \"" + task + "\"");
|
||||
return process.exit(1);
|
||||
};
|
||||
}).call(this);
|
||||
@@ -1,27 +1,27 @@
|
||||
(function() {
|
||||
var CoffeeScript, runScripts;
|
||||
|
||||
CoffeeScript = require('./coffee-script');
|
||||
|
||||
CoffeeScript.require = require;
|
||||
|
||||
CoffeeScript.eval = function(code, options) {
|
||||
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.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,13 +30,12 @@
|
||||
} else {
|
||||
throw new Error("Could not load " + url);
|
||||
}
|
||||
if (callback) {
|
||||
return callback();
|
||||
}
|
||||
if (callback) return callback();
|
||||
}
|
||||
};
|
||||
return xhr.send(null);
|
||||
};
|
||||
|
||||
runScripts = function() {
|
||||
var coffees, execute, index, length, s, scripts;
|
||||
scripts = document.getElementsByTagName('script');
|
||||
@@ -45,9 +44,7 @@
|
||||
_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;
|
||||
})();
|
||||
@@ -67,9 +64,11 @@
|
||||
})();
|
||||
return null;
|
||||
};
|
||||
|
||||
if (window.addEventListener) {
|
||||
addEventListener('DOMContentLoaded', runScripts, false);
|
||||
} else {
|
||||
attachEvent('onload', runScripts);
|
||||
}
|
||||
|
||||
}).call(this);
|
||||
99
lib/coffee-script/cake.js
Normal file
99
lib/coffee-script/cake.js
Normal file
@@ -0,0 +1,99 @@
|
||||
(function() {
|
||||
var CoffeeScript, cakefileDirectory, fatalError, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks;
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
path = require('path');
|
||||
|
||||
helpers = require('./helpers');
|
||||
|
||||
optparse = require('./optparse');
|
||||
|
||||
CoffeeScript = require('./coffee-script');
|
||||
|
||||
tasks = {};
|
||||
|
||||
options = {};
|
||||
|
||||
switches = [];
|
||||
|
||||
oparse = null;
|
||||
|
||||
helpers.extend(global, {
|
||||
task: function(name, description, action) {
|
||||
var _ref;
|
||||
if (!action) {
|
||||
_ref = [description, action], action = _ref[0], description = _ref[1];
|
||||
}
|
||||
return tasks[name] = {
|
||||
name: name,
|
||||
description: description,
|
||||
action: action
|
||||
};
|
||||
},
|
||||
option: function(letter, flag, description) {
|
||||
return switches.push([letter, flag, description]);
|
||||
},
|
||||
invoke: function(name) {
|
||||
if (!tasks[name]) missingTask(name);
|
||||
return tasks[name].action(options);
|
||||
}
|
||||
});
|
||||
|
||||
exports.run = function() {
|
||||
var arg, args, _i, _len, _ref, _results;
|
||||
global.__originalDirname = fs.realpathSync('.');
|
||||
process.chdir(cakefileDirectory(__originalDirname));
|
||||
args = process.argv.slice(2);
|
||||
CoffeeScript.run(fs.readFileSync('Cakefile').toString(), {
|
||||
filename: 'Cakefile'
|
||||
});
|
||||
oparse = new optparse.OptionParser(switches);
|
||||
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];
|
||||
_results.push(invoke(arg));
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
|
||||
printTasks = function() {
|
||||
var cakefilePath, desc, name, spaces, task;
|
||||
cakefilePath = path.join(path.relative(__originalDirname, process.cwd()), 'Cakefile');
|
||||
console.log("" + cakefilePath + " defines the following tasks:\n");
|
||||
for (name in tasks) {
|
||||
task = tasks[name];
|
||||
spaces = 20 - name.length;
|
||||
spaces = spaces > 0 ? Array(spaces + 1).join(' ') : '';
|
||||
desc = task.description ? "# " + task.description : '';
|
||||
console.log("cake " + name + spaces + " " + desc);
|
||||
}
|
||||
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) {
|
||||
return fatalError("No such task: " + task);
|
||||
};
|
||||
|
||||
cakefileDirectory = function(dir) {
|
||||
var parent;
|
||||
if (path.existsSync(path.join(dir, 'Cakefile'))) return dir;
|
||||
parent = path.normalize(path.join(dir, '..'));
|
||||
if (parent !== dir) return cakefileDirectory(parent);
|
||||
throw new Error("Cakefile not found in " + (process.cwd()));
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
87
lib/coffee-script.js → lib/coffee-script/coffee-script.js
Executable file → Normal file
87
lib/coffee-script.js → lib/coffee-script/coffee-script.js
Executable file → Normal file
@@ -1,10 +1,17 @@
|
||||
(function() {
|
||||
var Lexer, RESERVED, compile, fs, lexer, parser, path, _ref;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
var Lexer, RESERVED, compile, fs, lexer, parser, path, vm, _ref,
|
||||
__hasProp = Object.prototype.hasOwnProperty;
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
path = require('path');
|
||||
|
||||
_ref = require('./lexer'), Lexer = _ref.Lexer, RESERVED = _ref.RESERVED;
|
||||
|
||||
parser = require('./parser').parser;
|
||||
|
||||
vm = require('vm');
|
||||
|
||||
if (require.extensions) {
|
||||
require.extensions['.coffee'] = function(module, filename) {
|
||||
var content;
|
||||
@@ -18,15 +25,19 @@
|
||||
return compile(content);
|
||||
});
|
||||
}
|
||||
exports.VERSION = '1.1.2';
|
||||
|
||||
exports.VERSION = '1.2.0';
|
||||
|
||||
exports.RESERVED = RESERVED;
|
||||
|
||||
exports.helpers = require('./helpers');
|
||||
|
||||
exports.compile = compile = function(code, options) {
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
var merge;
|
||||
if (options == null) options = {};
|
||||
merge = exports.helpers.merge;
|
||||
try {
|
||||
return (parser.parse(lexer.tokenize(code))).compile(options);
|
||||
return (parser.parse(lexer.tokenize(code))).compile(merge({}, options));
|
||||
} catch (err) {
|
||||
if (options.filename) {
|
||||
err.message = "In " + options.filename + ", " + err.message;
|
||||
@@ -34,9 +45,11 @@
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
exports.tokens = function(code, options) {
|
||||
return lexer.tokenize(code, options);
|
||||
};
|
||||
|
||||
exports.nodes = function(source, options) {
|
||||
if (typeof source === 'string') {
|
||||
return parser.parse(lexer.tokenize(source, options));
|
||||
@@ -44,57 +57,55 @@
|
||||
return parser.parse(source);
|
||||
}
|
||||
};
|
||||
|
||||
exports.run = function(code, options) {
|
||||
var Module, mainModule;
|
||||
var mainModule;
|
||||
mainModule = require.main;
|
||||
mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : '.';
|
||||
mainModule.moduleCache && (mainModule.moduleCache = {});
|
||||
if (process.binding('natives').module) {
|
||||
Module = require('module').Module;
|
||||
mainModule.paths = Module._nodeModulePaths(path.dirname(options.filename));
|
||||
}
|
||||
mainModule.paths = require('module')._nodeModulePaths(path.dirname(options.filename));
|
||||
if (path.extname(mainModule.filename) !== '.coffee' || require.extensions) {
|
||||
return mainModule._compile(compile(code, options), mainModule.filename);
|
||||
} else {
|
||||
return mainModule._compile(code, mainModule.filename);
|
||||
}
|
||||
};
|
||||
|
||||
exports.eval = function(code, options) {
|
||||
var Module, Script, js, k, o, r, sandbox, v, _i, _len, _module, _ref2, _ref3, _ref4, _require;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
if (!(code = code.trim())) {
|
||||
return;
|
||||
}
|
||||
if (_ref2 = require('vm'), Script = _ref2.Script, _ref2) {
|
||||
sandbox = Script.createContext();
|
||||
sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox;
|
||||
var Module, Script, js, k, o, r, sandbox, v, _i, _len, _module, _ref2, _ref3, _require;
|
||||
if (options == null) options = {};
|
||||
if (!(code = code.trim())) return;
|
||||
Script = vm.Script;
|
||||
if (Script) {
|
||||
if (options.sandbox != null) {
|
||||
if (options.sandbox instanceof sandbox.constructor) {
|
||||
if (options.sandbox instanceof Script.createContext().constructor) {
|
||||
sandbox = options.sandbox;
|
||||
} else {
|
||||
_ref3 = options.sandbox;
|
||||
for (k in _ref3) {
|
||||
if (!__hasProp.call(_ref3, k)) continue;
|
||||
v = _ref3[k];
|
||||
sandbox = Script.createContext();
|
||||
_ref2 = options.sandbox;
|
||||
for (k in _ref2) {
|
||||
if (!__hasProp.call(_ref2, k)) continue;
|
||||
v = _ref2[k];
|
||||
sandbox[k] = v;
|
||||
}
|
||||
}
|
||||
sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox;
|
||||
} else {
|
||||
sandbox = global;
|
||||
}
|
||||
sandbox.__filename = options.filename || 'eval';
|
||||
sandbox.__dirname = path.dirname(sandbox.__filename);
|
||||
if (!(sandbox.module || sandbox.require)) {
|
||||
if (!(sandbox !== global || sandbox.module || sandbox.require)) {
|
||||
Module = require('module');
|
||||
sandbox.module = _module = new Module(options.modulename || 'eval');
|
||||
sandbox.require = _require = function(path) {
|
||||
return Module._load(path, _module);
|
||||
return Module._load(path, _module, true);
|
||||
};
|
||||
_module.filename = sandbox.__filename;
|
||||
_ref4 = Object.getOwnPropertyNames(require);
|
||||
for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
|
||||
r = _ref4[_i];
|
||||
_require[r] = require[r];
|
||||
_ref3 = Object.getOwnPropertyNames(require);
|
||||
for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
|
||||
r = _ref3[_i];
|
||||
if (r !== 'paths') _require[r] = require[r];
|
||||
}
|
||||
_require.paths = _module.paths = Module._nodeModulePaths(process.cwd());
|
||||
_require.resolve = function(request) {
|
||||
@@ -110,13 +121,15 @@
|
||||
}
|
||||
o.bare = true;
|
||||
js = compile(code, o);
|
||||
if (Script) {
|
||||
return Script.runInContext(js, sandbox);
|
||||
if (sandbox === global) {
|
||||
return vm.runInThisContext(js);
|
||||
} else {
|
||||
return eval(js);
|
||||
return vm.runInContext(js, sandbox);
|
||||
}
|
||||
};
|
||||
|
||||
lexer = new Lexer;
|
||||
|
||||
parser.lexer = {
|
||||
lex: function() {
|
||||
var tag, _ref2;
|
||||
@@ -131,5 +144,7 @@
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
parser.yy = require('./nodes');
|
||||
|
||||
}).call(this);
|
||||
442
lib/coffee-script/command.js
Normal file
442
lib/coffee-script/command.js
Normal file
@@ -0,0 +1,442 @@
|
||||
(function() {
|
||||
var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, forkNode, fs, helpers, 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');
|
||||
|
||||
path = require('path');
|
||||
|
||||
helpers = require('./helpers');
|
||||
|
||||
optparse = require('./optparse');
|
||||
|
||||
CoffeeScript = require('./coffee-script');
|
||||
|
||||
_ref = require('child_process'), spawn = _ref.spawn, exec = _ref.exec;
|
||||
|
||||
EventEmitter = require('events').EventEmitter;
|
||||
|
||||
helpers.extend(CoffeeScript, new EventEmitter);
|
||||
|
||||
printLine = function(line) {
|
||||
return process.stdout.write(line + '\n');
|
||||
};
|
||||
|
||||
printWarn = function(line) {
|
||||
return process.stderr.write(line + '\n');
|
||||
};
|
||||
|
||||
BANNER = 'Usage: coffee [options] path/to/script.coffee\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']];
|
||||
|
||||
opts = {};
|
||||
|
||||
sources = [];
|
||||
|
||||
sourceCode = [];
|
||||
|
||||
notSources = {};
|
||||
|
||||
watchers = {};
|
||||
|
||||
optionParser = null;
|
||||
|
||||
exports.run = function() {
|
||||
var 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.watch && !fs.watch) {
|
||||
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');
|
||||
if (opts.run) opts.literals = sources.splice(1).concat(opts.literals);
|
||||
process.argv = process.argv.slice(0, 2).concat(opts.literals);
|
||||
process.argv[0] = 'coffee';
|
||||
process.execPath = require.main.filename;
|
||||
_results = [];
|
||||
for (_i = 0, _len = sources.length; _i < _len; _i++) {
|
||||
source = sources[_i];
|
||||
_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, _i, _len, _ref2, _results;
|
||||
if (err && err.code !== 'ENOENT') throw err;
|
||||
if ((err != null ? err.code : void 0) === 'ENOENT') return;
|
||||
files = files.map(function(file) {
|
||||
return path.join(source, file);
|
||||
});
|
||||
index = sources.indexOf(source);
|
||||
[].splice.apply(sources, [index, index - index + 1].concat(files)), files;
|
||||
[].splice.apply(sourceCode, [index, index - index + 1].concat(_ref2 = files.map(function() {
|
||||
return null;
|
||||
}))), _ref2;
|
||||
_results = [];
|
||||
for (_i = 0, _len = files.length; _i < _len; _i++) {
|
||||
file = files[_i];
|
||||
_results.push(compilePath(file, false, base));
|
||||
}
|
||||
return _results;
|
||||
});
|
||||
} 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;
|
||||
options = compileOptions(file);
|
||||
try {
|
||||
t = task = {
|
||||
file: file,
|
||||
input: input,
|
||||
options: options
|
||||
};
|
||||
CoffeeScript.emit('compile', task);
|
||||
if (o.tokens) {
|
||||
return printTokens(CoffeeScript.tokens(t.input));
|
||||
} else if (o.nodes) {
|
||||
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);
|
||||
if (o.print) {
|
||||
return printLine(t.output.trim());
|
||||
} else if (o.compile) {
|
||||
return writeJs(t.file, t.output, base);
|
||||
} else if (o.lint) {
|
||||
return lint(t.file, t.output);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
CoffeeScript.emit('failure', err, task);
|
||||
if (CoffeeScript.listeners('failure').length) return;
|
||||
if (o.watch) return printLine(err.message);
|
||||
printWarn(err instanceof Error && err.stack || ("ERROR: " + err));
|
||||
return process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
compileStdio = function() {
|
||||
var code, stdin;
|
||||
code = '';
|
||||
stdin = process.openStdin();
|
||||
stdin.on('data', function(buffer) {
|
||||
if (buffer) return code += buffer.toString();
|
||||
});
|
||||
return stdin.on('end', function() {
|
||||
return compileScript(null, code);
|
||||
});
|
||||
};
|
||||
|
||||
joinTimeout = null;
|
||||
|
||||
compileJoin = function() {
|
||||
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;
|
||||
realFilename = module.filename;
|
||||
module.filename = '.';
|
||||
_ref2 = opts.require;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
req = _ref2[_i];
|
||||
require(req);
|
||||
}
|
||||
return module.filename = realFilename;
|
||||
};
|
||||
|
||||
watch = function(source, base) {
|
||||
var callback, compile, compileTimeout, prevStats, watchErr, watcher;
|
||||
prevStats = null;
|
||||
compileTimeout = null;
|
||||
watchErr = function(e) {
|
||||
if (e.code === 'ENOENT') {
|
||||
if (sources.indexOf(source) === -1) return;
|
||||
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;
|
||||
}
|
||||
prevStats = stats;
|
||||
return fs.readFile(source, function(err, code) {
|
||||
if (err) return watchErr(err);
|
||||
return compileScript(source, code.toString(), base);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
watchErr = function(e) {
|
||||
if (e.code !== 'ENOENT') throw e;
|
||||
removeSource(source, base, true);
|
||||
return compileJoin();
|
||||
};
|
||||
try {
|
||||
return watcher = fs.watch(source, callback = function(event) {
|
||||
if (event === 'change') {
|
||||
return compile();
|
||||
} else if (event === 'rename') {
|
||||
watcher.close();
|
||||
return wait(250, function() {
|
||||
compile();
|
||||
try {
|
||||
return watcher = fs.watch(source, callback);
|
||||
} catch (e) {
|
||||
return watchErr(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
return watchErr(e);
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
files = files.map(function(file) {
|
||||
return path.join(source, file);
|
||||
});
|
||||
_results = [];
|
||||
for (_i = 0, _len = files.length; _i < _len; _i++) {
|
||||
file = files[_i];
|
||||
if (!(!notSources[file])) continue;
|
||||
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();
|
||||
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 path.exists(jsPath, function(exists) {
|
||||
if (exists) {
|
||||
return fs.unlink(jsPath, function(err) {
|
||||
if (err && err.code !== 'ENOENT') throw err;
|
||||
return timeLog("removed " + source);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
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 = ' ';
|
||||
return fs.writeFile(jsPath, js, function(err) {
|
||||
if (err) {
|
||||
return printLine(err.message);
|
||||
} else if (opts.compile && opts.watch) {
|
||||
return timeLog("compiled " + source);
|
||||
}
|
||||
});
|
||||
};
|
||||
return path.exists(jsDir, function(exists) {
|
||||
if (exists) {
|
||||
return compile();
|
||||
} else {
|
||||
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) {
|
||||
return printLine(file + ':\t' + buffer.toString().trim());
|
||||
};
|
||||
conf = __dirname + '/../../extras/jsl.conf';
|
||||
jsl = spawn('jsl', ['-nologo', '-stdin', '-conf', conf]);
|
||||
jsl.stdout.on('data', printIt);
|
||||
jsl.stderr.on('data', printIt);
|
||||
jsl.stdin.write(js);
|
||||
return jsl.stdin.end();
|
||||
};
|
||||
|
||||
printTokens = function(tokens) {
|
||||
var strings, tag, token, value;
|
||||
strings = (function() {
|
||||
var _i, _len, _ref2, _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];
|
||||
_results.push("[" + tag + " " + value + "]");
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
return printLine(strings.join(' '));
|
||||
};
|
||||
|
||||
parseOptions = function() {
|
||||
var i, o, source, _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));
|
||||
sources = o.arguments;
|
||||
for (i = 0, _len = sources.length; i < _len; i++) {
|
||||
source = sources[i];
|
||||
sourceCode[i] = null;
|
||||
}
|
||||
};
|
||||
|
||||
compileOptions = function(filename) {
|
||||
return {
|
||||
filename: filename,
|
||||
bare: opts.bare
|
||||
};
|
||||
};
|
||||
|
||||
forkNode = function() {
|
||||
var args, nodeArgs;
|
||||
nodeArgs = opts.nodejs.split(/\s+/);
|
||||
args = process.argv.slice(1);
|
||||
args.splice(args.indexOf('--nodejs'), 2);
|
||||
return spawn(process.execPath, nodeArgs.concat(args), {
|
||||
cwd: process.cwd(),
|
||||
env: process.env,
|
||||
customFds: [0, 1, 2]
|
||||
});
|
||||
};
|
||||
|
||||
usage = function() {
|
||||
return printLine((new optparse.OptionParser(SWITCHES, BANNER)).help());
|
||||
};
|
||||
|
||||
version = function() {
|
||||
return printLine("CoffeeScript version " + CoffeeScript.VERSION);
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
@@ -1,18 +1,20 @@
|
||||
(function() {
|
||||
var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap;
|
||||
|
||||
Parser = require('jison').Parser;
|
||||
|
||||
unwrap = /^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/;
|
||||
|
||||
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.$&');
|
||||
return [patternString, "$$ = " + action + ";", options];
|
||||
};
|
||||
|
||||
grammar = {
|
||||
Root: [
|
||||
o('', function() {
|
||||
@@ -28,11 +30,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;
|
||||
@@ -57,18 +59,20 @@
|
||||
return new Literal($1);
|
||||
}), o('REGEX', function() {
|
||||
return new Literal($1);
|
||||
}), o('DEBUGGER', function() {
|
||||
return new Literal($1);
|
||||
}), o('BOOL', function() {
|
||||
var val;
|
||||
val = new Literal($1);
|
||||
if ($1 === 'undefined') {
|
||||
val.isUndefined = true;
|
||||
}
|
||||
if ($1 === 'undefined') val.isUndefined = true;
|
||||
return val;
|
||||
})
|
||||
],
|
||||
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);
|
||||
})
|
||||
@@ -139,9 +143,9 @@
|
||||
o('Identifier', function() {
|
||||
return new Value($1);
|
||||
}), o('Value Accessor', function() {
|
||||
return $1.push($2);
|
||||
return $1.add($2);
|
||||
}), o('Invocation Accessor', function() {
|
||||
return new Value($1, [$2]);
|
||||
return new Value($1, [].concat($2));
|
||||
}), o('ThisProperty')
|
||||
],
|
||||
Assignable: [
|
||||
@@ -166,7 +170,7 @@
|
||||
}), o('?. Identifier', function() {
|
||||
return new Access($2, 'soak');
|
||||
}), o(':: Identifier', function() {
|
||||
return new Access($2, 'proto');
|
||||
return [new Access(new Literal('prototype')), new Access($2)];
|
||||
}), o('::', function() {
|
||||
return new Access(new Literal('prototype'));
|
||||
}), o('Index')
|
||||
@@ -178,10 +182,6 @@
|
||||
return extend($2, {
|
||||
soak: true
|
||||
});
|
||||
}), o('INDEX_PROTO Index', function() {
|
||||
return extend($2, {
|
||||
proto: true
|
||||
});
|
||||
})
|
||||
],
|
||||
IndexValue: [
|
||||
@@ -214,17 +214,17 @@
|
||||
return new Class;
|
||||
}), o('CLASS Block', function() {
|
||||
return new Class(null, null, $2);
|
||||
}), o('CLASS EXTENDS Value', function() {
|
||||
}), o('CLASS EXTENDS Expression', function() {
|
||||
return new Class(null, $3);
|
||||
}), o('CLASS EXTENDS Value Block', function() {
|
||||
}), o('CLASS EXTENDS Expression Block', function() {
|
||||
return new Class(null, $3, $4);
|
||||
}), o('CLASS SimpleAssignable', function() {
|
||||
return new Class($2);
|
||||
}), o('CLASS SimpleAssignable Block', function() {
|
||||
return new Class($2, null, $3);
|
||||
}), o('CLASS SimpleAssignable EXTENDS Value', function() {
|
||||
}), o('CLASS SimpleAssignable EXTENDS Expression', function() {
|
||||
return new Class($2, $4);
|
||||
}), o('CLASS SimpleAssignable EXTENDS Value Block', function() {
|
||||
}), o('CLASS SimpleAssignable EXTENDS Expression Block', function() {
|
||||
return new Class($2, $4, $5);
|
||||
})
|
||||
],
|
||||
@@ -558,8 +558,11 @@
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
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']];
|
||||
|
||||
tokens = [];
|
||||
|
||||
for (name in grammar) {
|
||||
alternatives = grammar[name];
|
||||
grammar[name] = (function() {
|
||||
@@ -570,22 +573,20 @@
|
||||
_ref = alt[0].split(' ');
|
||||
for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) {
|
||||
token = _ref[_j];
|
||||
if (!grammar[token]) {
|
||||
tokens.push(token);
|
||||
}
|
||||
}
|
||||
if (name === 'Root') {
|
||||
alt[1] = "return " + alt[1];
|
||||
if (!grammar[token]) tokens.push(token);
|
||||
}
|
||||
if (name === 'Root') alt[1] = "return " + alt[1];
|
||||
_results.push(alt);
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
}
|
||||
|
||||
exports.parser = new Parser({
|
||||
tokens: tokens.join(' '),
|
||||
bnf: grammar,
|
||||
operators: operators.reverse(),
|
||||
startSymbol: 'Root'
|
||||
});
|
||||
|
||||
}).call(this);
|
||||
@@ -1,38 +1,40 @@
|
||||
(function() {
|
||||
var extend, flatten;
|
||||
|
||||
exports.starts = function(string, literal, start) {
|
||||
return literal === string.substr(start, literal.length);
|
||||
};
|
||||
|
||||
exports.ends = function(string, literal, back) {
|
||||
var len;
|
||||
len = literal.length;
|
||||
return literal === string.substr(string.length - len - (back || 0), len);
|
||||
};
|
||||
|
||||
exports.compact = function(array) {
|
||||
var item, _i, _len, _results;
|
||||
_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;
|
||||
};
|
||||
|
||||
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++;
|
||||
}
|
||||
return num;
|
||||
};
|
||||
|
||||
exports.merge = function(options, overrides) {
|
||||
return extend(extend({}, options), overrides);
|
||||
};
|
||||
|
||||
extend = exports.extend = function(object, properties) {
|
||||
var key, val;
|
||||
for (key in properties) {
|
||||
@@ -41,6 +43,7 @@
|
||||
}
|
||||
return object;
|
||||
};
|
||||
|
||||
exports.flatten = flatten = function(array) {
|
||||
var element, flattened, _i, _len;
|
||||
flattened = [];
|
||||
@@ -54,13 +57,16 @@
|
||||
}
|
||||
return flattened;
|
||||
};
|
||||
|
||||
exports.del = function(obj, key) {
|
||||
var val;
|
||||
val = obj[key];
|
||||
delete obj[key];
|
||||
return val;
|
||||
};
|
||||
|
||||
exports.last = function(array, back) {
|
||||
return array[array.length - (back || 0) - 1];
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
@@ -1,8 +1,10 @@
|
||||
(function() {
|
||||
var key, val, _ref;
|
||||
|
||||
_ref = require('./coffee-script');
|
||||
for (key in _ref) {
|
||||
val = _ref[key];
|
||||
exports[key] = val;
|
||||
}
|
||||
|
||||
}).call(this);
|
||||
@@ -1,23 +1,19 @@
|
||||
(function() {
|
||||
var ASSIGNED, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, starts, _ref;
|
||||
var __indexOf = Array.prototype.indexOf || function(item) {
|
||||
for (var i = 0, l = this.length; i < l; i++) {
|
||||
if (this[i] === item) return i;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
Rewriter = require('./rewriter').Rewriter;
|
||||
_ref = require('./helpers'), count = _ref.count, starts = _ref.starts, compact = _ref.compact, last = _ref.last;
|
||||
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,
|
||||
__indexOf = Array.prototype.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;
|
||||
|
||||
exports.Lexer = Lexer = (function() {
|
||||
|
||||
function Lexer() {}
|
||||
|
||||
Lexer.prototype.tokenize = function(code, opts) {
|
||||
var i;
|
||||
if (opts == null) {
|
||||
opts = {};
|
||||
}
|
||||
if (WHITESPACE.test(code)) {
|
||||
code = "\n" + code;
|
||||
}
|
||||
var i, tag;
|
||||
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;
|
||||
@@ -25,32 +21,31 @@
|
||||
this.indebt = 0;
|
||||
this.outdebt = 0;
|
||||
this.indents = [];
|
||||
this.ends = [];
|
||||
this.tokens = [];
|
||||
i = 0;
|
||||
while (this.chunk = code.slice(i)) {
|
||||
i += this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.heredocToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken();
|
||||
}
|
||||
this.closeIndentation();
|
||||
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, _ref2, _ref3;
|
||||
if (!(match = IDENTIFIER.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
var colon, forcedIdentifier, id, input, match, prev, tag, _ref3, _ref4;
|
||||
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)) && (((_ref2 = prev[0]) === '.' || _ref2 === '?.' || _ref2 === '::') || !prev.spaced && prev[0] === '@');
|
||||
forcedIdentifier = colon || (prev = last(this.tokens)) && (((_ref3 = prev[0]) === '.' || _ref3 === '?.' || _ref3 === '::') || !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' && (_ref3 = this.tag(), __indexOf.call(LINE_BREAK, _ref3) >= 0)) {
|
||||
if (tag === 'WHEN' && (_ref4 = this.tag(), __indexOf.call(LINE_BREAK, _ref4) >= 0)) {
|
||||
tag = 'LEADING_WHEN';
|
||||
} else if (tag === 'FOR') {
|
||||
this.seenFor = true;
|
||||
@@ -71,19 +66,17 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
if (__indexOf.call(JS_FORBIDDEN, id) >= 0) {
|
||||
if (__indexOf.call(['eval', 'arguments'].concat(JS_FORBIDDEN), id) >= 0) {
|
||||
if (forcedIdentifier) {
|
||||
tag = 'IDENTIFIER';
|
||||
id = new String(id);
|
||||
id.reserved = true;
|
||||
} else if (__indexOf.call(RESERVED, id) >= 0) {
|
||||
this.identifierError(id);
|
||||
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 '!':
|
||||
@@ -101,7 +94,6 @@
|
||||
return 'BOOL';
|
||||
case 'break':
|
||||
case 'continue':
|
||||
case 'debugger':
|
||||
return 'STATEMENT';
|
||||
default:
|
||||
return tag;
|
||||
@@ -109,33 +101,31 @@
|
||||
})();
|
||||
}
|
||||
this.token(tag, id);
|
||||
if (colon) {
|
||||
this.token(':', ':');
|
||||
}
|
||||
if (colon) this.token(':', ':');
|
||||
return input.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.numberToken = function() {
|
||||
var match, number;
|
||||
if (!(match = NUMBER.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
var binaryLiteral, lexedLength, match, number;
|
||||
if (!(match = NUMBER.exec(this.chunk))) return 0;
|
||||
number = match[0];
|
||||
lexedLength = number.length;
|
||||
if (binaryLiteral = /0b([01]+)/.exec(number)) {
|
||||
number = (parseInt(binaryLiteral[1], 2)).toString();
|
||||
}
|
||||
this.token('NUMBER', number);
|
||||
return number.length;
|
||||
return lexedLength;
|
||||
};
|
||||
|
||||
Lexer.prototype.stringToken = function() {
|
||||
var match, 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 {
|
||||
@@ -148,11 +138,10 @@
|
||||
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], {
|
||||
@@ -169,11 +158,10 @@
|
||||
this.line += count(heredoc, '\n');
|
||||
return heredoc.length;
|
||||
};
|
||||
|
||||
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, {
|
||||
@@ -185,6 +173,7 @@
|
||||
this.line += count(comment, '\n');
|
||||
return comment.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.jsToken = function() {
|
||||
var match, script;
|
||||
if (!(this.chunk.charAt(0) === '`' && (match = JSTOKEN.exec(this.chunk)))) {
|
||||
@@ -193,72 +182,73 @@
|
||||
this.token('JS', (script = match[0]).slice(1, -1));
|
||||
return script.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.regexToken = function() {
|
||||
var length, match, prev, regex, _ref2;
|
||||
if (this.chunk.charAt(0) !== '/') {
|
||||
return 0;
|
||||
}
|
||||
var flags, length, match, prev, regex, _ref3, _ref4;
|
||||
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 && (_ref2 = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref2) >= 0)) {
|
||||
if (prev && (_ref3 = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref3) >= 0)) {
|
||||
return 0;
|
||||
}
|
||||
if (!(match = REGEX.exec(this.chunk))) {
|
||||
return 0;
|
||||
if (!(match = REGEX.exec(this.chunk))) return 0;
|
||||
_ref4 = match, match = _ref4[0], regex = _ref4[1], flags = _ref4[2];
|
||||
if (regex.slice(0, 2) === '/*') {
|
||||
this.error('regular expressions cannot begin with `*`');
|
||||
}
|
||||
regex = match[0];
|
||||
this.token('REGEX', regex === '//' ? '/(?:)/' : regex);
|
||||
return regex.length;
|
||||
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, _ref2, _ref3, _ref4, _ref5;
|
||||
var body, flags, heregex, re, tag, tokens, value, _i, _len, _ref3, _ref4, _ref5, _ref6;
|
||||
heregex = match[0], body = match[1], flags = match[2];
|
||||
if (0 > body.indexOf('#{')) {
|
||||
re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/');
|
||||
if (re.match(/^\*/)) {
|
||||
this.error('regular expressions cannot begin with `*`');
|
||||
}
|
||||
this.token('REGEX', "/" + (re || '(?:)') + "/" + flags);
|
||||
return heregex.length;
|
||||
}
|
||||
this.token('IDENTIFIER', 'RegExp');
|
||||
this.tokens.push(['CALL_START', '(']);
|
||||
tokens = [];
|
||||
_ref2 = this.interpolateString(body, {
|
||||
_ref3 = this.interpolateString(body, {
|
||||
regex: true
|
||||
});
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
_ref3 = _ref2[_i], tag = _ref3[0], value = _ref3[1];
|
||||
for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
|
||||
_ref4 = _ref3[_i], tag = _ref4[0], value = _ref4[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 (((_ref4 = tokens[0]) != null ? _ref4[0] : void 0) !== 'STRING') {
|
||||
if (((_ref5 = tokens[0]) != null ? _ref5[0] : void 0) !== 'STRING') {
|
||||
this.tokens.push(['STRING', '""'], ['+', '+']);
|
||||
}
|
||||
(_ref5 = this.tokens).push.apply(_ref5, tokens);
|
||||
if (flags) {
|
||||
this.tokens.push([',', ','], ['STRING', '"' + flags + '"']);
|
||||
}
|
||||
(_ref6 = this.tokens).push.apply(_ref6, 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;
|
||||
}
|
||||
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();
|
||||
@@ -279,6 +269,7 @@
|
||||
diff = size - this.indent + this.outdebt;
|
||||
this.token('INDENT', diff);
|
||||
this.indents.push(diff);
|
||||
this.ends.push('OUTDENT');
|
||||
this.outdebt = this.indebt = 0;
|
||||
} else {
|
||||
this.indebt = 0;
|
||||
@@ -287,7 +278,8 @@
|
||||
this.indent = size;
|
||||
return indent.length;
|
||||
};
|
||||
Lexer.prototype.outdentToken = function(moveOut, noNewlines, close) {
|
||||
|
||||
Lexer.prototype.outdentToken = function(moveOut, noNewlines) {
|
||||
var dent, len;
|
||||
while (moveOut > 0) {
|
||||
len = this.indents.length - 1;
|
||||
@@ -303,67 +295,69 @@
|
||||
dent = this.indents.pop() - this.outdebt;
|
||||
moveOut -= dent;
|
||||
this.outdebt = 0;
|
||||
this.pair('OUTDENT');
|
||||
this.token('OUTDENT', dent);
|
||||
}
|
||||
}
|
||||
if (dent) {
|
||||
this.outdebt -= moveOut;
|
||||
if (dent) this.outdebt -= moveOut;
|
||||
while (this.value() === ';') {
|
||||
this.tokens.pop();
|
||||
}
|
||||
if (!(this.tag() === 'TERMINATOR' || noNewlines)) {
|
||||
this.token('TERMINATOR', '\n');
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
Lexer.prototype.whitespaceToken = function() {
|
||||
var match, nline, prev;
|
||||
if (!((match = WHITESPACE.exec(this.chunk)) || (nline = this.chunk.charAt(0) === '\n'))) {
|
||||
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 {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
Lexer.prototype.newlineToken = function() {
|
||||
if (this.tag() !== 'TERMINATOR') {
|
||||
this.token('TERMINATOR', '\n');
|
||||
}
|
||||
return this;
|
||||
};
|
||||
Lexer.prototype.suppressNewlines = function() {
|
||||
if (this.value() === '\\') {
|
||||
while (this.value() === ';') {
|
||||
this.tokens.pop();
|
||||
}
|
||||
if (this.tag() !== 'TERMINATOR') this.token('TERMINATOR', '\n');
|
||||
return this;
|
||||
};
|
||||
|
||||
Lexer.prototype.suppressNewlines = function() {
|
||||
if (this.value() === '\\') this.tokens.pop();
|
||||
return this;
|
||||
};
|
||||
|
||||
Lexer.prototype.literalToken = function() {
|
||||
var match, prev, tag, value, _ref2, _ref3, _ref4, _ref5;
|
||||
var match, prev, tag, value, _ref3, _ref4, _ref5, _ref6;
|
||||
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 && (_ref2 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref2) >= 0)) {
|
||||
this.assignmentError();
|
||||
if (!prev[1].reserved && (_ref3 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref3) >= 0)) {
|
||||
this.error("reserved word \"" + (this.value()) + "\" can't be assigned");
|
||||
}
|
||||
if ((_ref3 = prev[1]) === '||' || _ref3 === '&&') {
|
||||
if ((_ref4 = prev[1]) === '||' || _ref4 === '&&') {
|
||||
prev[0] = 'COMPOUND_ASSIGN';
|
||||
prev[1] += '=';
|
||||
return value.length;
|
||||
}
|
||||
}
|
||||
if (value === ';') {
|
||||
this.seenFor = false;
|
||||
tag = 'TERMINATOR';
|
||||
} else if (__indexOf.call(MATH, value) >= 0) {
|
||||
tag = 'MATH';
|
||||
@@ -378,56 +372,56 @@
|
||||
} else if (__indexOf.call(LOGIC, value) >= 0 || value === '?' && (prev != null ? prev.spaced : void 0)) {
|
||||
tag = 'LOGIC';
|
||||
} else if (prev && !prev.spaced) {
|
||||
if (value === '(' && (_ref4 = prev[0], __indexOf.call(CALLABLE, _ref4) >= 0)) {
|
||||
if (prev[0] === '?') {
|
||||
prev[0] = 'FUNC_EXIST';
|
||||
}
|
||||
if (value === '(' && (_ref5 = prev[0], __indexOf.call(CALLABLE, _ref5) >= 0)) {
|
||||
if (prev[0] === '?') prev[0] = 'FUNC_EXIST';
|
||||
tag = 'CALL_START';
|
||||
} else if (value === '[' && (_ref5 = prev[0], __indexOf.call(INDEXABLE, _ref5) >= 0)) {
|
||||
} else if (value === '[' && (_ref6 = prev[0], __indexOf.call(INDEXABLE, _ref6) >= 0)) {
|
||||
tag = 'INDEX_START';
|
||||
switch (prev[0]) {
|
||||
case '?':
|
||||
prev[0] = 'INDEX_SOAK';
|
||||
break;
|
||||
case '::':
|
||||
prev[0] = 'INDEX_PROTO';
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (value) {
|
||||
case '(':
|
||||
case '{':
|
||||
case '[':
|
||||
this.ends.push(INVERSES[value]);
|
||||
break;
|
||||
case ')':
|
||||
case '}':
|
||||
case ']':
|
||||
this.pair(value);
|
||||
}
|
||||
this.token(tag, value);
|
||||
return value.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.sanitizeHeredoc = function(doc, options) {
|
||||
var attempt, herecomment, indent, match, _ref2;
|
||||
var attempt, herecomment, indent, match, _ref3;
|
||||
indent = options.indent, herecomment = options.herecomment;
|
||||
if (herecomment) {
|
||||
if (HEREDOC_ILLEGAL.test(doc)) {
|
||||
throw new Error("block comment cannot contain \"*/\", starting on line " + (this.line + 1));
|
||||
}
|
||||
if (doc.indexOf('\n') <= 0) {
|
||||
return doc;
|
||||
this.error("block comment cannot contain \"*/\", starting");
|
||||
}
|
||||
if (doc.indexOf('\n') <= 0) return doc;
|
||||
} else {
|
||||
while (match = HEREDOC_INDENT.exec(doc)) {
|
||||
attempt = match[1];
|
||||
if (indent === null || (0 < (_ref2 = attempt.length) && _ref2 < indent.length)) {
|
||||
if (indent === null || (0 < (_ref3 = attempt.length) && _ref3 < 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;
|
||||
@@ -451,28 +445,22 @@
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
Lexer.prototype.closeIndentation = function() {
|
||||
return this.outdentToken(this.indent);
|
||||
};
|
||||
Lexer.prototype.identifierError = function(word) {
|
||||
throw SyntaxError("Reserved word \"" + word + "\" on line " + (this.line + 1));
|
||||
};
|
||||
Lexer.prototype.assignmentError = function() {
|
||||
throw SyntaxError("Reserved word \"" + (this.value()) + "\" on line " + (this.line + 1) + " can't be assigned");
|
||||
};
|
||||
|
||||
Lexer.prototype.balancedString = function(str, end) {
|
||||
var i, letter, match, prev, stack, _ref2;
|
||||
var i, letter, match, prev, stack, _ref3;
|
||||
stack = [end];
|
||||
for (i = 1, _ref2 = str.length; 1 <= _ref2 ? i < _ref2 : i > _ref2; 1 <= _ref2 ? i++ : i--) {
|
||||
for (i = 1, _ref3 = str.length; 1 <= _ref3 ? i < _ref3 : i > _ref3; 1 <= _ref3 ? i++ : i--) {
|
||||
switch (letter = str.charAt(i)) {
|
||||
case '\\':
|
||||
i++;
|
||||
continue;
|
||||
case end:
|
||||
stack.pop();
|
||||
if (!stack.length) {
|
||||
return str.slice(0, i + 1);
|
||||
}
|
||||
if (!stack.length) return str.slice(0, i + 1);
|
||||
end = stack[stack.length - 1];
|
||||
continue;
|
||||
}
|
||||
@@ -487,13 +475,12 @@
|
||||
}
|
||||
prev = letter;
|
||||
}
|
||||
throw new Error("missing " + (stack.pop()) + ", starting on line " + (this.line + 1));
|
||||
return this.error("missing " + (stack.pop()) + ", starting");
|
||||
};
|
||||
|
||||
Lexer.prototype.interpolateString = function(str, options) {
|
||||
var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _len, _ref2, _ref3, _ref4;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _len, _ref3, _ref4, _ref5;
|
||||
if (options == null) options = {};
|
||||
heredoc = options.heredoc, regex = options.regex;
|
||||
tokens = [];
|
||||
pi = 0;
|
||||
@@ -506,9 +493,7 @@
|
||||
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, {
|
||||
@@ -516,13 +501,13 @@
|
||||
rewrite: false
|
||||
});
|
||||
nested.pop();
|
||||
if (((_ref2 = nested[0]) != null ? _ref2[0] : void 0) === 'TERMINATOR') {
|
||||
if (((_ref3 = nested[0]) != null ? _ref3[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]);
|
||||
}
|
||||
@@ -530,59 +515,60 @@
|
||||
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('(', '(');
|
||||
}
|
||||
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++) {
|
||||
_ref3 = tokens[i], tag = _ref3[0], value = _ref3[1];
|
||||
if (i) {
|
||||
this.token('+', '+');
|
||||
}
|
||||
_ref4 = tokens[i], tag = _ref4[0], value = _ref4[1];
|
||||
if (i) this.token('+', '+');
|
||||
if (tag === 'TOKENS') {
|
||||
(_ref4 = this.tokens).push.apply(_ref4, value);
|
||||
(_ref5 = this.tokens).push.apply(_ref5, 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);
|
||||
this.indent -= size = last(this.indents);
|
||||
this.outdentToken(size, true);
|
||||
return this.pair(tag);
|
||||
}
|
||||
return this.ends.pop();
|
||||
};
|
||||
|
||||
Lexer.prototype.token = function(tag, value) {
|
||||
return this.tokens.push([tag, value, this.line]);
|
||||
};
|
||||
|
||||
Lexer.prototype.tag = function(index, tag) {
|
||||
var tok;
|
||||
return (tok = last(this.tokens, index)) && (tag ? tok[0] = tag : tok[0]);
|
||||
};
|
||||
|
||||
Lexer.prototype.value = function(index, val) {
|
||||
var tok;
|
||||
return (tok = last(this.tokens, index)) && (val ? tok[1] = val : tok[1]);
|
||||
};
|
||||
|
||||
Lexer.prototype.unfinished = function() {
|
||||
var prev, value;
|
||||
return LINE_CONTINUER.test(this.chunk) || (prev = last(this.tokens, 1)) && prev[0] !== '.' && (value = this.value()) && !value.reserved && NO_NEWLINE.test(value) && !CODE.test(value) && !ASSIGNED.test(this.chunk);
|
||||
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');
|
||||
};
|
||||
|
||||
Lexer.prototype.escapeLines = function(str, heredoc) {
|
||||
return str.replace(MULTILINER, heredoc ? '\\n' : '');
|
||||
};
|
||||
|
||||
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;
|
||||
@@ -593,10 +579,19 @@
|
||||
body = body.replace(RegExp("" + quote, "g"), '\\$&');
|
||||
return quote + this.escapeLines(body, heredoc) + quote;
|
||||
};
|
||||
|
||||
Lexer.prototype.error = function(message) {
|
||||
throw SyntaxError("" + message + " on line " + (this.line + 1));
|
||||
};
|
||||
|
||||
return Lexer;
|
||||
|
||||
})();
|
||||
|
||||
JS_KEYWORDS = ['true', 'false', 'null', 'this', 'new', 'delete', 'typeof', 'in', 'instanceof', 'return', 'throw', 'break', 'continue', 'debugger', 'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally', 'class', 'extends', 'super'];
|
||||
|
||||
COFFEE_KEYWORDS = ['undefined', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when'];
|
||||
|
||||
COFFEE_ALIAS_MAP = {
|
||||
and: '&&',
|
||||
or: '||',
|
||||
@@ -608,6 +603,7 @@
|
||||
on: 'true',
|
||||
off: 'false'
|
||||
};
|
||||
|
||||
COFFEE_ALIASES = (function() {
|
||||
var _results;
|
||||
_results = [];
|
||||
@@ -616,41 +612,75 @@
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
|
||||
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'];
|
||||
|
||||
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED);
|
||||
|
||||
exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS);
|
||||
|
||||
IDENTIFIER = /^([$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)([^\n\S]*:(?!:))?/;
|
||||
NUMBER = /^0x[\da-f]+|^\d*\.?\d+(?:e[+-]?\d+)?/i;
|
||||
|
||||
NUMBER = /^0x[\da-f]+|^0b[01]+|^\d*\.?\d+(?:e[+-]?\d+)?/i;
|
||||
|
||||
HEREDOC = /^("""|''')([\s\S]*?)(?:\n[^\n\S]*)?\1/;
|
||||
|
||||
OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/;
|
||||
|
||||
WHITESPACE = /^[^\n\S]+/;
|
||||
|
||||
COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)?$)|^(?:\s*#(?!##[^#]).*)+/;
|
||||
|
||||
CODE = /^[-=]>/;
|
||||
|
||||
MULTI_DENT = /^(?:\n[^\n\S]*)+/;
|
||||
|
||||
SIMPLESTR = /^'[^\\']*(?:\\.[^\\']*)*'/;
|
||||
|
||||
JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/;
|
||||
REGEX = /^\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/[imgy]{0,4}(?!\w)/;
|
||||
|
||||
REGEX = /^(\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/)([imgy]{0,4})(?!\w)/;
|
||||
|
||||
HEREGEX = /^\/{3}([\s\S]+?)\/{3}([imgy]{0,4})(?!\w)/;
|
||||
|
||||
HEREGEX_OMIT = /\s+(?:#.*)?/g;
|
||||
|
||||
MULTILINER = /\n/g;
|
||||
|
||||
HEREDOC_INDENT = /\n+([^\n\S]*)/g;
|
||||
|
||||
HEREDOC_ILLEGAL = /\*\//;
|
||||
ASSIGNED = /^\s*@?([$A-Za-z_][$\w\x7f-\uffff]*|['"].*['"])[^\n\S]*?[:=][^:=>]/;
|
||||
|
||||
LINE_CONTINUER = /^\s*(?:,|\??\.(?![.\d])|::)/;
|
||||
|
||||
TRAILING_SPACES = /\s+$/;
|
||||
NO_NEWLINE = /^(?:[-+*&|\/%=<>!.\\][<>=&|]*|and|or|is(?:nt)?|n(?:ot|ew)|delete|typeof|instanceof)$/;
|
||||
|
||||
COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|='];
|
||||
|
||||
UNARY = ['!', '~', 'NEW', 'TYPEOF', 'DELETE', 'DO'];
|
||||
|
||||
LOGIC = ['&&', '||', '&', '|', '^'];
|
||||
|
||||
SHIFT = ['<<', '>>', '>>>'];
|
||||
|
||||
COMPARE = ['==', '!=', '<', '>', '<=', '>='];
|
||||
|
||||
MATH = ['*', '/', '%'];
|
||||
|
||||
RELATION = ['IN', 'OF', 'INSTANCEOF'];
|
||||
|
||||
BOOL = ['TRUE', 'FALSE', 'NULL', 'UNDEFINED'];
|
||||
|
||||
NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', '++', '--', ']'];
|
||||
|
||||
NOT_SPACED_REGEX = NOT_REGEX.concat(')', '}', 'THIS', 'IDENTIFIER', 'STRING');
|
||||
|
||||
CALLABLE = ['IDENTIFIER', 'STRING', 'REGEX', ')', ']', '}', '?', '::', '@', 'THIS', 'SUPER'];
|
||||
|
||||
INDEXABLE = CALLABLE.concat('NUMBER', 'BOOL');
|
||||
|
||||
LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'];
|
||||
|
||||
}).call(this);
|
||||
File diff suppressed because it is too large
Load Diff
35
lib/optparse.js → lib/coffee-script/optparse.js
Executable file → Normal file
35
lib/optparse.js → lib/coffee-script/optparse.js
Executable file → Normal file
@@ -1,21 +1,27 @@
|
||||
(function() {
|
||||
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments;
|
||||
|
||||
exports.OptionParser = OptionParser = (function() {
|
||||
|
||||
function OptionParser(rules, banner) {
|
||||
this.banner = banner;
|
||||
this.rules = buildRules(rules);
|
||||
}
|
||||
|
||||
OptionParser.prototype.parse = function(args) {
|
||||
var arg, i, isOption, matchedRule, options, rule, value, _i, _len, _len2, _ref;
|
||||
var arg, i, isOption, matchedRule, options, originalArgs, pos, rule, value, _i, _len, _len2, _ref;
|
||||
options = {
|
||||
arguments: [],
|
||||
literals: []
|
||||
};
|
||||
originalArgs = args;
|
||||
args = normalizeArguments(args);
|
||||
for (i = 0, _len = args.length; i < _len; i++) {
|
||||
arg = args[i];
|
||||
if (arg === '--') {
|
||||
options.literals = args.slice(i + 1);
|
||||
pos = originalArgs.indexOf('--');
|
||||
options.arguments = [originalArgs[1 + pos]];
|
||||
options.literals = originalArgs.slice(2 + pos);
|
||||
break;
|
||||
}
|
||||
isOption = !!(arg.match(LONG_FLAG) || arg.match(SHORT_FLAG));
|
||||
@@ -34,18 +40,17 @@
|
||||
throw new Error("unrecognized option: " + arg);
|
||||
}
|
||||
if (!isOption) {
|
||||
options.arguments = args.slice(i);
|
||||
options.arguments = originalArgs.slice(originalArgs.indexOf(arg));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return options;
|
||||
};
|
||||
|
||||
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];
|
||||
@@ -56,29 +61,33 @@
|
||||
}
|
||||
return "\n" + (lines.join('\n')) + "\n";
|
||||
};
|
||||
|
||||
return OptionParser;
|
||||
|
||||
})();
|
||||
|
||||
LONG_FLAG = /^(--\w[\w\-]+)/;
|
||||
|
||||
SHORT_FLAG = /^(-\w)/;
|
||||
|
||||
MULTI_FLAG = /^-(\w{2,})/;
|
||||
|
||||
OPTIONAL = /\[(\w+(\*?))\]/;
|
||||
|
||||
buildRules = function(rules) {
|
||||
var tuple, _i, _len, _results;
|
||||
_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;
|
||||
};
|
||||
|
||||
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 {
|
||||
@@ -90,6 +99,7 @@
|
||||
isList: !!(match && match[2])
|
||||
};
|
||||
};
|
||||
|
||||
normalizeArguments = function(args) {
|
||||
var arg, l, match, result, _i, _j, _len, _len2, _ref;
|
||||
args = args.slice(0);
|
||||
@@ -108,4 +118,5 @@
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
674
lib/coffee-script/parser.js
Executable file
674
lib/coffee-script/parser.js
Executable file
File diff suppressed because one or more lines are too long
@@ -1,29 +1,36 @@
|
||||
(function() {
|
||||
var ACCESSOR, CoffeeScript, Module, REPL_PROMPT, REPL_PROMPT_CONTINUATION, SIMPLEVAR, Script, autocomplete, backlog, completeAttribute, completeVariable, enableColours, error, g, getCompletions, inspect, nonContextGlobals, readline, repl, run, sandbox, stdin, stdout, _i, _len;
|
||||
var ACCESSOR, CoffeeScript, Module, REPL_PROMPT, REPL_PROMPT_CONTINUATION, SIMPLEVAR, Script, autocomplete, backlog, completeAttribute, completeVariable, enableColours, error, getCompletions, inspect, readline, repl, run, stdin, stdout;
|
||||
|
||||
CoffeeScript = require('./coffee-script');
|
||||
|
||||
readline = require('readline');
|
||||
|
||||
inspect = require('util').inspect;
|
||||
|
||||
Script = require('vm').Script;
|
||||
|
||||
Module = require('module');
|
||||
|
||||
REPL_PROMPT = 'coffee> ';
|
||||
|
||||
REPL_PROMPT_CONTINUATION = '......> ';
|
||||
|
||||
enableColours = false;
|
||||
|
||||
if (process.platform !== 'win32') {
|
||||
enableColours = !process.env.NODE_DISABLE_COLORS;
|
||||
}
|
||||
|
||||
stdin = process.openStdin();
|
||||
|
||||
stdout = process.stdout;
|
||||
|
||||
error = function(err) {
|
||||
return stdout.write((err.stack || err.toString()) + '\n\n');
|
||||
return stdout.write((err.stack || err.toString()) + '\n');
|
||||
};
|
||||
|
||||
backlog = '';
|
||||
sandbox = Script.createContext();
|
||||
nonContextGlobals = ['Buffer', 'console', 'process', 'setInterval', 'clearInterval', 'setTimeout', 'clearTimeout'];
|
||||
for (_i = 0, _len = nonContextGlobals.length; _i < _len; _i++) {
|
||||
g = nonContextGlobals[_i];
|
||||
sandbox[g] = global[g];
|
||||
}
|
||||
sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox;
|
||||
|
||||
run = function(buffer) {
|
||||
var code, returnValue, _;
|
||||
if (!buffer.toString().trim() && !backlog) {
|
||||
@@ -40,33 +47,33 @@
|
||||
repl.setPrompt(REPL_PROMPT);
|
||||
backlog = '';
|
||||
try {
|
||||
_ = sandbox._;
|
||||
_ = global._;
|
||||
returnValue = CoffeeScript.eval("_=(" + code + "\n)", {
|
||||
sandbox: sandbox,
|
||||
filename: 'repl',
|
||||
modulename: 'repl'
|
||||
});
|
||||
if (returnValue === void 0) {
|
||||
sandbox._ = _;
|
||||
} else {
|
||||
process.stdout.write(inspect(returnValue, false, 2, enableColours) + '\n');
|
||||
}
|
||||
if (returnValue === void 0) global._ = _;
|
||||
process.stdout.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.runInContext(obj, sandbox);
|
||||
val = Script.runInThisContext(obj);
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
@@ -74,27 +81,40 @@
|
||||
return [completions, prefix];
|
||||
}
|
||||
};
|
||||
|
||||
completeVariable = function(text) {
|
||||
var completions, free, possibilities, vars, _ref;
|
||||
if (free = (_ref = text.match(SIMPLEVAR)) != null ? _ref[1] : void 0) {
|
||||
vars = Script.runInContext('Object.getOwnPropertyNames(this)', sandbox);
|
||||
possibilities = vars.concat(CoffeeScript.RESERVED);
|
||||
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);
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
possibilities = vars.concat(keywords);
|
||||
completions = getCompletions(free, possibilities);
|
||||
return [completions, free];
|
||||
}
|
||||
};
|
||||
|
||||
getCompletions = function(prefix, candidates) {
|
||||
var el, _j, _len2, _results;
|
||||
var el, _i, _len, _results;
|
||||
_results = [];
|
||||
for (_j = 0, _len2 = candidates.length; _j < _len2; _j++) {
|
||||
el = candidates[_j];
|
||||
if (el.indexOf(prefix) === 0) {
|
||||
_results.push(el);
|
||||
}
|
||||
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) {
|
||||
@@ -103,6 +123,7 @@
|
||||
} else {
|
||||
repl = readline.createInterface(stdin, stdout, autocomplete);
|
||||
}
|
||||
|
||||
repl.on('attemptClose', function() {
|
||||
if (backlog) {
|
||||
backlog = '';
|
||||
@@ -113,11 +134,16 @@
|
||||
return repl.close();
|
||||
}
|
||||
});
|
||||
|
||||
repl.on('close', function() {
|
||||
process.stdout.write('\n');
|
||||
return stdin.destroy();
|
||||
});
|
||||
|
||||
repl.on('line', run);
|
||||
|
||||
repl.setPrompt(REPL_PROMPT);
|
||||
|
||||
repl.prompt();
|
||||
|
||||
}).call(this);
|
||||
@@ -1,13 +1,12 @@
|
||||
(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 __indexOf = Array.prototype.indexOf || function(item) {
|
||||
for (var i = 0, l = this.length; i < l; i++) {
|
||||
if (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 = Array.prototype.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 = Array.prototype.slice;
|
||||
|
||||
exports.Rewriter = (function() {
|
||||
|
||||
function Rewriter() {}
|
||||
|
||||
Rewriter.prototype.rewrite = function(tokens) {
|
||||
this.tokens = tokens;
|
||||
this.removeLeadingNewlines();
|
||||
@@ -18,10 +17,9 @@
|
||||
this.tagPostfixConditionals();
|
||||
this.addImplicitBraces();
|
||||
this.addImplicitParentheses();
|
||||
this.ensureBalance(BALANCED_PAIRS);
|
||||
this.rewriteClosingParens();
|
||||
return this.tokens;
|
||||
};
|
||||
|
||||
Rewriter.prototype.scanTokens = function(block) {
|
||||
var i, token, tokens;
|
||||
tokens = this.tokens;
|
||||
@@ -31,6 +29,7 @@
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
Rewriter.prototype.detectEnd = function(i, condition, action) {
|
||||
var levels, token, tokens, _ref, _ref2;
|
||||
tokens = this.tokens;
|
||||
@@ -39,9 +38,7 @@
|
||||
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) {
|
||||
@@ -51,19 +48,17 @@
|
||||
}
|
||||
return i - 1;
|
||||
};
|
||||
|
||||
Rewriter.prototype.removeLeadingNewlines = function() {
|
||||
var i, tag, _len, _ref;
|
||||
_ref = this.tokens;
|
||||
for (i = 0, _len = _ref.length; i < _len; i++) {
|
||||
tag = _ref[i][0];
|
||||
if (tag !== 'TERMINATOR') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i) {
|
||||
return this.tokens.splice(0, i);
|
||||
if (tag !== 'TERMINATOR') break;
|
||||
}
|
||||
if (i) return this.tokens.splice(0, i);
|
||||
};
|
||||
|
||||
Rewriter.prototype.removeMidExpressionNewlines = function() {
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var _ref;
|
||||
@@ -74,6 +69,7 @@
|
||||
return 0;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.closeOpenCalls = function() {
|
||||
var action, condition;
|
||||
condition = function(token, i) {
|
||||
@@ -84,12 +80,11 @@
|
||||
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;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.closeOpenIndexes = function() {
|
||||
var action, condition;
|
||||
condition = function(token, i) {
|
||||
@@ -100,25 +95,25 @@
|
||||
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, startsLine;
|
||||
stack = [];
|
||||
start = null;
|
||||
startsLine = null;
|
||||
sameLine = true;
|
||||
startIndent = 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;
|
||||
}
|
||||
_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)) && ((!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 && ((_ref2 = one[0]) !== 'IDENTIFIER' && _ref2 !== 'NUMBER' && _ref2 !== 'STRING' && _ref2 !== '@' && _ref2 !== 'TERMINATOR' && _ref2 !== 'OUTDENT'));
|
||||
};
|
||||
action = function(token, i) {
|
||||
var tok;
|
||||
@@ -127,7 +122,7 @@
|
||||
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, _ref2;
|
||||
if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) {
|
||||
stack.push([(tag === 'INDENT' && this.tag(i - 1) === '{' ? '{' : tag), i]);
|
||||
return 1;
|
||||
@@ -139,11 +134,14 @@
|
||||
if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref2 = stack[stack.length - 1]) != null ? _ref2[0] : void 0) !== '{'))) {
|
||||
return 1;
|
||||
}
|
||||
sameLine = true;
|
||||
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]];
|
||||
@@ -153,63 +151,61 @@
|
||||
return 2;
|
||||
});
|
||||
};
|
||||
|
||||
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, _ref2;
|
||||
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') && (_ref2 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref2) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
|
||||
};
|
||||
action = function(token, i) {
|
||||
var idx;
|
||||
idx = token[0] === 'OUTDENT' ? i + 1 : i;
|
||||
return this.tokens.splice(idx, 0, ['CALL_END', ')', token[2]]);
|
||||
return this.tokens.splice(i, 0, ['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, _ref2, _ref3;
|
||||
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];
|
||||
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);
|
||||
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 (__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))) {
|
||||
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';
|
||||
}
|
||||
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, _ref2;
|
||||
tag = token[0];
|
||||
if (tag === 'TERMINATOR' && this.tag(i + 1) === 'THEN') {
|
||||
tokens.splice(i, 1);
|
||||
@@ -226,138 +222,80 @@
|
||||
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;
|
||||
}
|
||||
if (starter === 'THEN') indent.fromThen = true;
|
||||
indent.generated = outdent.generated = 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;
|
||||
});
|
||||
};
|
||||
|
||||
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];
|
||||
}
|
||||
});
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
Rewriter.prototype.ensureBalance = function(pairs) {
|
||||
var close, level, levels, open, openLine, tag, token, _i, _j, _len, _len2, _ref, _ref2;
|
||||
levels = {};
|
||||
openLine = {};
|
||||
_ref = this.tokens;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
token = _ref[_i];
|
||||
tag = token[0];
|
||||
for (_j = 0, _len2 = pairs.length; _j < _len2; _j++) {
|
||||
_ref2 = pairs[_j], open = _ref2[0], close = _ref2[1];
|
||||
levels[open] |= 0;
|
||||
if (tag === open) {
|
||||
if (levels[open]++ === 0) {
|
||||
openLine[open] = token[2];
|
||||
}
|
||||
} else if (tag === close && --levels[open] < 0) {
|
||||
throw Error("too many " + token[1] + " on line " + (token[2] + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (open in levels) {
|
||||
level = levels[open];
|
||||
if (level > 0) {
|
||||
throw Error("unclosed " + open + " on line " + (openLine[open] + 1));
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
Rewriter.prototype.rewriteClosingParens = function() {
|
||||
var debt, key, stack;
|
||||
stack = [];
|
||||
debt = {};
|
||||
for (key in INVERSES) {
|
||||
debt[key] = 0;
|
||||
}
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var inv, match, mtag, oppos, tag, val, _ref;
|
||||
if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) {
|
||||
stack.push(token);
|
||||
return 1;
|
||||
}
|
||||
if (__indexOf.call(EXPRESSION_END, tag) < 0) {
|
||||
return 1;
|
||||
}
|
||||
if (debt[inv = INVERSES[tag]] > 0) {
|
||||
debt[inv] -= 1;
|
||||
tokens.splice(i, 1);
|
||||
return 0;
|
||||
}
|
||||
match = stack.pop();
|
||||
mtag = match[0];
|
||||
oppos = INVERSES[mtag];
|
||||
if (tag === oppos) {
|
||||
return 1;
|
||||
}
|
||||
debt[mtag] += 1;
|
||||
val = [oppos, mtag === 'INDENT' ? match[1] : oppos];
|
||||
if (this.tag(i + 2) === mtag) {
|
||||
tokens.splice(i + 3, 0, val);
|
||||
stack.push(match);
|
||||
} else {
|
||||
tokens.splice(i, 0, val);
|
||||
}
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.indentation = function(token) {
|
||||
return [['INDENT', 2, token[2]], ['OUTDENT', 2, token[2]]];
|
||||
};
|
||||
|
||||
Rewriter.prototype.tag = function(i) {
|
||||
var _ref;
|
||||
return (_ref = this.tokens[i]) != null ? _ref[0] : void 0;
|
||||
};
|
||||
|
||||
return Rewriter;
|
||||
|
||||
})();
|
||||
|
||||
BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END']];
|
||||
INVERSES = {};
|
||||
|
||||
exports.INVERSES = INVERSES = {};
|
||||
|
||||
EXPRESSION_START = [];
|
||||
|
||||
EXPRESSION_END = [];
|
||||
|
||||
for (_i = 0, _len = BALANCED_PAIRS.length; _i < _len; _i++) {
|
||||
_ref = BALANCED_PAIRS[_i], left = _ref[0], rite = _ref[1];
|
||||
EXPRESSION_START.push(INVERSES[rite] = left);
|
||||
EXPRESSION_END.push(INVERSES[left] = rite);
|
||||
}
|
||||
|
||||
EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);
|
||||
|
||||
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_UNSPACED_CALL = ['+', '-'];
|
||||
|
||||
IMPLICIT_BLOCK = ['->', '=>', '{', '[', ','];
|
||||
|
||||
IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR'];
|
||||
|
||||
SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN'];
|
||||
|
||||
SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN'];
|
||||
|
||||
LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT'];
|
||||
|
||||
}).call(this);
|
||||
@@ -1,8 +1,12 @@
|
||||
(function() {
|
||||
var Scope, extend, last, _ref;
|
||||
|
||||
_ref = require('./helpers'), extend = _ref.extend, last = _ref.last;
|
||||
|
||||
exports.Scope = Scope = (function() {
|
||||
|
||||
Scope.root = null;
|
||||
|
||||
function Scope(parent, expressions, method) {
|
||||
this.parent = parent;
|
||||
this.expressions = expressions;
|
||||
@@ -14,17 +18,13 @@
|
||||
}
|
||||
];
|
||||
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,
|
||||
@@ -32,27 +32,25 @@
|
||||
}) - 1;
|
||||
}
|
||||
};
|
||||
|
||||
Scope.prototype.find = function(name, options) {
|
||||
if (this.check(name, options)) {
|
||||
return true;
|
||||
}
|
||||
if (this.check(name, options)) 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;
|
||||
}
|
||||
if (found || immediate) return found;
|
||||
return !!((_ref2 = this.parent) != null ? _ref2.check(name) : void 0);
|
||||
};
|
||||
|
||||
Scope.prototype.temporary = function(name, index) {
|
||||
if (name.length > 1) {
|
||||
return '_' + name + (index > 1 ? index : '');
|
||||
@@ -60,36 +58,40 @@
|
||||
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;
|
||||
}
|
||||
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;
|
||||
};
|
||||
|
||||
Scope.prototype.assign = function(name, value) {
|
||||
this.add(name, {
|
||||
value: value,
|
||||
assigned: true
|
||||
});
|
||||
}, true);
|
||||
return this.hasAssignments = true;
|
||||
};
|
||||
|
||||
Scope.prototype.hasDeclarations = function() {
|
||||
return !!this.declaredVariables().length;
|
||||
};
|
||||
|
||||
Scope.prototype.declaredVariables = function() {
|
||||
var realVars, tempVars, v, _i, _len, _ref2;
|
||||
realVars = [];
|
||||
@@ -103,18 +105,20 @@
|
||||
}
|
||||
return realVars.sort().concat(tempVars.sort());
|
||||
};
|
||||
|
||||
Scope.prototype.assignedVariables = function() {
|
||||
var v, _i, _len, _ref2, _results;
|
||||
_ref2 = 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);
|
||||
}
|
||||
if (v.type.assigned) _results.push("" + v.name + " = " + v.type.value);
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
|
||||
return Scope;
|
||||
|
||||
})();
|
||||
|
||||
}).call(this);
|
||||
301
lib/command.js
301
lib/command.js
@@ -1,301 +0,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;
|
||||
fs = require('fs');
|
||||
path = require('path');
|
||||
helpers = require('./helpers');
|
||||
optparse = require('./optparse');
|
||||
CoffeeScript = require('./coffee-script');
|
||||
_ref = require('child_process'), spawn = _ref.spawn, exec = _ref.exec;
|
||||
EventEmitter = require('events').EventEmitter;
|
||||
helpers.extend(CoffeeScript, new EventEmitter);
|
||||
printLine = function(line) {
|
||||
return process.stdout.write(line + '\n');
|
||||
};
|
||||
printWarn = function(line) {
|
||||
return process.binding('stdio').writeError(line + '\n');
|
||||
};
|
||||
BANNER = 'Usage: coffee [options] path/to/script.coffee';
|
||||
SWITCHES = [['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-o', '--output [DIR]', 'set the directory for compiled JavaScript'], ['-j', '--join [FILE]', 'concatenate the scripts before compiling'], ['-w', '--watch', 'watch scripts for changes, and recompile'], ['-p', '--print', 'print the compiled JavaScript to stdout'], ['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-e', '--eval', 'compile a string from the command line'], ['-r', '--require [FILE*]', 'require a library before executing your script'], ['-b', '--bare', 'compile without the top-level function wrapper'], ['-t', '--tokens', 'print the tokens that the lexer produces'], ['-n', '--nodes', 'print the parse tree that Jison produces'], ['--nodejs [ARGS]', 'pass options through to the "node" binary'], ['-v', '--version', 'display CoffeeScript version'], ['-h', '--help', 'display this help message']];
|
||||
opts = {};
|
||||
sources = [];
|
||||
contents = [];
|
||||
optionParser = null;
|
||||
exports.run = function() {
|
||||
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 = process.argv.slice(0, 2).concat(opts.literals);
|
||||
process.argv[0] = 'coffee';
|
||||
process.execPath = require.main.filename;
|
||||
return compileScripts();
|
||||
};
|
||||
compileScripts = function() {
|
||||
var base, compile, source, unprocessed, _i, _j, _len, _len2, _results;
|
||||
unprocessed = [];
|
||||
for (_i = 0, _len = sources.length; _i < _len; _i++) {
|
||||
source = sources[_i];
|
||||
unprocessed[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) {
|
||||
var remaining_files;
|
||||
remaining_files = function() {
|
||||
var total, x, _k, _len3;
|
||||
total = 0;
|
||||
for (_k = 0, _len3 = unprocessed.length; _k < _len3; _k++) {
|
||||
x = unprocessed[_k];
|
||||
total += x;
|
||||
}
|
||||
return total;
|
||||
};
|
||||
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;
|
||||
}
|
||||
unprocessed[sourceIndex] += files.length;
|
||||
for (_k = 0, _len3 = files.length; _k < _len3; _k++) {
|
||||
file = files[_k];
|
||||
compile(path.join(source, file), sourceIndex);
|
||||
}
|
||||
return unprocessed[sourceIndex] -= 1;
|
||||
});
|
||||
} else if (topLevel || path.extname(source) === '.coffee') {
|
||||
fs.readFile(source, function(err, code) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
unprocessed[sourceIndex] -= 1;
|
||||
if (opts.join) {
|
||||
contents[sourceIndex] = helpers.compact([contents[sourceIndex], code.toString()]).join('\n');
|
||||
if (helpers.compact(contents).length > 0 && remaining_files() === 0) {
|
||||
return compileJoin();
|
||||
}
|
||||
} else {
|
||||
return compileScript(source, code.toString(), base);
|
||||
}
|
||||
});
|
||||
if (opts.watch && !opts.join) {
|
||||
return watch(source, base);
|
||||
}
|
||||
} else {
|
||||
return unprocessed[sourceIndex] -= 1;
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
_results.push(compile(source, sources.indexOf(source), true));
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
compileScript = function(file, input, base) {
|
||||
var o, options, t, task;
|
||||
o = opts;
|
||||
options = compileOptions(file);
|
||||
try {
|
||||
t = task = {
|
||||
file: file,
|
||||
input: input,
|
||||
options: options
|
||||
};
|
||||
CoffeeScript.emit('compile', task);
|
||||
if (o.tokens) {
|
||||
return printTokens(CoffeeScript.tokens(t.input));
|
||||
} else if (o.nodes) {
|
||||
return printLine(CoffeeScript.nodes(t.input).toString().trim());
|
||||
} else if (o.run) {
|
||||
return CoffeeScript.run(t.input, t.options);
|
||||
} else {
|
||||
t.output = CoffeeScript.compile(t.input, t.options);
|
||||
CoffeeScript.emit('success', task);
|
||||
if (o.print) {
|
||||
return printLine(t.output.trim());
|
||||
} else if (o.compile) {
|
||||
return writeJs(t.file, t.output, base);
|
||||
} else if (o.lint) {
|
||||
return lint(t.file, t.output);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
CoffeeScript.emit('failure', err, task);
|
||||
if (CoffeeScript.listeners('failure').length) {
|
||||
return;
|
||||
}
|
||||
if (o.watch) {
|
||||
return printLine(err.message);
|
||||
}
|
||||
printWarn(err.stack);
|
||||
return process.exit(1);
|
||||
}
|
||||
};
|
||||
compileStdio = function() {
|
||||
var code, stdin;
|
||||
code = '';
|
||||
stdin = process.openStdin();
|
||||
stdin.on('data', function(buffer) {
|
||||
if (buffer) {
|
||||
return code += buffer.toString();
|
||||
}
|
||||
});
|
||||
return stdin.on('end', function() {
|
||||
return compileScript(null, code);
|
||||
});
|
||||
};
|
||||
compileJoin = function() {
|
||||
var code;
|
||||
code = contents.join('\n');
|
||||
return compileScript(opts.join, code, opts.join);
|
||||
};
|
||||
loadRequires = function() {
|
||||
var realFilename, req, _i, _len, _ref2;
|
||||
realFilename = module.filename;
|
||||
module.filename = '.';
|
||||
_ref2 = opts.require;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
req = _ref2[_i];
|
||||
require(req);
|
||||
}
|
||||
return module.filename = realFilename;
|
||||
};
|
||||
watch = function(source, base) {
|
||||
return fs.watchFile(source, {
|
||||
persistent: true,
|
||||
interval: 500
|
||||
}, function(curr, prev) {
|
||||
if (curr.size === prev.size && curr.mtime.getTime() === prev.mtime.getTime()) {
|
||||
return;
|
||||
}
|
||||
return fs.readFile(source, function(err, code) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
return compileScript(source, code.toString(), base);
|
||||
});
|
||||
});
|
||||
};
|
||||
writeJs = function(source, js, base) {
|
||||
var baseDir, compile, dir, filename, jsPath, 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);
|
||||
compile = function() {
|
||||
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 path.exists(dir, function(exists) {
|
||||
if (exists) {
|
||||
return compile();
|
||||
} else {
|
||||
return exec("mkdir -p " + dir, compile);
|
||||
}
|
||||
});
|
||||
};
|
||||
lint = function(file, js) {
|
||||
var conf, jsl, printIt;
|
||||
printIt = function(buffer) {
|
||||
return printLine(file + ':\t' + buffer.toString().trim());
|
||||
};
|
||||
conf = __dirname + '/../extras/jsl.conf';
|
||||
jsl = spawn('jsl', ['-nologo', '-stdin', '-conf', conf]);
|
||||
jsl.stdout.on('data', printIt);
|
||||
jsl.stderr.on('data', printIt);
|
||||
jsl.stdin.write(js);
|
||||
return jsl.stdin.end();
|
||||
};
|
||||
printTokens = function(tokens) {
|
||||
var strings, tag, token, value;
|
||||
strings = (function() {
|
||||
var _i, _len, _ref2, _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];
|
||||
_results.push("[" + tag + " " + value + "]");
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
return printLine(strings.join(' '));
|
||||
};
|
||||
parseOptions = function() {
|
||||
var o;
|
||||
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;
|
||||
};
|
||||
compileOptions = function(filename) {
|
||||
return {
|
||||
filename: filename,
|
||||
bare: opts.bare
|
||||
};
|
||||
};
|
||||
forkNode = function() {
|
||||
var args, nodeArgs;
|
||||
nodeArgs = opts.nodejs.split(/\s+/);
|
||||
args = process.argv.slice(1);
|
||||
args.splice(args.indexOf('--nodejs'), 2);
|
||||
return spawn(process.execPath, nodeArgs.concat(args), {
|
||||
cwd: process.cwd(),
|
||||
env: process.env,
|
||||
customFds: [0, 1, 2]
|
||||
});
|
||||
};
|
||||
usage = function() {
|
||||
return printLine((new optparse.OptionParser(SWITCHES, BANNER)).help());
|
||||
};
|
||||
version = function() {
|
||||
return printLine("CoffeeScript version " + CoffeeScript.VERSION);
|
||||
};
|
||||
}).call(this);
|
||||
676
lib/parser.js
676
lib/parser.js
File diff suppressed because one or more lines are too long
12
package.json
12
package.json
@@ -3,18 +3,18 @@
|
||||
"description": "Unfancy JavaScript",
|
||||
"keywords": ["javascript", "language", "coffeescript", "compiler"],
|
||||
"author": "Jeremy Ashkenas",
|
||||
"version": "1.1.2",
|
||||
"version": "1.2.0",
|
||||
"licenses": [{
|
||||
"type": "MIT",
|
||||
"url": "http://github.com/jashkenas/coffee-script/raw/master/LICENSE"
|
||||
}],
|
||||
"engines": {
|
||||
"node": ">=0.2.5"
|
||||
"node": ">=0.4.0"
|
||||
},
|
||||
"directories" : {
|
||||
"lib" : "./lib"
|
||||
"lib" : "./lib/coffee-script"
|
||||
},
|
||||
"main" : "./lib/coffee-script",
|
||||
"main" : "./lib/coffee-script/coffee-script",
|
||||
"bin": {
|
||||
"coffee": "./bin/coffee",
|
||||
"cake": "./bin/cake"
|
||||
@@ -23,5 +23,9 @@
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/jashkenas/coffee-script.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"uglify-js": ">=1.0.0",
|
||||
"jison": ">=0.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,23 +39,27 @@ helpers.extend global,
|
||||
missingTask name unless tasks[name]
|
||||
tasks[name].action options
|
||||
|
||||
|
||||
# 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.
|
||||
# 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 = ->
|
||||
path.exists 'Cakefile', (exists) ->
|
||||
throw new Error("Cakefile not found in #{process.cwd()}") unless exists
|
||||
args = process.argv.slice 2
|
||||
CoffeeScript.run fs.readFileSync('Cakefile').toString(), filename: 'Cakefile'
|
||||
oparse = new optparse.OptionParser switches
|
||||
return printTasks() unless args.length
|
||||
global.__originalDirname = fs.realpathSync '.'
|
||||
process.chdir cakefileDirectory __originalDirname
|
||||
args = process.argv.slice 2
|
||||
CoffeeScript.run fs.readFileSync('Cakefile').toString(), filename: 'Cakefile'
|
||||
oparse = new optparse.OptionParser switches
|
||||
return printTasks() unless args.length
|
||||
try
|
||||
options = oparse.parse(args)
|
||||
invoke arg for arg in options.arguments
|
||||
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 ''
|
||||
cakefilePath = path.join path.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,7 +67,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
|
||||
|
||||
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'
|
||||
parent = path.normalize path.join dir, '..'
|
||||
return cakefileDirectory parent unless parent is dir
|
||||
throw new Error "Cakefile not found in #{process.cwd()}"
|
||||
|
||||
35
src/coffee-script.coffee
Executable file → Normal file
35
src/coffee-script.coffee
Executable file → Normal file
@@ -10,6 +10,7 @@ fs = require 'fs'
|
||||
path = require 'path'
|
||||
{Lexer,RESERVED} = require './lexer'
|
||||
{parser} = require './parser'
|
||||
vm = require 'vm'
|
||||
|
||||
# TODO: Remove registerExtension when fully deprecated.
|
||||
if require.extensions
|
||||
@@ -20,7 +21,7 @@ else if require.registerExtension
|
||||
require.registerExtension '.coffee', (content) -> compile content
|
||||
|
||||
# The current CoffeeScript version number.
|
||||
exports.VERSION = '1.1.2'
|
||||
exports.VERSION = '1.2.0'
|
||||
|
||||
# Words that cannot be used as identifiers in CoffeeScript code
|
||||
exports.RESERVED = RESERVED
|
||||
@@ -31,8 +32,9 @@ 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
|
||||
(parser.parse lexer.tokenize code).compile merge {}, options
|
||||
catch err
|
||||
err.message = "In #{options.filename}, #{err.message}" if options.filename
|
||||
throw err
|
||||
@@ -43,7 +45,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
|
||||
@@ -63,9 +65,7 @@ exports.run = (code, options) ->
|
||||
mainModule.moduleCache and= {}
|
||||
|
||||
# Assign paths for node_modules loading
|
||||
if process.binding('natives').module
|
||||
{Module} = require 'module'
|
||||
mainModule.paths = Module._nodeModulePaths path.dirname options.filename
|
||||
mainModule.paths = require('module')._nodeModulePaths path.dirname options.filename
|
||||
|
||||
# Compile.
|
||||
if path.extname(mainModule.filename) isnt '.coffee' or require.extensions
|
||||
@@ -77,23 +77,26 @@ exports.run = (code, options) ->
|
||||
# The CoffeeScript REPL uses this to run the input.
|
||||
exports.eval = (code, options = {}) ->
|
||||
return unless code = code.trim()
|
||||
if {Script} = require 'vm'
|
||||
sandbox = Script.createContext()
|
||||
sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox
|
||||
Script = vm.Script
|
||||
if Script
|
||||
if options.sandbox?
|
||||
if options.sandbox instanceof sandbox.constructor
|
||||
if options.sandbox instanceof Script.createContext().constructor
|
||||
sandbox = options.sandbox
|
||||
else
|
||||
sandbox = Script.createContext()
|
||||
sandbox[k] = v for own k, v of options.sandbox
|
||||
sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox
|
||||
else
|
||||
sandbox = global
|
||||
sandbox.__filename = options.filename || 'eval'
|
||||
sandbox.__dirname = path.dirname sandbox.__filename
|
||||
# define module/require only if they chose not to specify their own
|
||||
unless sandbox.module or sandbox.require
|
||||
unless sandbox isnt global or sandbox.module or sandbox.require
|
||||
Module = require 'module'
|
||||
sandbox.module = _module = new Module(options.modulename || 'eval')
|
||||
sandbox.require = _require = (path) -> Module._load path, _module
|
||||
sandbox.require = _require = (path) -> Module._load path, _module, true
|
||||
_module.filename = sandbox.__filename
|
||||
_require[r] = require[r] for r in Object.getOwnPropertyNames require
|
||||
_require[r] = require[r] for r in Object.getOwnPropertyNames require when r isnt 'paths'
|
||||
# use the same hack node currently uses for their own REPL
|
||||
_require.paths = _module.paths = Module._nodeModulePaths process.cwd()
|
||||
_require.resolve = (request) -> Module._resolveFilename request, _module
|
||||
@@ -101,10 +104,10 @@ exports.eval = (code, options = {}) ->
|
||||
o[k] = v for own k, v of options
|
||||
o.bare = on # ensure return value
|
||||
js = compile code, o
|
||||
if Script
|
||||
Script.runInContext js, sandbox
|
||||
if sandbox is global
|
||||
vm.runInThisContext js
|
||||
else
|
||||
eval js
|
||||
vm.runInContext js, sandbox
|
||||
|
||||
# Instantiate a Lexer for our use here.
|
||||
lexer = new Lexer
|
||||
|
||||
@@ -17,37 +17,41 @@ CoffeeScript = require './coffee-script'
|
||||
helpers.extend CoffeeScript, new EventEmitter
|
||||
|
||||
printLine = (line) -> process.stdout.write line + '\n'
|
||||
printWarn = (line) -> process.binding('stdio').writeError line + '\n'
|
||||
printWarn = (line) -> process.stderr.write line + '\n'
|
||||
|
||||
# The help banner that is printed when `coffee` is called without arguments.
|
||||
BANNER = '''
|
||||
Usage: coffee [options] path/to/script.coffee
|
||||
|
||||
If called without options, `coffee` will run your script.
|
||||
'''
|
||||
|
||||
# The list of all the valid option flags that `coffee` knows how to handle.
|
||||
SWITCHES = [
|
||||
['-b', '--bare', 'compile without a top-level function wrapper']
|
||||
['-c', '--compile', 'compile to JavaScript and save as .js files']
|
||||
['-i', '--interactive', 'run an interactive CoffeeScript REPL']
|
||||
['-o', '--output [DIR]', 'set the directory for compiled JavaScript']
|
||||
['-j', '--join [FILE]', 'concatenate the scripts before compiling']
|
||||
['-w', '--watch', 'watch scripts for changes, and recompile']
|
||||
['-p', '--print', 'print the compiled JavaScript to stdout']
|
||||
['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint']
|
||||
['-s', '--stdio', 'listen for and compile scripts over stdio']
|
||||
['-e', '--eval', 'compile a string from the command line']
|
||||
['-r', '--require [FILE*]', 'require a library before executing your script']
|
||||
['-b', '--bare', 'compile without the top-level function wrapper']
|
||||
['-t', '--tokens', 'print the tokens that the lexer produces']
|
||||
['-n', '--nodes', 'print the parse tree that Jison produces']
|
||||
[ '--nodejs [ARGS]', 'pass options through to the "node" binary']
|
||||
['-v', '--version', 'display CoffeeScript version']
|
||||
['-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']
|
||||
]
|
||||
|
||||
# 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.
|
||||
@@ -60,58 +64,53 @@ exports.run = ->
|
||||
return version() if opts.version
|
||||
loadRequires() if opts.require
|
||||
return require './repl' if opts.interactive
|
||||
if opts.watch and !fs.watch
|
||||
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 = process.argv.slice(0, 2).concat opts.literals
|
||||
process.argv = process.argv.slice(0, 2).concat opts.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'
|
||||
files = files.map (file) -> path.join source, file
|
||||
index = sources.indexOf source
|
||||
sources[index..index] = files
|
||||
sourceCode[index..index] = files.map -> null
|
||||
compilePath file, no, base for file in files
|
||||
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 = []
|
||||
for source in sources
|
||||
unprocessed[sources.indexOf(source)]=1
|
||||
for source in sources
|
||||
base = path.join(source)
|
||||
compile = (source, sourceIndex, topLevel) ->
|
||||
remaining_files = ->
|
||||
total = 0
|
||||
total += x for x in unprocessed
|
||||
total
|
||||
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
|
||||
unprocessed[sourceIndex] += files.length
|
||||
for file in files
|
||||
compile path.join(source, file), sourceIndex
|
||||
unprocessed[sourceIndex] -= 1
|
||||
else if topLevel or path.extname(source) is '.coffee'
|
||||
fs.readFile source, (err, code) ->
|
||||
throw err if err
|
||||
unprocessed[sourceIndex] -= 1
|
||||
if opts.join
|
||||
contents[sourceIndex] = helpers.compact([contents[sourceIndex], code.toString()]).join('\n')
|
||||
if helpers.compact(contents).length > 0 and remaining_files() == 0
|
||||
compileJoin()
|
||||
else
|
||||
compileScript(source, code.toString(), base)
|
||||
watch source, base if opts.watch and not opts.join
|
||||
else
|
||||
unprocessed[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`,
|
||||
@@ -125,6 +124,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
|
||||
@@ -135,7 +137,7 @@ compileScript = (file, input, base) ->
|
||||
CoffeeScript.emit 'failure', err, task
|
||||
return if CoffeeScript.listeners('failure').length
|
||||
return printLine err.message if o.watch
|
||||
printWarn err.stack
|
||||
printWarn err instanceof Error and err.stack or "ERROR: #{err}"
|
||||
process.exit 1
|
||||
|
||||
# Attach the appropriate listeners to compile scripts incoming over **stdin**,
|
||||
@@ -148,11 +150,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 = ->
|
||||
@@ -161,40 +167,132 @@ loadRequires = ->
|
||||
require req for req in opts.require
|
||||
module.filename = realFilename
|
||||
|
||||
# Watch a source CoffeeScript file using `fs.watchFile`, recompiling it every
|
||||
# Watch a source CoffeeScript file using `fs.watch`, recompiling it every
|
||||
# time the file is updated. May be used in combination with other options,
|
||||
# such as `--lint` or `--print`.
|
||||
watch = (source, base) ->
|
||||
fs.watchFile source, {persistent: true, interval: 500}, (curr, prev) ->
|
||||
return if curr.size is prev.size and curr.mtime.getTime() is prev.mtime.getTime()
|
||||
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
|
||||
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 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)
|
||||
|
||||
watchErr = (e) ->
|
||||
throw e unless e.code is 'ENOENT'
|
||||
removeSource source, base, yes
|
||||
compileJoin()
|
||||
|
||||
try
|
||||
watcher = fs.watch source, callback = (event) ->
|
||||
if event is 'change'
|
||||
compile()
|
||||
else if event is 'rename'
|
||||
watcher.close()
|
||||
wait 250, ->
|
||||
compile()
|
||||
try
|
||||
watcher = fs.watch source, callback
|
||||
catch e
|
||||
watchErr e
|
||||
catch e
|
||||
watchErr e
|
||||
|
||||
|
||||
# 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
|
||||
files = files.map (file) -> path.join source, file
|
||||
for file in files when not notSources[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.slice()
|
||||
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
|
||||
path.exists jsPath, (exists) ->
|
||||
if exists
|
||||
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}"
|
||||
path.exists jsDir, (exists) ->
|
||||
if exists 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.
|
||||
lint = (file, js) ->
|
||||
printIt = (buffer) -> printLine file + ':\t' + buffer.toString().trim()
|
||||
conf = __dirname + '/../extras/jsl.conf'
|
||||
conf = __dirname + '/../../extras/jsl.conf'
|
||||
jsl = spawn 'jsl', ['-nologo', '-stdin', '-conf', conf]
|
||||
jsl.stdout.on 'data', printIt
|
||||
jsl.stderr.on 'data', printIt
|
||||
@@ -217,6 +315,8 @@ parseOptions = ->
|
||||
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}
|
||||
|
||||
@@ -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,6 +126,7 @@ grammar =
|
||||
o 'AlphaNumeric'
|
||||
o 'JS', -> new Literal $1
|
||||
o 'REGEX', -> new Literal $1
|
||||
o 'DEBUGGER', -> new Literal $1
|
||||
o 'BOOL', ->
|
||||
val = new Literal $1
|
||||
val.isUndefined = yes if $1 is 'undefined'
|
||||
@@ -135,6 +136,7 @@ grammar =
|
||||
# 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
|
||||
]
|
||||
|
||||
@@ -217,8 +219,8 @@ grammar =
|
||||
# Variables and properties that can be assigned to.
|
||||
SimpleAssignable: [
|
||||
o 'Identifier', -> new Value $1
|
||||
o 'Value Accessor', -> $1.push $2
|
||||
o 'Invocation Accessor', -> new Value $1, [$2]
|
||||
o 'Value Accessor', -> $1.add $2
|
||||
o 'Invocation Accessor', -> new Value $1, [].concat $2
|
||||
o 'ThisProperty'
|
||||
]
|
||||
|
||||
@@ -244,7 +246,7 @@ grammar =
|
||||
Accessor: [
|
||||
o '. Identifier', -> new Access $2
|
||||
o '?. Identifier', -> new Access $2, 'soak'
|
||||
o ':: Identifier', -> new Access $2, 'proto'
|
||||
o ':: Identifier', -> [(new Access new Literal 'prototype'), new Access $2]
|
||||
o '::', -> new Access new Literal 'prototype'
|
||||
o 'Index'
|
||||
]
|
||||
@@ -253,7 +255,6 @@ grammar =
|
||||
Index: [
|
||||
o 'INDEX_START IndexValue INDEX_END', -> $2
|
||||
o 'INDEX_SOAK Index', -> extend $2, soak : yes
|
||||
o 'INDEX_PROTO Index', -> extend $2, proto: yes
|
||||
]
|
||||
|
||||
IndexValue: [
|
||||
@@ -279,14 +280,14 @@ grammar =
|
||||
# Class definitions have optional bodies of prototype property assignments,
|
||||
# and optional references to the superclass.
|
||||
Class: [
|
||||
o 'CLASS', -> new Class
|
||||
o 'CLASS Block', -> new Class null, null, $2
|
||||
o 'CLASS EXTENDS Value', -> new Class null, $3
|
||||
o 'CLASS EXTENDS Value Block', -> new Class null, $3, $4
|
||||
o 'CLASS SimpleAssignable', -> new Class $2
|
||||
o 'CLASS SimpleAssignable Block', -> new Class $2, null, $3
|
||||
o 'CLASS SimpleAssignable EXTENDS Value', -> new Class $2, $4
|
||||
o 'CLASS SimpleAssignable EXTENDS Value Block', -> new Class $2, $4, $5
|
||||
o 'CLASS', -> new Class
|
||||
o 'CLASS Block', -> new Class null, null, $2
|
||||
o 'CLASS EXTENDS Expression', -> new Class null, $3
|
||||
o 'CLASS EXTENDS Expression Block', -> new Class null, $3, $4
|
||||
o 'CLASS SimpleAssignable', -> new Class $2
|
||||
o 'CLASS SimpleAssignable Block', -> new Class $2, null, $3
|
||||
o 'CLASS SimpleAssignable EXTENDS Expression', -> new Class $2, $4
|
||||
o 'CLASS SimpleAssignable EXTENDS Expression Block', -> new Class $2, $4, $5
|
||||
]
|
||||
|
||||
# Ordinary function invocation, or a chained series of calls.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
# Which is a format that can be fed directly into [Jison](http://github.com/zaach/jison).
|
||||
|
||||
{Rewriter} = require './rewriter'
|
||||
{Rewriter, INVERSES} = require './rewriter'
|
||||
|
||||
# Import the helpers we need.
|
||||
{count, starts, compact, last} = require './helpers'
|
||||
@@ -41,6 +41,7 @@ exports.Lexer = class Lexer
|
||||
@indebt = 0 # The over-indentation at the current level.
|
||||
@outdebt = 0 # The under-outdentation at the current level.
|
||||
@indents = [] # The stack of all current indentation levels.
|
||||
@ends = [] # The stack for pairing up tokens.
|
||||
@tokens = [] # Stream of parsed tokens in the form `['TYPE', value, line]`.
|
||||
|
||||
# At every position, run through this list of attempted matches,
|
||||
@@ -60,6 +61,7 @@ exports.Lexer = class Lexer
|
||||
@literalToken()
|
||||
|
||||
@closeIndentation()
|
||||
@error "missing #{tag}" if tag = @ends.pop()
|
||||
return @tokens if opts.rewrite is off
|
||||
(new Rewriter).rewrite @tokens
|
||||
|
||||
@@ -104,13 +106,13 @@ exports.Lexer = class Lexer
|
||||
@tokens.pop()
|
||||
id = '!' + id
|
||||
|
||||
if id in JS_FORBIDDEN
|
||||
if id in ['eval', 'arguments'].concat JS_FORBIDDEN
|
||||
if forcedIdentifier
|
||||
tag = 'IDENTIFIER'
|
||||
id = new String id
|
||||
id.reserved = yes
|
||||
else if id in RESERVED
|
||||
@identifierError id
|
||||
@error "reserved word \"#{id}\""
|
||||
|
||||
unless forcedIdentifier
|
||||
id = COFFEE_ALIAS_MAP[id] if id in COFFEE_ALIASES
|
||||
@@ -119,7 +121,7 @@ exports.Lexer = class Lexer
|
||||
when '==', '!=' then 'COMPARE'
|
||||
when '&&', '||' then 'LOGIC'
|
||||
when 'true', 'false', 'null', 'undefined' then 'BOOL'
|
||||
when 'break', 'continue', 'debugger' then 'STATEMENT'
|
||||
when 'break', 'continue' then 'STATEMENT'
|
||||
else tag
|
||||
|
||||
@token tag, id
|
||||
@@ -131,8 +133,11 @@ exports.Lexer = class Lexer
|
||||
numberToken: ->
|
||||
return 0 unless match = NUMBER.exec @chunk
|
||||
number = match[0]
|
||||
lexedLength = number.length
|
||||
if binaryLiteral = /0b([01]+)/.exec number
|
||||
number = (parseInt binaryLiteral[1], 2).toString()
|
||||
@token 'NUMBER', number
|
||||
number.length
|
||||
lexedLength
|
||||
|
||||
# Matches strings, including multi-line strings. Ensures that quotation marks
|
||||
# are balanced within the string's contents, and within nested interpolations.
|
||||
@@ -196,15 +201,18 @@ exports.Lexer = class Lexer
|
||||
prev = last @tokens
|
||||
return 0 if prev and (prev[0] in (if prev.spaced then NOT_REGEX else NOT_SPACED_REGEX))
|
||||
return 0 unless match = REGEX.exec @chunk
|
||||
[regex] = match
|
||||
@token 'REGEX', if regex is '//' then '/(?:)/' else regex
|
||||
regex.length
|
||||
[match, regex, flags] = match
|
||||
if regex[..1] is '/*' then @error 'regular expressions cannot begin with `*`'
|
||||
if regex is '//' then regex = '/(?:)/'
|
||||
@token 'REGEX', "#{regex}#{flags}"
|
||||
match.length
|
||||
|
||||
# Matches multiline extended regular expressions.
|
||||
heregexToken: (match) ->
|
||||
[heregex, body, flags] = match
|
||||
if 0 > body.indexOf '#{'
|
||||
re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/')
|
||||
if re.match /^\*/ then @error 'regular expressions cannot begin with `*`'
|
||||
@token 'REGEX', "/#{ re or '(?:)' }/#{flags}"
|
||||
return heregex.length
|
||||
@token 'IDENTIFIER', 'RegExp'
|
||||
@@ -239,6 +247,7 @@ exports.Lexer = class Lexer
|
||||
return 0 unless match = MULTI_DENT.exec @chunk
|
||||
indent = match[0]
|
||||
@line += count indent, '\n'
|
||||
@seenFor = no
|
||||
prev = last @tokens, 1
|
||||
size = indent.length - 1 - indent.lastIndexOf '\n'
|
||||
noNewlines = @unfinished()
|
||||
@@ -253,6 +262,7 @@ exports.Lexer = class Lexer
|
||||
diff = size - @indent + @outdebt
|
||||
@token 'INDENT', diff
|
||||
@indents.push diff
|
||||
@ends.push 'OUTDENT'
|
||||
@outdebt = @indebt = 0
|
||||
else
|
||||
@indebt = 0
|
||||
@@ -262,7 +272,7 @@ exports.Lexer = class Lexer
|
||||
|
||||
# Record an outdent token or multiple tokens, if we happen to be moving back
|
||||
# inwards past several recorded indents.
|
||||
outdentToken: (moveOut, noNewlines, close) ->
|
||||
outdentToken: (moveOut, noNewlines) ->
|
||||
while moveOut > 0
|
||||
len = @indents.length - 1
|
||||
if @indents[len] is undefined
|
||||
@@ -277,8 +287,10 @@ exports.Lexer = class Lexer
|
||||
dent = @indents.pop() - @outdebt
|
||||
moveOut -= dent
|
||||
@outdebt = 0
|
||||
@pair 'OUTDENT'
|
||||
@token 'OUTDENT', dent
|
||||
@outdebt -= moveOut if dent
|
||||
@tokens.pop() while @value() is ';'
|
||||
@token 'TERMINATOR', '\n' unless @tag() is 'TERMINATOR' or noNewlines
|
||||
this
|
||||
|
||||
@@ -293,6 +305,7 @@ exports.Lexer = class Lexer
|
||||
|
||||
# Generate a newline token. Consecutive newlines get merged together.
|
||||
newlineToken: ->
|
||||
@tokens.pop() while @value() is ';'
|
||||
@token 'TERMINATOR', '\n' unless @tag() is 'TERMINATOR'
|
||||
this
|
||||
|
||||
@@ -316,12 +329,15 @@ exports.Lexer = class Lexer
|
||||
tag = value
|
||||
prev = last @tokens
|
||||
if value is '=' and prev
|
||||
@assignmentError() if not prev[1].reserved and prev[1] in JS_FORBIDDEN
|
||||
if not prev[1].reserved and prev[1] in JS_FORBIDDEN
|
||||
@error "reserved word \"#{@value()}\" can't be assigned"
|
||||
if prev[1] in ['||', '&&']
|
||||
prev[0] = 'COMPOUND_ASSIGN'
|
||||
prev[1] += '='
|
||||
return value.length
|
||||
if value is ';' then 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'
|
||||
@@ -336,7 +352,9 @@ exports.Lexer = class Lexer
|
||||
tag = 'INDEX_START'
|
||||
switch prev[0]
|
||||
when '?' then prev[0] = 'INDEX_SOAK'
|
||||
when '::' then prev[0] = 'INDEX_PROTO'
|
||||
switch value
|
||||
when '(', '{', '[' then @ends.push INVERSES[value]
|
||||
when ')', '}', ']' then @pair value
|
||||
@token tag, value
|
||||
value.length
|
||||
|
||||
@@ -349,7 +367,7 @@ exports.Lexer = class Lexer
|
||||
{indent, herecomment} = options
|
||||
if herecomment
|
||||
if HEREDOC_ILLEGAL.test doc
|
||||
throw new Error "block comment cannot contain \"*/\", starting on line #{@line + 1}"
|
||||
@error "block comment cannot contain \"*/\", starting"
|
||||
return doc if doc.indexOf('\n') <= 0
|
||||
else
|
||||
while match = HEREDOC_INDENT.exec doc
|
||||
@@ -384,16 +402,6 @@ exports.Lexer = class Lexer
|
||||
closeIndentation: ->
|
||||
@outdentToken @indent
|
||||
|
||||
# The error for when you try to use a forbidden word in JavaScript as
|
||||
# an identifier.
|
||||
identifierError: (word) ->
|
||||
throw SyntaxError "Reserved word \"#{word}\" on line #{@line + 1}"
|
||||
|
||||
# The error for when you try to assign to a reserved word in JavaScript,
|
||||
# like "function" or "default".
|
||||
assignmentError: ->
|
||||
throw SyntaxError "Reserved word \"#{@value()}\" on line #{@line + 1} can't be assigned"
|
||||
|
||||
# Matches a balanced group such as a single or double-quoted string. Pass in
|
||||
# a series of delimiters, all of which must be nested correctly within the
|
||||
# contents of the string. This method allows us to have strings within
|
||||
@@ -420,8 +428,7 @@ exports.Lexer = class Lexer
|
||||
else if end is '"' and prev is '#' and letter is '{'
|
||||
stack.push end = '}'
|
||||
prev = letter
|
||||
throw new Error "missing #{ stack.pop() }, starting on line #{ @line + 1 }"
|
||||
|
||||
@error "missing #{ stack.pop() }, starting"
|
||||
|
||||
# Expand variables and expressions inside double-quoted strings using
|
||||
# Ruby-like notation for substitution of arbitrary expressions.
|
||||
@@ -451,8 +458,8 @@ exports.Lexer = class Lexer
|
||||
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
|
||||
@@ -470,6 +477,21 @@ exports.Lexer = class Lexer
|
||||
@token ')', ')' if interpolated
|
||||
tokens
|
||||
|
||||
# Pairs up a closing token, ensuring that all listed pairs of tokens are
|
||||
# correctly balanced throughout the course of the token stream.
|
||||
pair: (tag) ->
|
||||
unless tag is wanted = last @ends
|
||||
@error "unmatched #{tag}" unless 'OUTDENT' is wanted
|
||||
# Auto-close INDENT to support syntax like this:
|
||||
#
|
||||
# el.click((event) ->
|
||||
# el.hide())
|
||||
#
|
||||
@indent -= size = last @indents
|
||||
@outdentToken size, true
|
||||
return @pair tag
|
||||
@ends.pop()
|
||||
|
||||
# Helpers
|
||||
# -------
|
||||
|
||||
@@ -488,9 +510,8 @@ exports.Lexer = class Lexer
|
||||
# Are we in the midst of an unfinished expression?
|
||||
unfinished: ->
|
||||
LINE_CONTINUER.test(@chunk) or
|
||||
(prev = last @tokens, 1) and prev[0] isnt '.' and
|
||||
(value = @value()) and not value.reserved and
|
||||
NO_NEWLINE.test(value) and not CODE.test(value) and not ASSIGNED.test(@chunk)
|
||||
@tag() in ['\\', '.', '?.', 'UNARY', 'MATH', '+', '-', 'SHIFT', 'RELATION'
|
||||
'COMPARE', 'LOGIC', 'COMPOUND_ASSIGN', 'THROW', 'EXTENDS']
|
||||
|
||||
# Converts newlines for string literals.
|
||||
escapeLines: (str, heredoc) ->
|
||||
@@ -503,6 +524,10 @@ 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) ->
|
||||
throw SyntaxError "#{message} on line #{ @line + 1}"
|
||||
|
||||
# Constants
|
||||
# ---------
|
||||
@@ -556,6 +581,7 @@ IDENTIFIER = /// ^
|
||||
|
||||
NUMBER = ///
|
||||
^ 0x[\da-f]+ | # hex
|
||||
^ 0b[01]+ | # binary
|
||||
^ \d*\.?\d+ (?:e[+-]?\d+)? # decimal
|
||||
///i
|
||||
|
||||
@@ -585,7 +611,7 @@ JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/
|
||||
|
||||
# Regex-matching-regexes.
|
||||
REGEX = /// ^
|
||||
/ (?! [\s=] ) # disallow leading whitespace or equals signs
|
||||
(/ (?! [\s=] ) # disallow leading whitespace or equals signs
|
||||
[^ [ / \n \\ ]* # every other thing
|
||||
(?:
|
||||
(?: \\[\s\S] # anything escaped
|
||||
@@ -595,7 +621,7 @@ REGEX = /// ^
|
||||
]
|
||||
) [^ [ / \n \\ ]*
|
||||
)*
|
||||
/ [imgy]{0,4} (?!\w)
|
||||
/) ([imgy]{0,4}) (?!\w)
|
||||
///
|
||||
|
||||
HEREGEX = /// ^ /{3} ([\s\S]+?) /{3} ([imgy]{0,4}) (?!\w) ///
|
||||
@@ -609,18 +635,10 @@ HEREDOC_INDENT = /\n+([^\n\S]*)/g
|
||||
|
||||
HEREDOC_ILLEGAL = /\*\//
|
||||
|
||||
ASSIGNED = /^\s*@?([$A-Za-z_][$\w\x7f-\uffff]*|['"].*['"])[^\n\S]*?[:=][^:=>]/
|
||||
|
||||
LINE_CONTINUER = /// ^ \s* (?: , | \??\.(?![.\d]) | :: ) ///
|
||||
|
||||
TRAILING_SPACES = /\s+$/
|
||||
|
||||
NO_NEWLINE = /// ^ (?: # non-capturing group
|
||||
[-+*&|/%=<>!.\\][<>=&|]* | # symbol operators
|
||||
and | or | is(?:nt)? | n(?:ot|ew) | # word operators
|
||||
delete | typeof | instanceof
|
||||
) $ ///
|
||||
|
||||
# Compound assignment tokens.
|
||||
COMPOUND_ASSIGN = [
|
||||
'-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|='
|
||||
|
||||
351
src/nodes.coffee
351
src/nodes.coffee
@@ -4,6 +4,7 @@
|
||||
# the syntax tree into a string of JavaScript code, call `compile()` on the root.
|
||||
|
||||
{Scope} = require './scope'
|
||||
{RESERVED} = require './lexer'
|
||||
|
||||
# Import the helpers we plan to use.
|
||||
{compact, flatten, extend, merge, del, starts, ends, last} = require './helpers'
|
||||
@@ -48,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
|
||||
@@ -75,8 +76,12 @@ exports.Base = class Base
|
||||
# Construct a node that returns the current node's result.
|
||||
# Note that this is overridden for smarter behavior for
|
||||
# many statement nodes (e.g. If, For)...
|
||||
makeReturn: ->
|
||||
new Return this
|
||||
makeReturn: (res) ->
|
||||
me = @unwrapAll()
|
||||
if res
|
||||
new Call new Literal("#{res}.push"), [me]
|
||||
else
|
||||
new Return me
|
||||
|
||||
# Does this node, or any of its children, contain a node of a certain kind?
|
||||
# Recursively traverses down the *children* of the nodes, yielding to a block
|
||||
@@ -190,12 +195,12 @@ exports.Block = class Block extends Base
|
||||
|
||||
# A Block node does not return its entire body, rather it
|
||||
# ensures that the final expression is returned.
|
||||
makeReturn: ->
|
||||
makeReturn: (res) ->
|
||||
len = @expressions.length
|
||||
while len--
|
||||
expr = @expressions[len]
|
||||
if expr not instanceof Comment
|
||||
@expressions[len] = expr.makeReturn()
|
||||
@expressions[len] = expr.makeReturn res
|
||||
@expressions.splice(len, 1) if expr instanceof Return and not expr.expression
|
||||
break
|
||||
this
|
||||
@@ -222,10 +227,14 @@ 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 + ';'
|
||||
codes.push if node.isStatement o then code else "#{@tab}#{code};"
|
||||
else
|
||||
codes.push node.compile o, LEVEL_LIST
|
||||
return codes.join '\n' if top
|
||||
if top
|
||||
if @spaced
|
||||
return "\n#{codes.join '\n\n'}\n"
|
||||
else
|
||||
return codes.join '\n'
|
||||
code = codes.join(', ') or 'void 0'
|
||||
if codes.length > 1 and o.level >= LEVEL_LIST then "(#{code})" else code
|
||||
|
||||
@@ -234,11 +243,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
|
||||
code = @compileWithDeclarations o
|
||||
if o.bare then code else "(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.
|
||||
@@ -249,20 +269,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
|
||||
@@ -280,7 +304,7 @@ exports.Literal = class Literal extends Base
|
||||
constructor: (@value) ->
|
||||
|
||||
makeReturn: ->
|
||||
if @isStatement() then this else new Return this
|
||||
if @isStatement() then this else super
|
||||
|
||||
isAssignable: ->
|
||||
IDENTIFIER.test @value
|
||||
@@ -294,13 +318,15 @@ 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.reserved
|
||||
else 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']
|
||||
"\"#{@value}\""
|
||||
else
|
||||
@value
|
||||
@@ -328,7 +354,7 @@ exports.Return = class Return extends Base
|
||||
if expr and expr not instanceof Return then expr.compile o, level else super o, level
|
||||
|
||||
compileNode: (o) ->
|
||||
@tab + "return#{ if @expression then ' ' + @expression.compile(o, LEVEL_PAREN) else '' };"
|
||||
@tab + "return#{[" #{@expression.compile o, LEVEL_PAREN}" if @expression]};"
|
||||
|
||||
#### Value
|
||||
|
||||
@@ -344,9 +370,9 @@ exports.Value = class Value extends Base
|
||||
|
||||
children: ['base', 'properties']
|
||||
|
||||
# Add a property access to the list.
|
||||
push: (prop) ->
|
||||
@properties.push prop
|
||||
# Add a property (or *properties* ) `Access` to the list.
|
||||
add: (props) ->
|
||||
@properties = @properties.concat props
|
||||
this
|
||||
|
||||
hasProperties: ->
|
||||
@@ -373,9 +399,6 @@ exports.Value = class Value extends Base
|
||||
isSplice: ->
|
||||
last(@properties) instanceof Slice
|
||||
|
||||
makeReturn: ->
|
||||
if @properties.length then super() else @base.makeReturn()
|
||||
|
||||
# The value can be unwrapped as its inner node, if there are no attached
|
||||
# properties.
|
||||
unwrap: ->
|
||||
@@ -397,7 +420,7 @@ exports.Value = class Value extends Base
|
||||
nref = new Literal o.scope.freeVariable 'name'
|
||||
name = new Index new Assign nref, name.index
|
||||
nref = new Index nref
|
||||
[base.push(name), new Value(bref or base.base, [nref or name])]
|
||||
[base.add(name), new Value(bref or base.base, [nref or name])]
|
||||
|
||||
# We compile a value to JavaScript by compiling and joining each property.
|
||||
# Things get much more interesting if the chain of properties has *soak*
|
||||
@@ -441,7 +464,7 @@ exports.Comment = class Comment extends Base
|
||||
makeReturn: THIS
|
||||
|
||||
compileNode: (o, level) ->
|
||||
code = '/*' + multident(@comment, @tab) + '*/'
|
||||
code = '/*' + multident(@comment, @tab) + "\n#{@tab}*/"
|
||||
code = o.indent + code if (level or o.level) is LEVEL_TOP
|
||||
code
|
||||
|
||||
@@ -459,7 +482,7 @@ exports.Call = class Call extends Base
|
||||
|
||||
# Tag this invocation as creating a new instance.
|
||||
newInstance: ->
|
||||
base = @variable.base or @variable
|
||||
base = @variable?.base or @variable
|
||||
if base instanceof Call and not base.isNew
|
||||
base.newInstance()
|
||||
else
|
||||
@@ -474,7 +497,10 @@ exports.Call = class Call extends Base
|
||||
{name} = method
|
||||
throw SyntaxError 'cannot call super on an anonymous function.' unless name?
|
||||
if method.klass
|
||||
(new Value (new Literal method.klass), [new Access(new Literal "__super__"), new Access new Literal name]).compile o
|
||||
accesses = [new Access(new Literal '__super__')]
|
||||
accesses.push new Access new Literal 'constructor' if method.static
|
||||
accesses.push new Access new Literal name
|
||||
(new Value (new Literal method.klass), accesses).compile o
|
||||
else
|
||||
"#{name}.__super__.constructor"
|
||||
|
||||
@@ -586,7 +612,6 @@ exports.Extends = class Extends extends Base
|
||||
|
||||
# Hooks one constructor into another's prototype chain.
|
||||
compile: (o) ->
|
||||
utility 'hasProp'
|
||||
new Call(new Value(new Literal utility 'extends'), [@child, @parent]).compile o
|
||||
|
||||
#### Access
|
||||
@@ -596,14 +621,13 @@ exports.Extends = class Extends extends Base
|
||||
exports.Access = class Access extends Base
|
||||
constructor: (@name, tag) ->
|
||||
@name.asKey = yes
|
||||
@proto = if tag is 'proto' then '.prototype' else ''
|
||||
@soak = tag is 'soak'
|
||||
|
||||
children: ['name']
|
||||
|
||||
compile: (o) ->
|
||||
name = @name.compile o
|
||||
@proto + if IDENTIFIER.test name then ".#{name}" else "[#{name}]"
|
||||
if IDENTIFIER.test name then ".#{name}" else "[#{name}]"
|
||||
|
||||
isComplex: NO
|
||||
|
||||
@@ -616,7 +640,7 @@ exports.Index = class Index extends Base
|
||||
children: ['index']
|
||||
|
||||
compile: (o) ->
|
||||
(if @proto then '.prototype' else '') + "[#{ @index.compile o, LEVEL_PAREN }]"
|
||||
"[#{ @index.compile o, LEVEL_PAREN }]"
|
||||
|
||||
isComplex: ->
|
||||
@index.isComplex()
|
||||
@@ -660,13 +684,13 @@ exports.Range = class Range extends Base
|
||||
|
||||
# Generate the condition.
|
||||
condPart = if @stepNum
|
||||
condPart = if +@stepNum > 0 then "#{lt} #{@toVar}" else "#{gt} #{@toVar}"
|
||||
if +@stepNum > 0 then "#{lt} #{@toVar}" else "#{gt} #{@toVar}"
|
||||
else if known
|
||||
[from, to] = [+@fromNum, +@toNum]
|
||||
condPart = if from <= to then "#{lt} #{to}" else "#{gt} #{to}"
|
||||
if from <= to then "#{lt} #{to}" else "#{gt} #{to}"
|
||||
else
|
||||
cond = "#{@fromVar} <= #{@toVar}"
|
||||
condPart = "#{cond} ? #{lt} #{@toVar} : #{gt} #{@toVar}"
|
||||
"#{cond} ? #{lt} #{@toVar} : #{gt} #{@toVar}"
|
||||
|
||||
# Generate the step.
|
||||
stepPart = if @stepVar
|
||||
@@ -720,14 +744,14 @@ 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_PAREN
|
||||
compiled = to and to.compile o, LEVEL_ACCESS
|
||||
if to and not (not @range.exclusive and +compiled is -1)
|
||||
toStr = ', ' + if @range.exclusive
|
||||
compiled
|
||||
else if SIMPLENUM.test compiled
|
||||
(+compiled + 1).toString()
|
||||
else
|
||||
"(#{compiled} + 1) || 9e9"
|
||||
"#{compiled} + 1 || 9e9"
|
||||
".slice(#{ fromStr }#{ toStr or '' })"
|
||||
|
||||
#### Obj
|
||||
@@ -856,11 +880,15 @@ exports.Class = class Class extends Base
|
||||
@externalCtor = o.scope.freeVariable 'class'
|
||||
assign = new Assign new Literal(@externalCtor), func
|
||||
else
|
||||
unless assign.variable.this
|
||||
assign.variable = new Value(new Literal(name), [new Access(base, 'proto')])
|
||||
if func instanceof Code and func.bound
|
||||
@boundFuncs.push base
|
||||
func.bound = no
|
||||
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
|
||||
@boundFuncs.push base
|
||||
func.bound = no
|
||||
assign
|
||||
compact exprs
|
||||
|
||||
@@ -892,17 +920,26 @@ exports.Class = class Class extends Base
|
||||
compileNode: (o) ->
|
||||
decl = @determineName()
|
||||
name = decl or @name or '_Class'
|
||||
name = "_#{name}" if name.reserved
|
||||
lname = new Literal name
|
||||
|
||||
@setContext name
|
||||
@walkBody name, o
|
||||
@ensureConstructor name
|
||||
@body.expressions.unshift new Extends lname, @parent if @parent
|
||||
@body.spaced = yes
|
||||
@body.expressions.unshift @ctor unless @ctor instanceof Code
|
||||
@body.expressions.push lname
|
||||
@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
|
||||
call.variable.params.push new Param @superClass
|
||||
|
||||
klass = new Parens call, yes
|
||||
klass = new Assign @variable, klass if @variable
|
||||
klass.compile o
|
||||
|
||||
@@ -913,6 +950,7 @@ exports.Class = class Class extends Base
|
||||
exports.Assign = class Assign extends Base
|
||||
constructor: (@variable, @value, @context, options) ->
|
||||
@param = options and options.param
|
||||
@subpattern = options and options.subpattern
|
||||
|
||||
children: ['variable', 'value']
|
||||
|
||||
@@ -935,13 +973,14 @@ exports.Assign = class Assign extends Base
|
||||
return @compileSplice o if @variable.isSplice()
|
||||
return @compileConditional o if @context in ['||=', '&&=', '?=']
|
||||
name = @variable.compile o, LEVEL_LIST
|
||||
unless @context or @variable.isAssignable()
|
||||
throw SyntaxError "\"#{ @variable.compile o }\" cannot be assigned."
|
||||
unless @context or isValue and (@variable.namespaced or @variable.hasProperties())
|
||||
if @param
|
||||
o.scope.add name, 'var'
|
||||
else
|
||||
o.scope.find name
|
||||
unless @context
|
||||
unless (varBase = @variable.unwrapAll()).isAssignable()
|
||||
throw SyntaxError "\"#{ @variable.compile o }\" cannot be assigned."
|
||||
unless varBase.hasProperties?()
|
||||
if @param
|
||||
o.scope.add name, 'var'
|
||||
else
|
||||
o.scope.find name
|
||||
if @value instanceof Code and match = METHOD_DEF.exec name
|
||||
@value.klass = match[1] if match[1]
|
||||
@value.name = match[2] ? match[3] ? match[4] ? match[5]
|
||||
@@ -977,6 +1016,8 @@ 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
|
||||
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
|
||||
assigns = []
|
||||
@@ -998,6 +1039,8 @@ exports.Assign = class Assign extends Base
|
||||
else
|
||||
idx = if obj.this then obj.properties[0].name else obj
|
||||
if not splat and obj instanceof Splat
|
||||
name = obj.name.unwrap().value
|
||||
obj = obj.unwrap()
|
||||
val = "#{olen} <= #{vvar}.length ? #{ utility 'slice' }.call(#{vvar}, #{i}"
|
||||
if rest = olen - i - 1
|
||||
ivar = o.scope.freeVariable 'i'
|
||||
@@ -1007,18 +1050,21 @@ exports.Assign = class Assign extends Base
|
||||
val = new Literal val
|
||||
splat = "#{ivar}++"
|
||||
else
|
||||
name = obj.unwrap().value
|
||||
if obj instanceof Splat
|
||||
obj = obj.name.compile o
|
||||
throw SyntaxError \
|
||||
"multiple splats are disallowed in an assignment: #{obj} ..."
|
||||
throw new SyntaxError \
|
||||
"multiple splats are disallowed in an assignment: #{obj}..."
|
||||
if typeof idx is 'number'
|
||||
idx = new Literal splat or idx
|
||||
acc = no
|
||||
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]
|
||||
assigns.push new Assign(obj, val, null, param: @param).compile o, LEVEL_TOP
|
||||
assigns.push vvar unless top
|
||||
if name? and name in ['arguments','eval'].concat 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
|
||||
code = assigns.join ', '
|
||||
if o.level < LEVEL_LIST then code else "(#{code})"
|
||||
|
||||
@@ -1041,7 +1087,7 @@ exports.Assign = class Assign extends Base
|
||||
to = +to.compile(o) - +fromRef
|
||||
to += 1 unless exclusive
|
||||
else
|
||||
to = to.compile(o) + ' - ' + fromRef
|
||||
to = to.compile(o, LEVEL_ACCESS) + ' - ' + fromRef
|
||||
to += ' + 1' unless exclusive
|
||||
else
|
||||
to = "9e9"
|
||||
@@ -1059,7 +1105,7 @@ exports.Code = class Code extends Base
|
||||
@params = params or []
|
||||
@body = body or new Block
|
||||
@bound = tag is 'boundfunc'
|
||||
@context = 'this' if @bound
|
||||
@context = '_this' if @bound
|
||||
|
||||
children: ['params', 'body']
|
||||
|
||||
@@ -1074,7 +1120,7 @@ exports.Code = class Code extends Base
|
||||
# a closure.
|
||||
compileNode: (o) ->
|
||||
o.scope = new Scope o.scope, @body, this
|
||||
o.scope.shared = del o, 'sharedScope'
|
||||
o.scope.shared = del(o, 'sharedScope')
|
||||
o.indent += TAB
|
||||
delete o.bare
|
||||
vars = []
|
||||
@@ -1101,6 +1147,11 @@ exports.Code = class Code extends Base
|
||||
@body.expressions.unshift exprs... if exprs.length
|
||||
o.scope.parameter vars[i] = v.compile o for v, i in vars unless splats
|
||||
@body.makeReturn() unless wasEmpty or @noReturn
|
||||
if @bound
|
||||
if o.scope.parent.method?.bound
|
||||
@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
|
||||
@@ -1108,7 +1159,6 @@ exports.Code = class Code extends Base
|
||||
code += "\n#{ @body.compileWithDeclarations o }\n#{@tab}" unless @body.isEmpty()
|
||||
code += '}'
|
||||
return @tab + code if @ctor
|
||||
return utility('bind') + "(#{code}, #{@context})" if @bound
|
||||
if @front or (o.level >= LEVEL_ACCESS) then "(#{code})" else code
|
||||
|
||||
# Short-circuit `traverseChildren` method to prevent it from crossing scope boundaries
|
||||
@@ -1162,6 +1212,8 @@ 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
|
||||
# splats, to a proper array.
|
||||
@@ -1197,9 +1249,12 @@ exports.While = class While extends Base
|
||||
|
||||
isStatement: YES
|
||||
|
||||
makeReturn: ->
|
||||
@returns = yes
|
||||
this
|
||||
makeReturn: (res) ->
|
||||
if res
|
||||
super
|
||||
else
|
||||
@returns = not @jumps loop: yes
|
||||
this
|
||||
|
||||
addBody: (@body) ->
|
||||
this
|
||||
@@ -1221,11 +1276,14 @@ exports.While = class While extends Base
|
||||
if body.isEmpty()
|
||||
body = ''
|
||||
else
|
||||
if o.level > LEVEL_TOP or @returns
|
||||
rvar = o.scope.freeVariable 'results'
|
||||
if @returns
|
||||
body.makeReturn rvar = o.scope.freeVariable 'results'
|
||||
set = "#{@tab}#{rvar} = [];\n"
|
||||
body = Push.wrap rvar, body if body
|
||||
body = Block.wrap [new If @guard, body] if @guard
|
||||
if @guard
|
||||
if body.expressions.length > 1
|
||||
body.expressions.unshift new If (new Parens @guard).invert(), new Literal "continue"
|
||||
else
|
||||
body = Block.wrap [new If @guard, body] if @guard
|
||||
body = "\n#{ body.compile o, LEVEL_TOP }\n#{@tab}"
|
||||
code = set + @tab + "while (#{ @condition.compile o, LEVEL_PAREN }) {#{body}}"
|
||||
if @returns
|
||||
@@ -1308,11 +1366,14 @@ exports.Op = class Op extends Base
|
||||
unfoldSoak: (o) ->
|
||||
@operator in ['++', '--', 'delete'] and unfoldSoak o, this, 'first'
|
||||
|
||||
compileNode: (o) ->
|
||||
compileNode: (o) ->
|
||||
isChain = @isChainable() and @first.isChainable()
|
||||
# In chains, there's no need to wrap bare obj literals in parens,
|
||||
# as the chained expression is wrapped.
|
||||
@first.front = @front unless isChain
|
||||
return @compileUnary o if @isUnary()
|
||||
return @compileChain o if @isChainable() and @first.isChainable()
|
||||
return @compileChain o if isChain
|
||||
return @compileExistence o if @operator is '?'
|
||||
@first.front = @front
|
||||
code = @first.compile(o, LEVEL_OP) + ' ' + @operator + ' ' +
|
||||
@second.compile(o, LEVEL_OP)
|
||||
if o.level <= LEVEL_OP then code else "(#{code})"
|
||||
@@ -1329,7 +1390,7 @@ exports.Op = class Op extends Base
|
||||
"(#{code})"
|
||||
|
||||
compileExistence: (o) ->
|
||||
if @first.isComplex()
|
||||
if @first.isComplex() and o.level > LEVEL_TOP
|
||||
ref = new Literal o.scope.freeVariable 'ref'
|
||||
fst = new Parens new Assign ref, @first
|
||||
else
|
||||
@@ -1340,9 +1401,11 @@ exports.Op = class Op extends Base
|
||||
# Compile a unary **Op**.
|
||||
compileUnary: (o) ->
|
||||
parts = [op = @operator]
|
||||
plusMinus = op in ['+', '-']
|
||||
parts.push ' ' if op in ['new', 'typeof', 'delete'] or
|
||||
op in ['+', '-'] and @first instanceof Op and @first.operator is op
|
||||
@first = new Parens @first if op is 'new' and @first.isStatement o
|
||||
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
|
||||
parts.push @first.compile o, LEVEL_OP
|
||||
parts.reverse() if @flip
|
||||
parts.join ''
|
||||
@@ -1368,11 +1431,11 @@ exports.In = class In extends Base
|
||||
@compileLoopTest o
|
||||
|
||||
compileOrTest: (o) ->
|
||||
return "#{!!@negated}" if @array.base.objects.length is 0
|
||||
[sub, ref] = @object.cache o, LEVEL_OP
|
||||
[cmp, cnj] = if @negated then [' !== ', ' && '] else [' === ', ' || ']
|
||||
tests = for item, i in @array.base.objects
|
||||
(if i then ref else sub) + cmp + item.compile o, LEVEL_OP
|
||||
return 'false' if tests.length is 0
|
||||
(if i then ref else sub) + cmp + item.compile o, LEVEL_ACCESS
|
||||
tests = tests.join cnj
|
||||
if o.level < LEVEL_OP then tests else "(#{tests})"
|
||||
|
||||
@@ -1399,9 +1462,9 @@ exports.Try = class Try extends Base
|
||||
|
||||
jumps: (o) -> @attempt.jumps(o) or @recovery?.jumps(o)
|
||||
|
||||
makeReturn: ->
|
||||
@attempt = @attempt .makeReturn() if @attempt
|
||||
@recovery = @recovery.makeReturn() if @recovery
|
||||
makeReturn: (res) ->
|
||||
@attempt = @attempt .makeReturn res if @attempt
|
||||
@recovery = @recovery.makeReturn res if @recovery
|
||||
this
|
||||
|
||||
# Compilation is more or less as you would expect -- the *finally* clause
|
||||
@@ -1409,16 +1472,19 @@ exports.Try = class Try extends Base
|
||||
compileNode: (o) ->
|
||||
o.indent += TAB
|
||||
errorPart = if @error then " (#{ @error.compile o }) " else ' '
|
||||
tryPart = @attempt.compile o, LEVEL_TOP
|
||||
|
||||
catchPart = if @recovery
|
||||
o.scope.add @error.value, 'param'
|
||||
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 (_e) {}'
|
||||
"""
|
||||
#{@tab}try {
|
||||
#{ @attempt.compile o, LEVEL_TOP }
|
||||
#{@tab}}#{ catchPart or '' }
|
||||
""" + if @ensure then " finally {\n#{ @ensure.compile o, LEVEL_TOP }\n#{@tab}}" else ''
|
||||
' catch (_error) {}'
|
||||
|
||||
ensurePart = if @ensure then " finally {\n#{ @ensure.compile o, LEVEL_TOP }\n#{@tab}}" else ''
|
||||
|
||||
"""#{@tab}try {
|
||||
#{tryPart}
|
||||
#{@tab}}#{ catchPart or '' }#{ensurePart}"""
|
||||
|
||||
#### Throw
|
||||
|
||||
@@ -1450,13 +1516,14 @@ exports.Existence = class Existence extends Base
|
||||
invert: NEGATE
|
||||
|
||||
compileNode: (o) ->
|
||||
@expression.front = @front
|
||||
code = @expression.compile o, LEVEL_OP
|
||||
code = if IDENTIFIER.test(code) and not o.scope.check code
|
||||
[cmp, cnj] = if @negated then ['===', '||'] else ['!==', '&&']
|
||||
"typeof #{code} #{cmp} \"undefined\" #{cnj} #{code} #{cmp} null"
|
||||
if IDENTIFIER.test(code) and not o.scope.check code
|
||||
[cmp, cnj] = if @negated then ['===', '||'] else ['!==', '&&']
|
||||
code = "typeof #{code} #{cmp} \"undefined\" #{cnj} #{code} #{cmp} null"
|
||||
else
|
||||
# do not use strict equality here; it will break existing code
|
||||
"#{code} #{if @negated then '==' else '!='} null"
|
||||
code = "#{code} #{if @negated then '==' else '!='} null"
|
||||
if o.level <= LEVEL_COND then code else "(#{code})"
|
||||
|
||||
#### Parens
|
||||
@@ -1473,7 +1540,6 @@ exports.Parens = class Parens extends Base
|
||||
|
||||
unwrap : -> @body
|
||||
isComplex : -> @body.isComplex()
|
||||
makeReturn: -> @body.makeReturn()
|
||||
|
||||
compileNode: (o) ->
|
||||
expr = @body.unwrap()
|
||||
@@ -1494,7 +1560,7 @@ exports.Parens = class Parens extends Base
|
||||
# Unlike Python array comprehensions, they can be multi-line, and you can pass
|
||||
# the current index of the loop as a second parameter. Unlike Ruby blocks,
|
||||
# you can map and filter in a single pass.
|
||||
exports.For = class For extends Base
|
||||
exports.For = class For extends While
|
||||
constructor: (body, source) ->
|
||||
{@source, @guard, @step, @name, @index} = source
|
||||
@body = Block.wrap [body]
|
||||
@@ -1510,14 +1576,6 @@ exports.For = class For extends Base
|
||||
|
||||
children: ['body', 'source', 'guard', 'step']
|
||||
|
||||
isStatement: YES
|
||||
|
||||
jumps: While::jumps
|
||||
|
||||
makeReturn: ->
|
||||
@returns = yes
|
||||
this
|
||||
|
||||
# Welcome to the hairiest method in all of CoffeeScript. Handles the inner
|
||||
# loop, filtering, stepping, and result saving for array, object, and range
|
||||
# comprehensions. Some of the generated code can be shared in common, and
|
||||
@@ -1558,16 +1616,19 @@ exports.For = class For extends Base
|
||||
if @returns
|
||||
resultPart = "#{@tab}#{rvar} = [];\n"
|
||||
returnResult = "\n#{@tab}return #{rvar};"
|
||||
body = Push.wrap rvar, body
|
||||
body.makeReturn rvar
|
||||
if @guard
|
||||
body = Block.wrap [new If @guard, body]
|
||||
if body.expressions.length > 1
|
||||
body.expressions.unshift new If (new Parens @guard).invert(), new Literal "continue"
|
||||
else
|
||||
body = Block.wrap [new If @guard, body] if @guard
|
||||
if @pattern
|
||||
body.expressions.unshift new Assign @name, new Literal "#{svar}[#{ivar}]"
|
||||
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
|
||||
guardPart = "\n#{idt1}if (!#{utility 'hasProp'}.call(#{svar}, #{ivar})) continue;" if @own
|
||||
body = body.compile merge(o, indent: idt1), LEVEL_TOP
|
||||
body = '\n' + body + '\n' if body
|
||||
"""
|
||||
@@ -1609,9 +1670,10 @@ exports.Switch = class Switch extends Base
|
||||
return block if block.jumps o
|
||||
@otherwise?.jumps o
|
||||
|
||||
makeReturn: ->
|
||||
pair[1].makeReturn() for pair in @cases
|
||||
@otherwise?.makeReturn()
|
||||
makeReturn: (res) ->
|
||||
pair[1].makeReturn res for pair in @cases
|
||||
@otherwise or= new Block [new Literal 'void 0'] if res
|
||||
@otherwise?.makeReturn res
|
||||
this
|
||||
|
||||
compileNode: (o) ->
|
||||
@@ -1669,9 +1731,10 @@ exports.If = class If extends Base
|
||||
compileNode: (o) ->
|
||||
if @isStatement o then @compileStatement o else @compileExpression o
|
||||
|
||||
makeReturn: ->
|
||||
@body and= new Block [@body.makeReturn()]
|
||||
@elseBody and= new Block [@elseBody.makeReturn()]
|
||||
makeReturn: (res) ->
|
||||
@elseBody or= new Block [new Literal 'void 0'] if res
|
||||
@body and= new Block [@body.makeReturn res]
|
||||
@elseBody and= new Block [@elseBody.makeReturn res]
|
||||
this
|
||||
|
||||
ensureBlock: (node) ->
|
||||
@@ -1688,9 +1751,18 @@ exports.If = class If extends Base
|
||||
|
||||
cond = @condition.compile o, LEVEL_PAREN
|
||||
o.indent += TAB
|
||||
body = @ensureBlock(@body).compile o
|
||||
body = "\n#{body}\n#{@tab}" if body
|
||||
ifPart = "if (#{cond}) {#{body}}"
|
||||
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 = @tab + ifPart unless child
|
||||
return ifPart unless @elseBody
|
||||
ifPart + ' else ' + if @isChain
|
||||
@@ -1716,15 +1788,6 @@ exports.If = class If extends Base
|
||||
# Faux-nodes are never created by the grammar, but are used during code
|
||||
# generation to generate other combinations of nodes.
|
||||
|
||||
#### Push
|
||||
|
||||
# The **Push** creates the tree for `array.push(value)`,
|
||||
# which is helpful for recording the result arrays from comprehensions.
|
||||
Push =
|
||||
wrap: (name, exps) ->
|
||||
return exps if exps.isEmpty() or last(exps.expressions).jumps()
|
||||
exps.push new Call new Value(new Literal(name), [new Access new Literal 'push']), [exps.pop()]
|
||||
|
||||
#### Closure
|
||||
|
||||
# A faux-node used to wrap an expressions body in a closure.
|
||||
@@ -1748,6 +1811,7 @@ 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)
|
||||
@@ -1766,35 +1830,23 @@ 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 (__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;
|
||||
}
|
||||
'''
|
||||
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; }
|
||||
"""
|
||||
|
||||
# Create a function bound to the current value of "this".
|
||||
bind: '''
|
||||
bind: -> '''
|
||||
function(fn, me){ return function(){ return fn.apply(me, arguments); }; }
|
||||
'''
|
||||
|
||||
# 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 (this[i] === item) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
'''
|
||||
indexOf: -> """
|
||||
Array.prototype.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: -> 'Object.prototype.hasOwnProperty'
|
||||
slice : -> 'Array.prototype.slice'
|
||||
|
||||
# Levels indicate a node's position in the AST. Useful for knowing if
|
||||
# parens are necessary or superfluous.
|
||||
@@ -1836,8 +1888,9 @@ IS_STRING = /^['"]/
|
||||
# Helper for ensuring that utility functions are assigned at the top level.
|
||||
utility = (name) ->
|
||||
ref = "__#{name}"
|
||||
Scope.root.assign ref, UTILITIES[name]
|
||||
Scope.root.assign ref, UTILITIES[name]()
|
||||
ref
|
||||
|
||||
multident = (code, tab) ->
|
||||
code.replace /\n/g, '$&' + tab
|
||||
code = code.replace /\n/g, '$&' + tab
|
||||
code.replace /\s+$/, ''
|
||||
|
||||
@@ -25,10 +25,13 @@ exports.OptionParser = class OptionParser
|
||||
# for interpreting the options object.
|
||||
parse: (args) ->
|
||||
options = arguments: [], literals: []
|
||||
args = normalizeArguments args
|
||||
originalArgs = args
|
||||
args = normalizeArguments args
|
||||
for arg, i in args
|
||||
if arg is '--'
|
||||
options.literals = args[(i + 1)..]
|
||||
pos = originalArgs.indexOf '--'
|
||||
options.arguments = [originalArgs[1 + pos]]
|
||||
options.literals = originalArgs[(2 + pos)..]
|
||||
break
|
||||
isOption = !!(arg.match(LONG_FLAG) or arg.match(SHORT_FLAG))
|
||||
matchedRule = no
|
||||
@@ -40,7 +43,7 @@ exports.OptionParser = class OptionParser
|
||||
break
|
||||
throw new Error "unrecognized option: #{arg}" if isOption and not matchedRule
|
||||
if not isOption
|
||||
options.arguments = args.slice i
|
||||
options.arguments = originalArgs[(originalArgs.indexOf arg)..]
|
||||
break
|
||||
options
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user