diff --git a/documentation/docs/grammar.html b/documentation/docs/grammar.html index 5d79eea5..5728ab41 100644 --- a/documentation/docs/grammar.html +++ b/documentation/docs/grammar.html @@ -96,6 +96,7 @@ through and printed to JavaScript.

  AssignObj: [
     o "Identifier ASSIGN Expression",           -> new AssignNode new ValueNode($1), $3, 'object'
     o "AlphaNumeric ASSIGN Expression",         -> new AssignNode new ValueNode($1), $3, 'object'
+    o "ThisProperty ASSIGN Expression",         -> new AssignNode new ValueNode($1), $3, 'this'
     o "Comment"
   ]
#

A return statement from a function body.

  Return: [
     o "RETURN Expression",                      -> new ReturnNode $2
@@ -125,14 +126,12 @@ that hoovers up the remaining arguments.

o "Param . . .", -> new SplatNode $1 ]
#

A splat that occurs outside of a parameter list.

  Splat: [
     o "Expression . . .",                       -> new SplatNode $1
-  ]
-  
#

Variables and properties that can be assigned to.

  SimpleAssignable: [
+  ]
#

Variables and properties that can be assigned to.

  SimpleAssignable: [
     o "Identifier",                             -> new ValueNode $1
     o "Value Accessor",                         -> $1.push $2
     o "Invocation Accessor",                    -> new ValueNode $1, [$2]
     o "ThisProperty"
-  ]
-  
#

Everything that can be assigned to.

  Assignable: [
+  ]
#

Everything that can be assigned to.

  Assignable: [
     o "SimpleAssignable"
     o "Array",                                  -> new ValueNode $1
     o "Object",                                 -> new ValueNode $1
@@ -198,8 +197,7 @@ object.

]
#

A reference to the this current object.

  This: [
     o "THIS",                                   -> new ValueNode new LiteralNode 'this'
     o "@",                                      -> new ValueNode new LiteralNode 'this'
-  ]
-  
#

A reference to a property on this.

  ThisProperty: [
+  ]
#

A reference to a property on this.

  ThisProperty: [
     o "@ Identifier",                           -> new ValueNode new LiteralNode('this'), [new AccessorNode($2)]
   ]
#

The CoffeeScript range literal.

  Range: [
     o "[ Expression . . Expression ]",          -> new RangeNode $2, $5
diff --git a/documentation/docs/lexer.html b/documentation/docs/lexer.html
index 47b1c3f6..c839798d 100644
--- a/documentation/docs/lexer.html
+++ b/documentation/docs/lexer.html
@@ -310,7 +310,7 @@ match if successful, and false otherwise.

if m then m[index] else false
#

Are we in the midst of an unfinished expression?

  unfinished: ->
     prev: @prev(2)
     @value() and @value().match and @value().match(NO_NEWLINE) and
-      prev and (prev[0] isnt '.') and not @value().match(CODE)
#

There are no exensions to the core lexer by default.

Lexer.extensions: []
#

Constants

#

Keywords that CoffeeScript shares in common with JavaScript.

JS_KEYWORDS: [
+      prev and (prev[0] isnt '.') and not @value().match(CODE)
#

Lexer Properties

#

There are no exensions to the core lexer by default.

  @extensions: []
#

Constants

#

Keywords that CoffeeScript shares in common with JavaScript.

JS_KEYWORDS: [
   "if", "else",
   "true", "false",
   "new", "return",
@@ -320,21 +320,20 @@ match if successful, and false otherwise.

"delete", "instanceof", "typeof", "switch", "super", "extends", "class", "this", "null" -]
#

CoffeeScript-only keywords, which we're more relaxed about allowing. They can't +]

#

CoffeeScript-only keywords, which we're more relaxed about allowing. They can't be used standalone, but you can reference them as an attached property.

COFFEE_ALIASES:  ["and", "or", "is", "isnt", "not"]
 COFFEE_KEYWORDS: COFFEE_ALIASES.concat [
   "then", "unless",
   "yes", "no", "on", "off",
   "of", "by", "where", "when"
-]
#

The combined list of keywords is the superset that gets passed verbatim to -the parser.

KEYWORDS: JS_KEYWORDS.concat COFFEE_KEYWORDS
#

The list of keywords that are reserved by JavaScript, but not used, or are +]

#

The combined list of keywords is the superset that gets passed verbatim to +the parser.

