diff --git a/documentation/docs/cake.html b/documentation/docs/cake.html index 1c909799..a48a30f6 100644 --- a/documentation/docs/cake.html +++ b/documentation/docs/cake.html @@ -4,10 +4,10 @@ for CoffeeScript. You define tasks with names and descriptions in a Cakefile, and can call them from the command line, or invoke them from other tasks.
Running cake
with no arguments will print out a list of all the tasks in the
-current directory's Cakefile.
External dependencies.
fs: require 'fs'
-path: require 'path'
-coffee: require 'coffee-script'
-optparse: require 'optparse'
Keep track of the list of defined tasks, the accepted options, and so on.
tasks: {}
+current directory's Cakefile.
External dependencies.
fs: require 'fs'
+path: require 'path'
+optparse: require 'optparse'
+CoffeeScript: require 'coffee-script'
Keep track of the list of defined tasks, the accepted options, and so on.
tasks: {}
options: {}
switches: []
oparse: null
Mixin the top-level Cake functions for Cakefiles to use directly.
process.mixin {
Define a Cake task with a short name, a sentence description, @@ -25,7 +25,7 @@ If no tasks are passed, print the help screen.
text/coffeescript
tags.
parser: exports.parser
this.exports: this.CoffeeScript: {} The current CoffeeScript version number.
exports.VERSION: '0.5.4'
Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison compiler.
exports.compile: (code, options) ->
- (parser.parse lexer.tokenize code).compile options
Tokenize a string of CoffeeScript code, and return the array of tokens.
exports.tokens: (code) ->
+ try
+ (parser.parse lexer.tokenize code).compile options
+ catch err
+ err.message: "In ${options.source}, ${err.message}" if options.source
+ throw err
Tokenize a string of CoffeeScript code, and return the array of tokens.
exports.tokens: (code) ->
lexer.tokenize code
Tokenize and parse a string of CoffeeScript code, and return the AST. You can
then compile it by calling .compile()
on the root, or traverse it by using
.traverse()
with a callback.
exports.nodes: (code) ->
- parser.parse lexer.tokenize code
The real Lexer produces a generic stream of tokens. This object provides a + parser.parse lexer.tokenize code
Compile and execute a string of CoffeeScript (on the server), correctly
+setting __filename
, __dirname
, and relative require()
.
exports.run: (code, options) ->
+ module.filename: __filename: options.source
+ __dirname: path.dirname __filename
+ eval exports.compile code, options
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".
parser.lexer: {
lex: ->
@@ -32,7 +40,7 @@ directly as a "Jison lexer".
Activate CoffeeScript in the browser by having it compile and evaluate +}
Activate CoffeeScript in the browser by having it compile and evaluate
all script tags with a content-type of text/coffeescript
. This happens
on page load. Unfortunately, the text contents of remote scripts cannot be
accessed from the browser, so only inline script tags will work.
if document? and document.getElementsByTagName
diff --git a/documentation/docs/command.html b/documentation/docs/command.html
index 4f657a7d..e4bcd721 100644
--- a/documentation/docs/command.html
+++ b/documentation/docs/command.html
@@ -34,7 +34,7 @@ Many flags cause us to divert before compiling anything. Flags passed after
return version() if options.version
return require 'repl' if options.interactive
return compile_stdio() if options.stdio
- return compile_script 'unknown', sources[0] if options.eval
+ return compile_script 'console', sources[0] if options.eval
return usage() unless sources.length
separator: sources.indexOf '--'
flags: []
@@ -54,19 +54,16 @@ requested options. Both compile_scripts and watch_scripts share this method
in common. If evaluating the script directly sets __filename
, __dirname
and module.filename
to be correct relative to the script's path.
compile_script: (source, code) ->
o: options
+ code_opts: compile_options source
try
if o.tokens then print_tokens CoffeeScript.tokens code
else if o.nodes then puts CoffeeScript.nodes(code).toString()
+ else if o.run then CoffeeScript.run code, code_opts
else
- js: CoffeeScript.compile code, compile_options()
+ js: CoffeeScript.compile code, code_opts
if o.compile then write_js source, js
else if o.lint then lint js
else if o.print or o.eval then print js
- else
- __filename: source
- __dirname: path.dirname source
- module.filename: source
- eval js
catch err
if o.watch then puts err.message else throw err
Attach the appropriate listeners to compile scripts incoming over stdin, and write them back to stdout.
compile_stdio: ->
@@ -75,7 +72,7 @@ and write them back to stdout.
Watch a list of source CoffeeScript files using fs.watchFile
, recompiling
+ process.stdio.write CoffeeScript.compile code, compile_options('stdio')
Watch a list of source CoffeeScript files using fs.watchFile
, recompiling
them every time the files are updated. May be used in combination with other
options, such as --lint
or --print
.
watch_scripts: ->
watch: (source) ->
@@ -103,9 +100,12 @@ any errors or warnings that arise.
Use the OptionParser module to extract all options from
process.argv
that are specified in SWITCHES
.
parse_options: ->
option_parser: new optparse.OptionParser SWITCHES, BANNER
- options: option_parser.parse(process.argv)
- sources: options.arguments[2...options.arguments.length]
The compile-time options to pass to the CoffeeScript compiler.
compile_options: ->
- if options['no-wrap'] then {no_wrap: true} else {}
Print the --help
usage message and exit.
usage: ->
+ o: options: option_parser.parse(process.argv)
+ options.run: not (o.compile or o.print or o.lint or o.eval)
+ sources: options.arguments[2...options.arguments.length]
The compile-time options to pass to the CoffeeScript compiler.
compile_options: (source) ->
+ o: {source: source}
+ o['no-wrap']: options['no-wrap']
+ o
Print the --help
usage message and exit.
usage: ->
puts option_parser.help()
process.exit 0
Print the --version
message and exit.
version: ->
puts "CoffeeScript version ${CoffeeScript.VERSION}"
diff --git a/documentation/docs/lexer.html b/documentation/docs/lexer.html
index 2fec663c..044c5b7b 100644
--- a/documentation/docs/lexer.html
+++ b/documentation/docs/lexer.html
@@ -317,7 +317,7 @@ to avoid having a JavaScript error at runtime.
JS_FORBIDDEN: JS_KEYWORDS.concat RESERVED
Token matching regexes.
IDENTIFIER : /^([a-zA-Z$_](\w|\$)*)/
NUMBER : /^(\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?(e[+\-]?[0-9]+)?)))\b/i
HEREDOC : /^("{6}|'{6}|"{3}\n?([\s\S]*?)\n?([ \t]*)"{3}|'{3}\n?([\s\S]*?)\n?([ \t]*)'{3})/
-INTERPOLATION : /^\$([a-zA-Z_@]\w*)/
+INTERPOLATION : /^\$([a-zA-Z_@]\w*(\.\w+)*)/
OPERATOR : /^([+\*&|\/\-%=<>:!?]+)/
WHITESPACE : /^([ \t]+)/
COMMENT : /^(((\n?[ \t]*)?#[^\n]*)+)/
diff --git a/documentation/docs/nodes.html b/documentation/docs/nodes.html
index e316e6cb..7c5441f3 100644
--- a/documentation/docs/nodes.html
+++ b/documentation/docs/nodes.html
@@ -228,8 +228,8 @@ of the current function.
If you call a function with a splat, it's converted into a JavaScript + "${methname}.__superClass__.constructor" + "${meth}.call(this${ if args.length then ', ' else '' }$args)"
If you call a function with a splat, it's converted into a JavaScript
.apply()
call to allow the variable-length arguments.
compile_splat: (o) ->
meth: @variable.compile o
obj: @variable.source or 'this'
@@ -241,7 +241,7 @@ of the current function.
Node to extend an object's prototype with an ancestor object. + "$@prefix${meth}.apply($obj, ${ args.join('') })"
Node to extend an object's prototype with an ancestor object.
After goog.inherits
from the
Closure Library.
exports.ExtendsNode: class ExtendsNode extends BaseNode
type: 'Extends'
@@ -353,7 +353,7 @@ commas affixed to comments.
objects: for obj, i in @objects
code: obj.compile(o)
if obj instanceof CommentNode
- "\n$code\n${o.indent}"
+ "\n$code\n$o.indent"
else if i is @objects.length - 1
code
else
@@ -484,7 +484,7 @@ for details.
A function definition. This is the only node that creates a new Scope. + "${name}.splice.apply($name, [$from, $to].concat($val))"
A function definition. This is the only node that creates a new Scope. When for the purposes of walking the contents of a function body, the CodeNode has no children -- they're within the inner scope.
exports.CodeNode: class CodeNode extends BaseNode
type: 'Code'
@@ -530,7 +530,7 @@ the function -- the parameters and body of expressions.
A splat, either as a parameter to a function, an argument to a call, -or in a destructuring assignment.
exports.SplatNode: class SplatNode extends BaseNode
+or as part of a destructuring assignment.
exports.SplatNode: class SplatNode extends BaseNode
type: 'Splat'
constructor: (name) ->
@@ -538,16 +538,15 @@ or in a destructuring assignment.
Compiling a parameter splat means recovering the parameters that succeed +the splat in the parameter list, by slicing the arguments object.
compile_param: (o) ->
name: @name.compile(o)
o.scope.find name
- "$name = Array.prototype.slice.call(arguments, $@index)"
-
- compile_value: (o, name, index) ->
- "Array.prototype.slice.call($name, $index)"
A while loop, the only sort of low-level loop exposed by CoffeeScript. From -it, all other loops can be manufactured.
exports.WhileNode: class WhileNode extends BaseNode
+ "$name = Array.prototype.slice.call(arguments, $@index)"
A compiling a splat as a destructuring assignment means slicing arguments +from the right-hand-side's corresponding array.
compile_value: (o, name, index) ->
+ "Array.prototype.slice.call($name, $index)"
A while loop, the only sort of low-level loop exposed by CoffeeScript. From +it, all other loops can be manufactured. Useful in cases where you need more +flexibility or more speed than a comprehension can provide.
exports.WhileNode: class WhileNode extends BaseNode
type: 'While'
constructor: (condition, opts) ->
@@ -559,9 +558,9 @@ it, all other loops can be manufactured.
The main difference from a JavaScript while is that the CoffeeScript +while can be used as a part of a larger expression -- while loops may +return an array containing the computed result of each iteration.
compile_node: (o) ->
returns: del(o, 'returns')
top: del(o, 'top') and not returns
o.indent: @idt(1)
@@ -578,11 +577,9 @@ it, all other loops can be manufactured.
Simple Arithmetic and logical operations. Performs some conversion from +statement WhileNode
Simple Arithmetic and logical operations. Performs some conversion from CoffeeScript operations into their JavaScript equivalents.
exports.OpNode: class OpNode extends BaseNode
- type: 'Op'
-
- CONVERSIONS: {
+ type: 'Op'
The map of conversions from CoffeeScript to JavaScript symbols.
CONVERSIONS: {
'==': '==='
'!=': '!=='
'and': '&&'
@@ -590,11 +587,8 @@ CoffeeScript operations into their JavaScript equivalents.
The list of operators for which we perform +Python-style comparison chaining.
CHAINABLE: ['<', '>', '>=', '<=', '===', '!==']
Our assignment operators that have no JavaScript equivalent.
ASSIGNMENT: ['||=', '&&=', '?=']
Operators must come before their operands with a space.
PREFIX_OPERATORS: ['typeof', 'delete']
constructor: (operator, first, second, flip) ->
@type += ' ' + operator
@@ -614,14 +608,14 @@ CoffeeScript operations into their JavaScript equivalents.
Mimic Python's chained comparisons. See: -http://docs.python.org/reference/expressions.html#notin
compile_chain: (o) ->
+ [@first.compile(o), @operator, @second.compile(o)].join ' '
Mimic Python's chained comparisons when multiple comparison operators are
+used sequentially. For example: 50 < 65 > 10
compile_chain: (o) ->
shared: @first.unwrap().second
[@first.second, shared]: shared.compile_reference(o) if shared instanceof CallNode
[first, second, shared]: [@first.compile(o), @second.compile(o), shared.compile(o)]
- "($first) && ($shared $@operator $second)"
-
- compile_assignment: (o) ->
+ "($first) && ($shared $@operator $second)"
When compiling a conditional assignment, take care to ensure that the +operands are only evaluated once, even though we have to reference them +more than once.
compile_assignment: (o) ->
[first, second]: [@first.compile(o), @second.compile(o)]
o.scope.find(first) if first.match(IDENTIFIER)
return "$first = ${ ExistenceNode.compile_test(o, @first) } ? $first : $second" if @operator is '?='
@@ -636,7 +630,7 @@ CoffeeScript operations into their JavaScript equivalents.
A try/catch/finally block.
exports.TryNode: class TryNode extends BaseNode
+ parts.join('')
A try/catch/finally block.
exports.TryNode: class TryNode extends BaseNode
type: 'Try'
constructor: (attempt, error, recovery, ensure) ->
@@ -653,7 +647,7 @@ CoffeeScript operations into their JavaScript equivalents.
Throw an exception.
exports.ThrowNode: class ThrowNode extends BaseNode
+statement TryNode
Throw an exception.
exports.ThrowNode: class ThrowNode extends BaseNode
type: 'Throw'
constructor: (expression) ->
@@ -662,7 +656,7 @@ CoffeeScript operations into their JavaScript equivalents.
Check an expression for existence (meaning not null or undefined).
exports.ExistenceNode: class ExistenceNode extends BaseNode
+statement ThrowNode, true
Check an expression for existence (meaning not null or undefined).
exports.ExistenceNode: class ExistenceNode extends BaseNode
type: 'Existence'
constructor: (expression) ->
@@ -676,7 +670,7 @@ CoffeeScript operations into their JavaScript equivalents.
An extra set of parentheses, specified explicitly in the source.
exports.ParentheticalNode: class ParentheticalNode extends BaseNode
+ "(typeof $first !== \"undefined\" && $second !== null)"
An extra set of parentheses, specified explicitly in the source.
exports.ParentheticalNode: class ParentheticalNode extends BaseNode
type: 'Paren'
constructor: (expression) ->
@@ -690,7 +684,7 @@ CoffeeScript operations into their JavaScript equivalents.
The replacement for the for loop is an array comprehension (that compiles) + "($code)"
The replacement for the for loop is an array comprehension (that compiles) into a for loop. Also acts as an expression, able to return the result of the comprehenion. Unlike Python array comprehensions, it's able to pass the current index of the loop as a second parameter.
exports.ForNode: class ForNode extends BaseNode
@@ -737,7 +731,7 @@ the current index of the loop as a second parameter.
If/else statements. Switch/whens get compiled into these. Acts as an +statement ForNode
If/else statements. Switch/whens get compiled into these. Acts as an expression by pushing down requested returns to the expression bodies. Single-expression IfNodes are compiled into ternary operators if possible, because ternaries are first-class returnable assignable expressions.
exports.IfNode: class IfNode extends BaseNode
@@ -779,9 +773,9 @@ because ternaries are first-class returnable assignable expressions.
force_statement: ->
@tags.statement: true
- this
Tag a chain of IfNodes with their switch condition for equality.
rewrite_condition: (expression) ->
+ this
Tag a chain of IfNodes with their switch condition for equality.
rewrite_condition: (expression) ->
@switcher: expression
- this
Rewrite a chain of IfNodes with their switch condition for equality.
rewrite_switch: (o) ->
+ this
Rewrite a chain of IfNodes with their switch condition for equality.
rewrite_switch: (o) ->
assigner: @switcher
if not (@switcher.unwrap() instanceof LiteralNode)
variable: literal(o.scope.free_variable())
@@ -793,14 +787,14 @@ because ternaries are first-class returnable assignable expressions.
else
new OpNode('is', assigner, @condition)
@else_body.rewrite_condition(@switcher) if @is_chain()
- this
Rewrite a chain of IfNodes to add a default case as the final else.
add_else: (exprs, statement) ->
+ this
Rewrite a chain of IfNodes to add a default case as the final else.
add_else: (exprs, statement) ->
if @is_chain()
@else_body.add_else exprs, statement
else
exprs: exprs.unwrap() unless statement
@children.push @else_body: exprs
- this
If the else_body is an IfNode itself, then we've got an if-else chain.
is_chain: ->
- @chain ||= @else_body and @else_body instanceof IfNode
The IfNode only compiles into a statement if either of the bodies needs + this
If the else_body is an IfNode itself, then we've got an if-else chain.
is_chain: ->
+ @chain ||= @else_body and @else_body instanceof IfNode
The IfNode only compiles into a statement if either of the bodies needs to be a statement.
is_statement: ->
@statement ||= !!(@comment or @tags.statement or @body.is_statement() or (@else_body and @else_body.is_statement()))
@@ -808,7 +802,7 @@ to be a statement.
Compile the IfNode as a regular if-else statement. Flattened chains + if @is_statement() then @compile_statement(o) else @compile_ternary(o)
Compile the IfNode as a regular if-else statement. Flattened chains force sub-else bodies into statement form.
compile_statement: (o) ->
@rewrite_switch(o) if @switcher
child: del o, 'chain_child'
@@ -826,22 +820,22 @@ force sub-else bodies into statement form.
Compile the IfNode into a ternary operator.
compile_ternary: (o) ->
+ "$if_part$else_part"
Compile the IfNode into a ternary operator.
compile_ternary: (o) ->
if_part: @condition.compile(o) + ' ? ' + @body.compile(o)
else_part: if @else_body then @else_body.compile(o) else 'null'
- "$if_part : $else_part"
Tabs are two spaces for pretty printing.
TAB: ' '
-TRAILING_WHITESPACE: /\s+$/gm
Keep the identifier regex in sync with the Lexer.
IDENTIFIER: /^[a-zA-Z$_](\w|\$)*$/
Merge objects.
merge: (options, overrides) ->
+ "$if_part : $else_part"
Tabs are two spaces for pretty printing.
TAB: ' '
+TRAILING_WHITESPACE: /\s+$/gm
Keep the identifier regex in sync with the Lexer.
IDENTIFIER: /^[a-zA-Z$_](\w|\$)*$/
Merge objects.
merge: (options, overrides) ->
fresh: {}
(fresh[key]: val) for key, val of options
(fresh[key]: val) for key, val of overrides if overrides
- fresh
Trim out all falsy values from an array.
compact: (array) -> item for item in array when item
Return a completely flattened version of an array.
flatten: (array) ->
+ fresh
Trim out all falsy values from an array.
compact: (array) -> item for item in array when item
Return a completely flattened version of an array.
flatten: (array) ->
memo: []
for item in array
if item instanceof Array then memo: memo.concat(item) else memo.push(item)
- memo
Delete a key from an object, returning the value.
del: (obj, key) ->
+ memo
Delete a key from an object, returning the value.
del: (obj, key) ->
val: obj[key]
delete obj[key]
- val
Quickie helper for a generated LiteralNode.
literal: (name) ->
+ val
Quickie helper for a generated LiteralNode.
literal: (name) ->
new LiteralNode(name)