KEYWORDS: JS_KEYWORDS.concat COFFEE_KEYWORDS
#

The list of keywords that are reserved by JavaScript, but not used, or are used by CoffeeScript internally. We throw an error when these are encountered, to avoid having a JavaScript error at runtime.

RESERVED: [
   "case", "default", "do", "function", "var", "void", "with"
-  "const", "let", "debugger", "enum", "export", "import", "native",
-  "__extends", "__hasProp"
-]
#

The superset of both JavaScript keywords and reserved words, none of which may -be used as identifiers or properties.

JS_FORBIDDEN: JS_KEYWORDS.concat RESERVED
#

Token matching regexes.

IDENTIFIER    : /^([a-zA-Z\$_](\w|\$)*)/
+  "const", "let", "debugger", "enum", "export", "import", "native"
+]
#

The superset of both JavaScript keywords and reserved words, none of which may +be used as identifiers or properties.

JS_FORBIDDEN: JS_KEYWORDS.concat RESERVED
#

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*(\.\w+)*)/
@@ -345,27 +344,27 @@ be used as identifiers or properties.

MULTI_DENT : /^((\n([ \t]*))+)(\.)?/ LAST_DENTS : /\n([ \t]*)/g LAST_DENT : /\n([ \t]*)/ -ASSIGNMENT : /^(:|=)$/
#

Regex-matching-regexes.

REGEX_START        : /^\/[^\/ ]/
+ASSIGNMENT    : /^(:|=)$/
#

Regex-matching-regexes.

REGEX_START        : /^\/[^\/ ]/
 REGEX_INTERPOLATION: /([^\\]\$[a-zA-Z_@]|[^\\]\$\{.*[^\\]\})/
 REGEX_FLAGS        : /^[imgy]{0,4}/
-REGEX_ESCAPE       : /\\[^\$]/g
#

Token cleaning regexes.

JS_CLEANER      : /(^`|`$)/g
+REGEX_ESCAPE       : /\\[^\$]/g
#

Token cleaning regexes.

JS_CLEANER      : /(^`|`$)/g
 MULTILINER      : /\n/g
 STRING_NEWLINES : /\n[ \t]*/g
 COMMENT_CLEANER : /(^[ \t]*#|\n[ \t]*$)/mg
 NO_NEWLINE      : /^([+\*&|\/\-%=<>:!.\\][<>=&|]*|and|or|is|isnt|not|delete|typeof|instanceof)$/
-HEREDOC_INDENT  : /^[ \t]+/mg
#

Tokens which a regular expression will never immediately follow, but which +HEREDOC_INDENT : /^[ \t]+/mg

#

Tokens which a regular expression will never immediately follow, but which a division operator might.

See: http://www.mozilla.org/js/language/js20-2002-04/rationale/syntax.html#regular-expressions

Our list is shorter, due to sans-parentheses method calls.

NOT_REGEX: [
   'NUMBER', 'REGEX', '++', '--', 'FALSE', 'NULL', 'TRUE'
-]
#

Tokens which could legitimately be invoked or indexed. A opening +]

#

Tokens which could legitimately be invoked or indexed. A opening parentheses or bracket following these tokens will be recorded as the start -of a function invocation or indexing operation.

CALLABLE: ['IDENTIFIER', 'SUPER', ')', ']', '}', 'STRING', '@']
#

Tokens that indicate an access -- keywords immediately following will be -treated as identifiers.

ACCESSORS: ['PROPERTY_ACCESS', 'PROTOTYPE_ACCESS', 'SOAK_ACCESS', '@']
#

Tokens that, when immediately preceding a WHEN, indicate that the WHEN +of a function invocation or indexing operation.

CALLABLE: ['IDENTIFIER', 'SUPER', ')', ']', '}', 'STRING', '@']
#

Tokens that indicate an access -- keywords immediately following will be +treated as identifiers.

ACCESSORS: ['PROPERTY_ACCESS', 'PROTOTYPE_ACCESS', 'SOAK_ACCESS', '@']
#

Tokens that, when immediately preceding a WHEN, indicate that the WHEN occurs at the start of a line. We disambiguate these from trailing whens to -avoid an ambiguity in the grammar.

LINE_BREAK: ['INDENT', 'OUTDENT', 'TERMINATOR']
#

Half-assignments...

HALF_ASSIGNMENTS: ['-', '+', '/', '*', '%', '||', '&&', '?']
#

Conversions from CoffeeScript operators into JavaScript ones.

CONVERSIONS: {
+avoid an ambiguity in the grammar.

LINE_BREAK: ['INDENT', 'OUTDENT', 'TERMINATOR']
#

Half-assignments...

HALF_ASSIGNMENTS: ['-', '+', '/', '*', '%', '||', '&&', '?']
#

Conversions from CoffeeScript operators into JavaScript ones.

CONVERSIONS: {
   'and':  '&&'
   'or':   '||'
   'is':   '=='
diff --git a/documentation/docs/nodes.html b/documentation/docs/nodes.html
index 4d5cecca..a71e2295 100644
--- a/documentation/docs/nodes.html
+++ b/documentation/docs/nodes.html
@@ -262,8 +262,6 @@ returning the bound function. After ECMAScript 5, Prototype.js, and
 Underscore's bind functions.

exports.CurryNode: class CurryNode extends CallNode
   type: 'Curry'
 
-  body: 'func.apply(obj, args.concat(Array.prototype.slice.call(arguments, 0)))'
-
   constructor: (meth, args) ->
     @children:  flatten [@meth: meth, @context: args[0], @args: (args.slice(1) or [])]
     @compile_splat_arguments: SplatNode.compile_mixed_array <- @, @args
@@ -274,30 +272,17 @@ Underscore's bind functions.

(new ArrayNode(@args)).compile o compile_node: (o) -> - body: Expressions.wrap([literal @body]) - curried: new CodeNode([], body) - curry: new CodeNode([literal('func'), literal('obj'), literal('args')], Expressions.wrap([curried])) - (new ParentheticalNode(new CallNode(curry, [@meth, @context, literal(@arguments(o))]))).compile o
#

ExtendsNode

#

Node to extend an object's prototype with an ancestor object. + utility 'slice' + ref: new ValueNode literal utility 'bind' + (new CallNode(ref, [@meth, @context, literal(@arguments(o))])).compile o

#

ExtendsNode

#

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'
 
-  code: '''
-        function(child, parent) {
-            var ctor = function(){ };
-            ctor.prototype = parent.prototype;
-            child.__superClass__ = parent.prototype;
-            child.prototype = new ctor();
-            child.prototype.constructor = child;
-          }
-        '''
-
   constructor: (child, parent) ->
     @children:  [@child: child, @parent: parent]
#

Hooks one constructor into another's prototype chain.

  compile_node: (o) ->
-    o.scope.assign('__extends', @code, true)
-    ref:  new ValueNode literal('__extends')
-    call: new CallNode ref, [@child, @parent]
-    call.compile(o)
#

AccessorNode

#

A . accessor into a property of a value, or the :: shorthand for + ref: new ValueNode literal utility 'extends' + (new CallNode ref, [@child, @parent]).compile o

#

AccessorNode

#

A . accessor into a property of a value, or the :: shorthand for an accessor into the object's prototype.

exports.AccessorNode: class AccessorNode extends BaseNode
   type: 'Accessor'
 
@@ -392,7 +377,7 @@ commas affixed to comments.

for obj, i in @objects code: obj.compile(o) if obj instanceof SplatNode - return @compile_splat_literal(@objects, o) + return @compile_splat_literal @objects, o else if obj instanceof CommentNode objects.push "\n$code\n$o.indent" else if i is @objects.length - 1 @@ -418,14 +403,16 @@ constructor, property assignments, and inheritance getting built out below.

o.top: true for prop in @properties - if prop.variable and prop.variable.base.value is 'constructor' + pvar: prop.variable + if pvar and pvar.base.value is 'constructor' func: prop.value func.body.push(new ReturnNode(literal('this'))) constructor: new AssignNode(@variable, func) else - if prop.variable - val: new ValueNode(@variable, [new AccessorNode(prop.variable, 'prototype')]) - prop: new AssignNode(val, prop.value) + if pvar + access: if prop.context is 'this' then pvar.base.properties[0] else new AccessorNode(pvar, 'prototype') + val: new ValueNode(@variable, [access]) + prop: new AssignNode(val, prop.value) props.push prop if not constructor @@ -508,7 +495,7 @@ for details.

< code: assigns.join("\n") code
#

Compile the assignment from an array splice literal, using JavaScript's Array#splice method.

  compile_splice: (o) ->
-    name:   @variable.compile(merge(o, {only_first: true}))
+    name:   @variable.compile merge o, {only_first: true}
     l:      @variable.properties.length
     range:  @variable.properties[l - 1].range
     plus:   if range.exclusive then '' else ' + 1'
@@ -557,8 +544,9 @@ a closure.

func: "function${ if @bound then '' else name_part }(${ params.join(', ') }) {$code${@idt(if @bound then 1 else 0)}}" func: "($func)" if top and not @bound return func unless @bound - inner: "(function$name_part() {\n${@idt(2)}return __func.apply(__this, arguments);\n${@idt(1)}});" - "(function(__this) {\n${@idt(1)}var __func = $func;\n${@idt(1)}return $inner\n$@tab})(this)" + utility 'slice' + ref: new ValueNode literal utility 'bind' + (new CallNode ref, [literal(func), literal('this')]).compile o top_sensitive: -> true
#

When traversing (for printing or inspecting), return the real children of @@ -587,28 +575,28 @@ the splat in the parameter list, by slicing the arguments object.

for trailing in @trailings o.scope.assign(trailing.compile(o), "arguments[arguments.length - $@trailings.length + $i]") i: + 1 - "$name = Array.prototype.slice.call(arguments, $@index, arguments.length - ${@trailings.length})"
#

A compiling a splat as a destructuring assignment means slicing arguments + "$name = ${utility('slice')}.call(arguments, $@index, arguments.length - ${@trailings.length})"

#

A compiling a splat as a destructuring assignment means slicing arguments from the right-hand-side's corresponding array.

  compile_value: (o, name, index, trailings) ->
-    if trailings? then "Array.prototype.slice.call($name, $index, ${name}.length - $trailings)" \
-    else "Array.prototype.slice.call($name, $index)"
#

Utility function that converts arbitrary number of elements, mixed with -splats, to a proper array

SplatNode.compile_mixed_array: (list, o) ->
-  args: []
-  i: 0
-  for arg in list
-    code: arg.compile o
-    if not (arg instanceof SplatNode)
-      prev: args[i - 1]
-      if i is 1 and prev.substr(0, 1) is '[' and prev.substr(prev.length - 1, 1) is ']'
-        args[i - 1]: "${prev.substr(0, prev.length - 1)}, $code]"
-        continue
-      else if i > 1 and prev.substr(0, 9) is '.concat([' and prev.substr(prev.length - 2, 2) is '])'
-        args[i - 1]: "${prev.substr(0, prev.length - 2)}, $code])"
-        continue
-      else
-        code: "[$code]"
-    args.push(if i is 0 then code else ".concat($code)")
-    i: + 1
-  args.join('')
#

WhileNode

#

A while loop, the only sort of low-level loop exposed by CoffeeScript. From + trail: if trailings then ", ${name}.length - $trailings" else '' + "${utility 'slice'}.call($name, $index$trail)"

#

Utility function that converts arbitrary number of elements, mixed with +splats, to a proper array

  @compile_mixed_array: (list, o) ->
+    args: []
+    i: 0
+    for arg in list
+      code: arg.compile o
+      if not (arg instanceof SplatNode)
+        prev: args[i - 1]
+        if i is 1 and prev.substr(0, 1) is '[' and prev.substr(prev.length - 1, 1) is ']'
+          args[i - 1]: "${prev.substr(0, prev.length - 1)}, $code]"
+          continue
+        else if i > 1 and prev.substr(0, 9) is '.concat([' and prev.substr(prev.length - 2, 2) is '])'
+          args[i - 1]: "${prev.substr(0, prev.length - 2)}, $code])"
+          continue
+        else
+          code: "[$code]"
+      args.push(if i is 0 then code else ".concat($code)")
+      i: + 1
+    args.join('')
#

WhileNode

#

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'
@@ -738,12 +726,12 @@ table.

compile_node: (o) -> ExistenceNode.compile_test(o, @expression)
#

The meat of the ExistenceNode is in this static compile_test method because other nodes like to check the existence of their variables as well. -Be careful not to double-evaluate anything.

ExistenceNode.compile_test: (o, variable) ->
-  [first, second]: [variable, variable]
-  if variable instanceof CallNode or (variable instanceof ValueNode and variable.has_properties())
-    [first, second]: variable.compile_reference(o)
-  [first, second]: [first.compile(o), second.compile(o)]
-  "(typeof $first !== \"undefined\" && $second !== null)"
#

ParentheticalNode

#

An extra set of parentheses, specified explicitly in the source. At one time +Be careful not to double-evaluate anything.

  @compile_test: (o, variable) ->
+    [first, second]: [variable, variable]
+    if variable instanceof CallNode or (variable instanceof ValueNode and variable.has_properties())
+      [first, second]: variable.compile_reference(o)
+    [first, second]: [first.compile(o), second.compile(o)]
+    "(typeof $first !== \"undefined\" && $second !== null)"
#

ParentheticalNode

#

An extra set of parentheses, specified explicitly in the source. At one time we tried to clean up the results by detecting and removing redundant parentheses, but no longer -- you can put in as many as you please.

@@ -833,8 +821,7 @@ some cannot.

< if @filter body: Expressions.wrap([new IfNode(@filter, body)]) if @object - o.scope.assign('__hasProp', 'Object.prototype.hasOwnProperty', true) - for_part: "$ivar in $svar) { if (__hasProp.call($svar, $ivar)" + for_part: "$ivar in $svar) { if (${utility('hasProp')}.call($svar, $ivar)" body: body.compile(merge(o, {indent: body_dent, top: true})) vars: if range then name else "$name, $ivar" close: if @object then '}}\n' else '}\n' @@ -937,8 +924,34 @@ in which case, no dice.

call: new CallNode(new ValueNode(func, [new AccessorNode(literal('call'))]), [literal('this')]) if statement then Expressions.wrap([call]) else call -}
#

Constants

#

Tabs are two spaces for pretty printing.

TAB: '  '
#

Trim out all trailing whitespace, so that the generated code plays nice -with Git.

TRAILING_WHITESPACE: /\s+$/gm
#

Keep this identifier regex in sync with the Lexer.

IDENTIFIER: /^[a-zA-Z\$_](\w|\$)*$/
#

Utility Functions

#

Handy helper for a generating LiteralNode.

literal: (name) ->
-  new LiteralNode(name)
+}
#

Utility Functions

UTILITIES: {
#

Correctly set up a prototype chain for inheritance, including a reference +to the superclass for super() calls. See: +goog.inherits

  __extends:  """
+              function(child, parent) {
+                  var ctor = function(){ };
+                  ctor.prototype = parent.prototype;
+                  child.__superClass__ = parent.prototype;
+                  child.prototype = new ctor();
+                  child.prototype.constructor = child;
+                }
+              """
#

Bind a function to a calling context, optionally including curried arguments. +See Underscore's implementation

  __bind:   """
+            function(func, obj, args) {
+                return function() {
+                  return func.apply(obj || {}, args ? args.concat(__slice.call(arguments, 0)) : arguments);
+                };
+              }
+            """
+
+  __hasProp:'Object.prototype.hasOwnProperty'
+
+  __slice:  'Array.prototype.slice'
+
+}
#

Constants

#

Tabs are two spaces for pretty printing.

TAB: '  '
#

Trim out all trailing whitespace, so that the generated code plays nice +with Git.

TRAILING_WHITESPACE: /\s+$/gm
#

Keep this identifier regex in sync with the Lexer.

IDENTIFIER: /^[a-zA-Z\$_](\w|\$)*$/
#

Utility Functions

#

Handy helper for a generating LiteralNode.

literal: (name) ->
+  new LiteralNode(name)
#

Helper for ensuring that utility functions are assigned at the top level.

utility: (name) ->
+  ref: "__$name"
+  Scope.root.assign ref, UTILITIES[ref]
+  ref
 
 
\ No newline at end of file diff --git a/documentation/docs/optparse.html b/documentation/docs/optparse.html index 8f8532d7..9878a0fe 100644 --- a/documentation/docs/optparse.html +++ b/documentation/docs/optparse.html @@ -17,7 +17,7 @@ many option parsers that allow you to attach callback actions for every flag. Instead, you're responsible for interpreting the options object.

  parse: (args) ->
     options: {arguments: []}
     args: normalize_arguments args
-    while arg: args.shift()
+    while (arg: args.shift())
       is_option: !!(arg.match(LONG_FLAG) or arg.match(SHORT_FLAG))
       matched_rule: no
       for rule in @rules
diff --git a/documentation/docs/scope.html b/documentation/docs/scope.html
index ddb81d25..bd7751f6 100644
--- a/documentation/docs/scope.html
+++ b/documentation/docs/scope.html
@@ -5,38 +5,44 @@ and has a reference to its parent enclosing scope. In this way, we know which
 variables are new and need to be declared with var, and which are shared
 with the outside.

#

Set up exported variables for both Node.js and the browser.

this.exports: this unless process?
 
-exports.Scope: class Scope
#

Initialize a scope with its parent, for lookups up the chain, +exports.Scope: class Scope

#

The top-level Scope object.

  @root: null
#

Initialize a scope with its parent, for lookups up the chain, as well as a reference to the Expressions node is belongs to, which is where it should declare its variables, and a reference to the function that it wraps.

  constructor: (parent, expressions, method) ->
     [@parent, @expressions, @method]: [parent, expressions, method]
     @variables: {}
-    @temp_var: if @parent then @parent.temp_var else '_a'
#

Look up a variable name in lexical scope, and declare it if it does not + if @parent + @temp_var: @parent.temp_var + else + Scope.root: this + @temp_var: '_a'

#

Look up a variable name in lexical scope, and declare it if it does not already exist.

  find: (name) ->
     return true if @check name
     @variables[name]: 'var'
-    false
#

Reserve a variable name as originating from a function parameter for this + false

#

Test variables and return true the first time fn(v, k) returns true

  any: (fn) ->
+    for v, k of @variables when fn(v, k)
+      return true
+    return false
#

Reserve a variable name as originating from a function parameter for this scope. No var required for internal references.

  parameter: (name) ->
-    @variables[name]: 'param'
#

Just check to see if a variable has already been declared, without reserving.

  check: (name) ->
+    @variables[name]: 'param'
#

Just check to see if a variable has already been declared, without reserving.

  check: (name) ->
     return true if @variables[name]
-    !!(@parent and @parent.check(name))
#

If we need to store an intermediate result, find an available name for a + !!(@parent and @parent.check(name))

#

If we need to store an intermediate result, find an available name for a compiler-generated variable. _a, _b, and so on...

  free_variable: ->
     while @check @temp_var
       ordinal: 1 + parseInt @temp_var.substr(1), 36
       @temp_var: '_' + ordinal.toString(36).replace(/\d/g, 'a')
     @variables[@temp_var]: 'var'
-    @temp_var
#

Ensure that an assignment is made at the top of this scope -(or at the top-level scope, if requested).

  assign: (name, value, top_level) ->
-    return @parent.assign(name, value, top_level) if top_level and @parent
-    @variables[name]: {value: value, assigned: true}
#

Does this scope reference any variables that need to be declared in the + @temp_var

#

Ensure that an assignment is made at the top of this scope +(or at the top-level scope, if requested).

  assign: (name, value) ->
+    @variables[name]: {value: value, assigned: true}
#

Does this scope reference any variables that need to be declared in the given function body?

  has_declarations: (body) ->
-    body is @expressions and @declared_variables().length
#

Does this scope reference any assignments that need to be declared at the + body is @expressions and @any (k, val) -> val is 'var'

#

Does this scope reference any assignments that need to be declared at the top of the given function body?

  has_assignments: (body) ->
-    body is @expressions and @assigned_variables().length
#

Return the list of variables first declared in this scope.

  declared_variables: ->
-    (key for key, val of @variables when val is 'var').sort()
#

Return the list of assignments that are supposed to be made at the top + body is @expressions and @any (k, val) -> val.assigned

#

Return the list of variables first declared in this scope.

  declared_variables: ->
+    (key for key, val of @variables when val is 'var').sort()
#

Return the list of assignments that are supposed to be made at the top of this scope.

  assigned_variables: ->
-    "$key = ${val.value}" for key, val of @variables when val.assigned
#

Compile the JavaScript for all of the variable declarations in this scope.

  compiled_declarations: ->
-    @declared_variables().join ', '
#

Compile the JavaScript for all of the variable assignments in this scope.

  compiled_assignments: ->
+    "$key = ${val.value}" for key, val of @variables when val.assigned
#

Compile the JavaScript for all of the variable declarations in this scope.

  compiled_declarations: ->
+    @declared_variables().join ', '
#

Compile the JavaScript for all of the variable assignments in this scope.

  compiled_assignments: ->
     @assigned_variables().join ', '
 
 
\ No newline at end of file