mirror of
				https://github.com/jashkenas/coffeescript.git
				synced 2022-11-09 12:23:24 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			7610 lines
		
	
	
	
		
			408 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			7610 lines
		
	
	
	
		
			408 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<!DOCTYPE html>
 | 
						||
 | 
						||
<html>
 | 
						||
<head>
 | 
						||
  <title>nodes.coffee</title>
 | 
						||
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
 | 
						||
  <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
 | 
						||
  <link rel="stylesheet" media="all" href="docco.css" />
 | 
						||
</head>
 | 
						||
<body>
 | 
						||
  <div id="container">
 | 
						||
    <div id="background"></div>
 | 
						||
    
 | 
						||
      <ul id="jump_to">
 | 
						||
        <li>
 | 
						||
          <a class="large" href="javascript:void(0);">Jump To …</a>
 | 
						||
          <a class="small" href="javascript:void(0);">+</a>
 | 
						||
          <div id="jump_wrapper">
 | 
						||
          <div id="jump_page_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="coffeescript.html">
 | 
						||
                  coffeescript.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="register.html">
 | 
						||
                  register.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.litcoffee
 | 
						||
                </a>
 | 
						||
              
 | 
						||
                
 | 
						||
                <a class="source" href="sourcemap.html">
 | 
						||
                  sourcemap.litcoffee
 | 
						||
                </a>
 | 
						||
              
 | 
						||
            </div>
 | 
						||
          </div>
 | 
						||
        </li>
 | 
						||
      </ul>
 | 
						||
    
 | 
						||
    <ul class="sections">
 | 
						||
        
 | 
						||
          <li id="title">
 | 
						||
              <div class="annotation">
 | 
						||
                  <h1>nodes.coffee</h1>
 | 
						||
              </div>
 | 
						||
          </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-1">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-1">¶</a>
 | 
						||
              </div>
 | 
						||
              <p><code>nodes.coffee</code> contains all of the node classes for the syntax tree. Most
 | 
						||
nodes are created as the result of actions in the <a href="grammar.html">grammar</a>,
 | 
						||
but some are created by other nodes as a method of code generation. To convert
 | 
						||
the syntax tree into a string of JavaScript code, call <code>compile()</code> on the root.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>
 | 
						||
Error.stackTraceLimit = Infinity
 | 
						||
 | 
						||
{Scope} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./scope'</span>
 | 
						||
{isUnassignable, JS_FORBIDDEN} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./lexer'</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-2">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-2">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Import the helpers we plan to use.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>{compact, flatten, extend, merge, del, starts, ends, some,
 | 
						||
addDataToNode, attachCommentsToNode, locationDataToString,
 | 
						||
throwSyntaxError} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-3">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-3">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Functions required by parser.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.extend = extend
 | 
						||
exports.addDataToNode = addDataToNode</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-4">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-4">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Constant functions for nodes that don’t need customization.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">YES</span>     = -></span> <span class="hljs-literal">yes</span>
 | 
						||
<span class="hljs-function"><span class="hljs-title">NO</span>      = -></span> <span class="hljs-literal">no</span>
 | 
						||
<span class="hljs-function"><span class="hljs-title">THIS</span>    = -></span> <span class="hljs-keyword">this</span>
 | 
						||
<span class="hljs-function"><span class="hljs-title">NEGATE</span>  = -></span> @negated = <span class="hljs-keyword">not</span> @negated; <span class="hljs-keyword">this</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-5">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-5">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="codefragment">CodeFragment</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-6">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-6">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>The various nodes defined below all compile to a collection of <strong>CodeFragment</strong> objects.
 | 
						||
A CodeFragments is a block of generated code, and the location in the source file where the code
 | 
						||
came from. CodeFragments can be assembled together into working code just by catting together
 | 
						||
all the CodeFragments’ <code>code</code> snippets, in order.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.CodeFragment = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CodeFragment</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(parent, code)</span> -></span>
 | 
						||
    @code = <span class="hljs-string">"<span class="hljs-subst">#{code}</span>"</span>
 | 
						||
    @type = parent?.constructor?.name <span class="hljs-keyword">or</span> <span class="hljs-string">'unknown'</span>
 | 
						||
    @locationData = parent?.locationData
 | 
						||
    @comments = parent?.comments
 | 
						||
 | 
						||
  toString: <span class="hljs-function">-></span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-7">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-7">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>This is only intended for debugging.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-string">"<span class="hljs-subst">#{@code}</span><span class="hljs-subst">#{<span class="hljs-keyword">if</span> @locationData <span class="hljs-keyword">then</span> <span class="hljs-string">": "</span> + locationDataToString(@locationData) <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>}</span>"</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-8">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-8">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Convert an array of CodeFragments into a string.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">fragmentsToText</span> = <span class="hljs-params">(fragments)</span> -></span>
 | 
						||
  (fragment.code <span class="hljs-keyword">for</span> fragment <span class="hljs-keyword">in</span> fragments).join(<span class="hljs-string">''</span>)</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-9">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-9">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="base">Base</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-10">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-10">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>The <strong>Base</strong> is the abstract base class for all nodes in the syntax tree.
 | 
						||
Each subclass implements the <code>compileNode</code> method, which performs the
 | 
						||
code generation for that node. To compile a node to JavaScript,
 | 
						||
call <code>compile</code> on it, which wraps <code>compileNode</code> in some generic extra smarts,
 | 
						||
to know when the generated code needs to be wrapped up in a closure.
 | 
						||
An options hash is passed and cloned throughout, containing information about
 | 
						||
the environment from higher in the tree (such as if a returned value is
 | 
						||
being requested by the surrounding function), information about the current
 | 
						||
scope, and indentation level.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Base = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Base</span></span>
 | 
						||
 | 
						||
  compile: <span class="hljs-function"><span class="hljs-params">(o, lvl)</span> -></span>
 | 
						||
    fragmentsToText @compileToFragments o, lvl</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-11">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-11">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Occasionally a node is compiled multiple times, for example to get the name
 | 
						||
of a variable to add to scope tracking. When we know that a “premature”
 | 
						||
compilation won’t result in comments being output, set those comments aside
 | 
						||
so that they’re preserved for a later <code>compile</code> call that will result in
 | 
						||
the comments being included in the output.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileWithoutComments: <span class="hljs-function"><span class="hljs-params">(o, lvl, method = <span class="hljs-string">'compile'</span>)</span> -></span>
 | 
						||
    <span class="hljs-keyword">if</span> @comments
 | 
						||
      @ignoreTheseCommentsTemporarily = @comments
 | 
						||
      <span class="hljs-keyword">delete</span> @comments
 | 
						||
    unwrapped = @unwrapAll()
 | 
						||
    <span class="hljs-keyword">if</span> unwrapped.comments
 | 
						||
      unwrapped.ignoreTheseCommentsTemporarily = unwrapped.comments
 | 
						||
      <span class="hljs-keyword">delete</span> unwrapped.comments
 | 
						||
 | 
						||
    fragments = @[method] o, lvl
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> @ignoreTheseCommentsTemporarily
 | 
						||
      @comments = @ignoreTheseCommentsTemporarily
 | 
						||
      <span class="hljs-keyword">delete</span> @ignoreTheseCommentsTemporarily
 | 
						||
    <span class="hljs-keyword">if</span> unwrapped.ignoreTheseCommentsTemporarily
 | 
						||
      unwrapped.comments = unwrapped.ignoreTheseCommentsTemporarily
 | 
						||
      <span class="hljs-keyword">delete</span> unwrapped.ignoreTheseCommentsTemporarily
 | 
						||
 | 
						||
    fragments
 | 
						||
 | 
						||
  compileNodeWithoutComments: <span class="hljs-function"><span class="hljs-params">(o, lvl)</span> -></span>
 | 
						||
    @compileWithoutComments o, lvl, <span class="hljs-string">'compileNode'</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-12">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-12">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Common logic for determining whether to wrap this node in a closure before
 | 
						||
compiling it, or to compile directly. We need to wrap if this node is a
 | 
						||
<em>statement</em>, and it’s not a <em>pureStatement</em>, and we’re not at
 | 
						||
the top level of a block (which would be unnecessary), and we haven’t
 | 
						||
already been asked to return the result (because statements know how to
 | 
						||
return results).</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileToFragments: <span class="hljs-function"><span class="hljs-params">(o, lvl)</span> -></span>
 | 
						||
    o        = extend {}, o
 | 
						||
    o.level  = lvl <span class="hljs-keyword">if</span> lvl
 | 
						||
    node     = @unfoldSoak(o) <span class="hljs-keyword">or</span> <span class="hljs-keyword">this</span>
 | 
						||
    node.tab = o.indent
 | 
						||
 | 
						||
    fragments = <span class="hljs-keyword">if</span> o.level <span class="hljs-keyword">is</span> LEVEL_TOP <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> node.isStatement(o)
 | 
						||
      node.compileNode o
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      node.compileClosure o
 | 
						||
    @compileCommentFragments o, node, fragments
 | 
						||
    fragments
 | 
						||
 | 
						||
  compileToFragmentsWithoutComments: <span class="hljs-function"><span class="hljs-params">(o, lvl)</span> -></span>
 | 
						||
    @compileWithoutComments o, lvl, <span class="hljs-string">'compileToFragments'</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-13">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-13">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Statements converted into expressions via closure-wrapping share a scope
 | 
						||
object with their parent closure, to preserve the expected lexical scope.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileClosure: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    <span class="hljs-keyword">if</span> jumpNode = @jumps()
 | 
						||
      jumpNode.error <span class="hljs-string">'cannot use a pure statement in an expression'</span>
 | 
						||
    o.sharedScope = <span class="hljs-literal">yes</span>
 | 
						||
    func = <span class="hljs-keyword">new</span> Code [], Block.wrap [<span class="hljs-keyword">this</span>]
 | 
						||
    args = []
 | 
						||
    <span class="hljs-keyword">if</span> @contains (<span class="hljs-function"><span class="hljs-params">(node)</span> -></span> node <span class="hljs-keyword">instanceof</span> SuperCall)
 | 
						||
      func.bound = <span class="hljs-literal">yes</span>
 | 
						||
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (argumentsNode = @contains isLiteralArguments) <span class="hljs-keyword">or</span> @contains isLiteralThis
 | 
						||
      args = [<span class="hljs-keyword">new</span> ThisLiteral]
 | 
						||
      <span class="hljs-keyword">if</span> argumentsNode
 | 
						||
        meth = <span class="hljs-string">'apply'</span>
 | 
						||
        args.push <span class="hljs-keyword">new</span> IdentifierLiteral <span class="hljs-string">'arguments'</span>
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        meth = <span class="hljs-string">'call'</span>
 | 
						||
      func = <span class="hljs-keyword">new</span> Value func, [<span class="hljs-keyword">new</span> Access <span class="hljs-keyword">new</span> PropertyName meth]
 | 
						||
    parts = (<span class="hljs-keyword">new</span> Call func, args).compileNode o
 | 
						||
 | 
						||
    <span class="hljs-keyword">switch</span>
 | 
						||
      <span class="hljs-keyword">when</span> func.isGenerator <span class="hljs-keyword">or</span> func.base?.isGenerator
 | 
						||
        parts.unshift @makeCode <span class="hljs-string">"(yield* "</span>
 | 
						||
        parts.push    @makeCode <span class="hljs-string">")"</span>
 | 
						||
      <span class="hljs-keyword">when</span> func.isAsync <span class="hljs-keyword">or</span> func.base?.isAsync
 | 
						||
        parts.unshift @makeCode <span class="hljs-string">"(await "</span>
 | 
						||
        parts.push    @makeCode <span class="hljs-string">")"</span>
 | 
						||
    parts
 | 
						||
 | 
						||
  compileCommentFragments: <span class="hljs-function"><span class="hljs-params">(o, node, fragments)</span> -></span>
 | 
						||
    <span class="hljs-keyword">return</span> fragments <span class="hljs-keyword">unless</span> node.comments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-14">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-14">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>This is where comments, that are attached to nodes as a <code>comments</code>
 | 
						||
property, become <code>CodeFragment</code>s. “Inline block comments,” e.g.
 | 
						||
<code>/* */</code>-delimited comments that are interspersed within code on a line,
 | 
						||
are added to the current <code>fragments</code> stream. All other fragments are
 | 
						||
attached as properties to the nearest preceding or following fragment,
 | 
						||
to remain stowaways until they get properly output in <code>compileComments</code>
 | 
						||
later on.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre><span class="hljs-function">    <span class="hljs-title">unshiftCommentFragment</span> = <span class="hljs-params">(commentFragment)</span> -></span>
 | 
						||
      <span class="hljs-keyword">if</span> commentFragment.unshift</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-15">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-15">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Find the first non-comment fragment and insert <code>commentFragment</code>
 | 
						||
before it.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        unshiftAfterComments fragments, commentFragment
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        <span class="hljs-keyword">if</span> fragments.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span>
 | 
						||
          precedingFragment = fragments[fragments.length - <span class="hljs-number">1</span>]
 | 
						||
          <span class="hljs-keyword">if</span> commentFragment.newLine <span class="hljs-keyword">and</span> precedingFragment.code <span class="hljs-keyword">isnt</span> <span class="hljs-string">''</span> <span class="hljs-keyword">and</span>
 | 
						||
             <span class="hljs-keyword">not</span> <span class="hljs-regexp">/\n\s*$/</span>.test precedingFragment.code
 | 
						||
            commentFragment.code = <span class="hljs-string">"\n<span class="hljs-subst">#{commentFragment.code}</span>"</span>
 | 
						||
        fragments.push commentFragment
 | 
						||
 | 
						||
    <span class="hljs-keyword">for</span> comment <span class="hljs-keyword">in</span> node.comments <span class="hljs-keyword">when</span> comment <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> @compiledComments
 | 
						||
      @compiledComments.push comment <span class="hljs-comment"># Don’t output this comment twice.</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-16">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-16">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>For block/here comments, denoted by <code>###</code>, that are inline comments
 | 
						||
like <code>1 + ### comment ### 2</code>, create fragments and insert them into
 | 
						||
the fragments array.
 | 
						||
Otherwise attach comment fragments to their closest fragment for now,
 | 
						||
so they can be inserted into the output later after all the newlines
 | 
						||
have been added.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      <span class="hljs-keyword">if</span> comment.here <span class="hljs-comment"># Block comment, delimited by `###`.</span>
 | 
						||
        commentFragment = <span class="hljs-keyword">new</span> HereComment(comment).compileNode o
 | 
						||
      <span class="hljs-keyword">else</span> <span class="hljs-comment"># Line comment, delimited by `#`.</span>
 | 
						||
        commentFragment = <span class="hljs-keyword">new</span> LineComment(comment).compileNode o
 | 
						||
      <span class="hljs-keyword">if</span> (commentFragment.isHereComment <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> commentFragment.newLine) <span class="hljs-keyword">or</span>
 | 
						||
         node.includeCommentFragments()</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-17">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-17">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Inline block comments, like <code>1 + /* comment */ 2</code>, or a node whose
 | 
						||
<code>compileToFragments</code> method has logic for outputting comments.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        unshiftCommentFragment commentFragment
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        <span class="hljs-keyword">if</span> commentFragment.unshift
 | 
						||
          fragments[<span class="hljs-number">0</span>].precedingComments ?= []
 | 
						||
          fragments[<span class="hljs-number">0</span>].precedingComments.push commentFragment
 | 
						||
        <span class="hljs-keyword">else</span>
 | 
						||
          fragments[fragments.length - <span class="hljs-number">1</span>].followingComments ?= []
 | 
						||
          fragments[fragments.length - <span class="hljs-number">1</span>].followingComments.push commentFragment
 | 
						||
    fragments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-18">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-18">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>If the code generation wishes to use the result of a complex expression
 | 
						||
in multiple places, ensure that the expression is only ever evaluated once,
 | 
						||
by assigning it to a temporary variable. Pass a level to precompile.</p>
 | 
						||
<p>If <code>level</code> is passed, then returns <code>[val, ref]</code>, where <code>val</code> is the compiled value, and <code>ref</code>
 | 
						||
is the compiled reference. If <code>level</code> is not passed, this returns <code>[val, ref]</code> where
 | 
						||
the two values are raw nodes which have not been compiled.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  cache: <span class="hljs-function"><span class="hljs-params">(o, level, shouldCache)</span> -></span>
 | 
						||
    complex = <span class="hljs-keyword">if</span> shouldCache? <span class="hljs-keyword">then</span> shouldCache <span class="hljs-keyword">this</span> <span class="hljs-keyword">else</span> @shouldCache()
 | 
						||
    <span class="hljs-keyword">if</span> complex
 | 
						||
      ref = <span class="hljs-keyword">new</span> IdentifierLiteral o.scope.freeVariable <span class="hljs-string">'ref'</span>
 | 
						||
      sub = <span class="hljs-keyword">new</span> Assign ref, <span class="hljs-keyword">this</span>
 | 
						||
      <span class="hljs-keyword">if</span> level <span class="hljs-keyword">then</span> [sub.compileToFragments(o, level), [@makeCode(ref.value)]] <span class="hljs-keyword">else</span> [sub, ref]
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      ref = <span class="hljs-keyword">if</span> level <span class="hljs-keyword">then</span> @compileToFragments o, level <span class="hljs-keyword">else</span> <span class="hljs-keyword">this</span>
 | 
						||
      [ref, ref]</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-19">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-19">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Occasionally it may be useful to make an expression behave as if it was ‘hoisted’, whereby the
 | 
						||
result of the expression is available before its location in the source, but the expression’s
 | 
						||
variable scope corresponds the source position. This is used extensively to deal with executable
 | 
						||
class bodies in classes.</p>
 | 
						||
<p>Calling this method mutates the node, proxying the <code>compileNode</code> and <code>compileToFragments</code>
 | 
						||
methods to store their result for later replacing the <code>target</code> node, which is returned by the
 | 
						||
call.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  hoist: <span class="hljs-function">-></span>
 | 
						||
    @hoisted = <span class="hljs-literal">yes</span>
 | 
						||
    target   = <span class="hljs-keyword">new</span> HoistTarget @
 | 
						||
 | 
						||
    compileNode        = @compileNode
 | 
						||
    compileToFragments = @compileToFragments
 | 
						||
 | 
						||
    @compileNode = <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
      target.update compileNode, o
 | 
						||
 | 
						||
    @compileToFragments = <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
      target.update compileToFragments, o
 | 
						||
 | 
						||
    target
 | 
						||
 | 
						||
  cacheToCodeFragments: <span class="hljs-function"><span class="hljs-params">(cacheValues)</span> -></span>
 | 
						||
    [fragmentsToText(cacheValues[<span class="hljs-number">0</span>]), fragmentsToText(cacheValues[<span class="hljs-number">1</span>])]</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-20">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-20">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>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)…</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  makeReturn: <span class="hljs-function"><span class="hljs-params">(res)</span> -></span>
 | 
						||
    me = @unwrapAll()
 | 
						||
    <span class="hljs-keyword">if</span> res
 | 
						||
      <span class="hljs-keyword">new</span> Call <span class="hljs-keyword">new</span> Literal(<span class="hljs-string">"<span class="hljs-subst">#{res}</span>.push"</span>), [me]
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      <span class="hljs-keyword">new</span> Return me</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-21">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-21">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Does this node, or any of its children, contain a node of a certain kind?
 | 
						||
Recursively traverses down the <em>children</em> nodes and returns the first one
 | 
						||
that verifies <code>pred</code>. Otherwise return undefined. <code>contains</code> does not cross
 | 
						||
scope boundaries.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  contains: <span class="hljs-function"><span class="hljs-params">(pred)</span> -></span>
 | 
						||
    node = <span class="hljs-literal">undefined</span>
 | 
						||
    @traverseChildren <span class="hljs-literal">no</span>, <span class="hljs-function"><span class="hljs-params">(n)</span> -></span>
 | 
						||
      <span class="hljs-keyword">if</span> pred n
 | 
						||
        node = n
 | 
						||
        <span class="hljs-keyword">return</span> <span class="hljs-literal">no</span>
 | 
						||
    node</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-22">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-22">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Pull out the last node of a node list.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  lastNode: <span class="hljs-function"><span class="hljs-params">(list)</span> -></span>
 | 
						||
    <span class="hljs-keyword">if</span> list.length <span class="hljs-keyword">is</span> <span class="hljs-number">0</span> <span class="hljs-keyword">then</span> <span class="hljs-literal">null</span> <span class="hljs-keyword">else</span> list[list.length - <span class="hljs-number">1</span>]</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-23">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-23">¶</a>
 | 
						||
              </div>
 | 
						||
              <p><code>toString</code> representation of the node, for inspecting the parse tree.
 | 
						||
This is what <code>coffee --nodes</code> prints out.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  toString: <span class="hljs-function"><span class="hljs-params">(idt = <span class="hljs-string">''</span>, name = @constructor.name)</span> -></span>
 | 
						||
    tree = <span class="hljs-string">'\n'</span> + idt + name
 | 
						||
    tree += <span class="hljs-string">'?'</span> <span class="hljs-keyword">if</span> @soak
 | 
						||
    @eachChild (node) -> tree += node.toString idt + TAB
 | 
						||
    tree</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-24">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-24">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Passes each child to a function, breaking when the function returns <code>false</code>.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  eachChild: <span class="hljs-function"><span class="hljs-params">(func)</span> -></span>
 | 
						||
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span> <span class="hljs-keyword">unless</span> @children
 | 
						||
    <span class="hljs-keyword">for</span> attr <span class="hljs-keyword">in</span> @children <span class="hljs-keyword">when</span> @[attr]
 | 
						||
      <span class="hljs-keyword">for</span> child <span class="hljs-keyword">in</span> flatten [@[attr]]
 | 
						||
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span> <span class="hljs-keyword">if</span> func(child) <span class="hljs-keyword">is</span> <span class="hljs-literal">false</span>
 | 
						||
    <span class="hljs-keyword">this</span>
 | 
						||
 | 
						||
  traverseChildren: <span class="hljs-function"><span class="hljs-params">(crossScope, func)</span> -></span>
 | 
						||
    @eachChild (child) ->
 | 
						||
      recur = func(child)
 | 
						||
      child.traverseChildren(crossScope, func) <span class="hljs-keyword">unless</span> recur <span class="hljs-keyword">is</span> <span class="hljs-literal">no</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-25">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-25">¶</a>
 | 
						||
              </div>
 | 
						||
              <p><code>replaceInContext</code> will traverse children looking for a node for which <code>match</code> returns
 | 
						||
true. Once found, the matching node will be replaced by the result of calling <code>replacement</code>.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  replaceInContext: <span class="hljs-function"><span class="hljs-params">(match, replacement)</span> -></span>
 | 
						||
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span> <span class="hljs-keyword">unless</span> @children
 | 
						||
    <span class="hljs-keyword">for</span> attr <span class="hljs-keyword">in</span> @children <span class="hljs-keyword">when</span> children = @[attr]
 | 
						||
      <span class="hljs-keyword">if</span> Array.isArray children
 | 
						||
        <span class="hljs-keyword">for</span> child, i <span class="hljs-keyword">in</span> children
 | 
						||
          <span class="hljs-keyword">if</span> match child
 | 
						||
            children[i..i] = replacement child, @
 | 
						||
            <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>
 | 
						||
          <span class="hljs-keyword">else</span>
 | 
						||
            <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span> <span class="hljs-keyword">if</span> child.replaceInContext match, replacement
 | 
						||
      <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> match children
 | 
						||
        @[attr] = replacement children, @
 | 
						||
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span> <span class="hljs-keyword">if</span> children.replaceInContext match, replacement
 | 
						||
 | 
						||
  invert: <span class="hljs-function">-></span>
 | 
						||
    <span class="hljs-keyword">new</span> Op <span class="hljs-string">'!'</span>, <span class="hljs-keyword">this</span>
 | 
						||
 | 
						||
  unwrapAll: <span class="hljs-function">-></span>
 | 
						||
    node = <span class="hljs-keyword">this</span>
 | 
						||
    <span class="hljs-keyword">continue</span> <span class="hljs-keyword">until</span> node <span class="hljs-keyword">is</span> node = node.unwrap()
 | 
						||
    node</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-26">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-26">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Default implementations of the common node properties and methods. Nodes
 | 
						||
will override these with custom logic, if needed.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-27">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-27">¶</a>
 | 
						||
              </div>
 | 
						||
              <p><code>children</code> are the properties to recurse into when tree walking. The
 | 
						||
<code>children</code> list <em>is</em> the structure of the AST. The <code>parent</code> pointer, and
 | 
						||
the pointer to the <code>children</code> are how you can traverse the tree.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  children: []</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-28">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-28">¶</a>
 | 
						||
              </div>
 | 
						||
              <p><code>isStatement</code> has to do with “everything is an expression”. A few things
 | 
						||
can’t be expressions, such as <code>break</code>. Things that <code>isStatement</code> returns
 | 
						||
<code>true</code> for are things that can’t be used as expressions. There are some
 | 
						||
error messages that come from <code>nodes.coffee</code> due to statements ending up
 | 
						||
in expression position.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  isStatement: NO</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-29">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-29">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Track comments that have been compiled into fragments, to avoid outputting
 | 
						||
them twice.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compiledComments: []</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-30">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-30">¶</a>
 | 
						||
              </div>
 | 
						||
              <p><code>includeCommentFragments</code> lets <code>compileCommentFragments</code> know whether this node
 | 
						||
has special awareness of how to handle comments within its output.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  includeCommentFragments: NO</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-31">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-31">¶</a>
 | 
						||
              </div>
 | 
						||
              <p><code>jumps</code> tells you if an expression, or an internal part of an expression
 | 
						||
has a flow control construct (like <code>break</code>, or <code>continue</code>, or <code>return</code>,
 | 
						||
or <code>throw</code>) that jumps out of the normal flow of control and can’t be
 | 
						||
used as a value. This is important because things like this make no sense;
 | 
						||
we have to disallow them.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  jumps: NO</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-32">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-32">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>If <code>node.shouldCache() is false</code>, it is safe to use <code>node</code> more than once.
 | 
						||
Otherwise you need to store the value of <code>node</code> in a variable and output
 | 
						||
that variable several times instead. Kind of like this: <code>5</code> need not be
 | 
						||
cached. <code>returnFive()</code>, however, could have side effects as a result of
 | 
						||
evaluating it more than once, and therefore we need to cache it. The
 | 
						||
parameter is named <code>shouldCache</code> rather than <code>mustCache</code> because there are
 | 
						||
also cases where we might not need to cache but where we want to, for
 | 
						||
example a long expression that may well be idempotent but we want to cache
 | 
						||
for brevity.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  shouldCache: YES
 | 
						||
 | 
						||
  isChainable: NO
 | 
						||
  isAssignable: NO
 | 
						||
  isNumber: NO
 | 
						||
 | 
						||
  unwrap: THIS
 | 
						||
  unfoldSoak: NO</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-33">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-33">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Is this node used to assign a certain variable?</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  assigns: NO</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-34">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-34">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>For this node and all descendents, set the location data to <code>locationData</code>
 | 
						||
if the location data is not already set.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  updateLocationDataIfMissing: <span class="hljs-function"><span class="hljs-params">(locationData)</span> -></span>
 | 
						||
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span> <span class="hljs-keyword">if</span> @locationData <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @forceUpdateLocation
 | 
						||
    <span class="hljs-keyword">delete</span> @forceUpdateLocation
 | 
						||
    @locationData = locationData
 | 
						||
 | 
						||
    @eachChild (child) ->
 | 
						||
      child.updateLocationDataIfMissing locationData</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-35">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-35">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Throw a SyntaxError associated with this node’s location.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  error: <span class="hljs-function"><span class="hljs-params">(message)</span> -></span>
 | 
						||
    throwSyntaxError message, @locationData
 | 
						||
 | 
						||
  makeCode: <span class="hljs-function"><span class="hljs-params">(code)</span> -></span>
 | 
						||
    <span class="hljs-keyword">new</span> CodeFragment <span class="hljs-keyword">this</span>, code
 | 
						||
 | 
						||
  wrapInParentheses: <span class="hljs-function"><span class="hljs-params">(fragments)</span> -></span>
 | 
						||
    [@makeCode(<span class="hljs-string">'('</span>), fragments..., @makeCode(<span class="hljs-string">')'</span>)]
 | 
						||
 | 
						||
  wrapInBraces: <span class="hljs-function"><span class="hljs-params">(fragments)</span> -></span>
 | 
						||
    [@makeCode(<span class="hljs-string">'{'</span>), fragments..., @makeCode(<span class="hljs-string">'}'</span>)]</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-36">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-36">¶</a>
 | 
						||
              </div>
 | 
						||
              <p><code>fragmentsList</code> is an array of arrays of fragments. Each array in fragmentsList will be
 | 
						||
concatenated together, with <code>joinStr</code> added in between each, to produce a final flat array
 | 
						||
of fragments.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  joinFragmentArrays: <span class="hljs-function"><span class="hljs-params">(fragmentsList, joinStr)</span> -></span>
 | 
						||
    answer = []
 | 
						||
    <span class="hljs-keyword">for</span> fragments, i <span class="hljs-keyword">in</span> fragmentsList
 | 
						||
      <span class="hljs-keyword">if</span> i <span class="hljs-keyword">then</span> answer.push @makeCode joinStr
 | 
						||
      answer = answer.concat fragments
 | 
						||
    answer</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-37">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-37">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="hoisttarget">HoistTarget</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-38">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-38">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>A <strong>HoistTargetNode</strong> represents the output location in the node tree for a hoisted node.
 | 
						||
See Base#hoist.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.HoistTarget = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HoistTarget</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-39">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-39">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Expands hoisted fragments in the given array</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  @expand = <span class="hljs-function"><span class="hljs-params">(fragments)</span> -></span>
 | 
						||
    <span class="hljs-keyword">for</span> fragment, i <span class="hljs-keyword">in</span> fragments <span class="hljs-keyword">by</span> <span class="hljs-number">-1</span> <span class="hljs-keyword">when</span> fragment.fragments
 | 
						||
      fragments[i..i] = @expand fragment.fragments
 | 
						||
    fragments
 | 
						||
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@source)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-40">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-40">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Holds presentational options to apply when the source node is compiled.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    @options = {}</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-41">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-41">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Placeholder fragments to be replaced by the source node’s compilation.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    @targetFragments = { fragments: [] }
 | 
						||
 | 
						||
  isStatement: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    @source.isStatement o</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-42">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-42">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Update the target fragments with the result of compiling the source.
 | 
						||
Calls the given compile function with the node and options (overriden with the target
 | 
						||
presentational options).</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  update: <span class="hljs-function"><span class="hljs-params">(compile, o)</span> -></span>
 | 
						||
    @targetFragments.fragments = compile.call @source, merge o, @options</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-43">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-43">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Copies the target indent and level, and returns the placeholder fragments</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileToFragments: <span class="hljs-function"><span class="hljs-params">(o, level)</span> -></span>
 | 
						||
    @options.indent = o.indent
 | 
						||
    @options.level  = level ? o.level
 | 
						||
    [ @targetFragments ]
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    @compileToFragments o
 | 
						||
 | 
						||
  compileClosure: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    @compileToFragments o</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-44">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-44">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="block">Block</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-45">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-45">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>The block is the list of expressions that forms the body of an
 | 
						||
indented block of code – the implementation of a function, a clause in an
 | 
						||
<code>if</code>, <code>switch</code>, or <code>try</code>, and so on…</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Block = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Block</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(nodes)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
    @expressions = compact flatten nodes <span class="hljs-keyword">or</span> []
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'expressions'</span>]</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-46">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-46">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Tack an expression on to the end of this expression list.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  push: <span class="hljs-function"><span class="hljs-params">(node)</span> -></span>
 | 
						||
    @expressions.push node
 | 
						||
    <span class="hljs-keyword">this</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-47">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-47">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Remove and return the last expression of this expression list.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  pop: <span class="hljs-function">-></span>
 | 
						||
    @expressions.pop()</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-48">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-48">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Add an expression at the beginning of this expression list.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  unshift: <span class="hljs-function"><span class="hljs-params">(node)</span> -></span>
 | 
						||
    @expressions.unshift node
 | 
						||
    <span class="hljs-keyword">this</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-49">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-49">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>If this Block consists of just a single node, unwrap it by pulling
 | 
						||
it back out.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  unwrap: <span class="hljs-function">-></span>
 | 
						||
    <span class="hljs-keyword">if</span> @expressions.length <span class="hljs-keyword">is</span> <span class="hljs-number">1</span> <span class="hljs-keyword">then</span> @expressions[<span class="hljs-number">0</span>] <span class="hljs-keyword">else</span> <span class="hljs-keyword">this</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-50">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-50">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Is this an empty block of code?</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  isEmpty: <span class="hljs-function">-></span>
 | 
						||
    <span class="hljs-keyword">not</span> @expressions.length
 | 
						||
 | 
						||
  isStatement: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    <span class="hljs-keyword">for</span> exp <span class="hljs-keyword">in</span> @expressions <span class="hljs-keyword">when</span> exp.isStatement o
 | 
						||
      <span class="hljs-keyword">return</span> <span class="hljs-literal">yes</span>
 | 
						||
    <span class="hljs-literal">no</span>
 | 
						||
 | 
						||
  jumps: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    <span class="hljs-keyword">for</span> exp <span class="hljs-keyword">in</span> @expressions
 | 
						||
      <span class="hljs-keyword">return</span> jumpNode <span class="hljs-keyword">if</span> jumpNode = exp.jumps o</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-51">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-51">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>A Block node does not return its entire body, rather it
 | 
						||
ensures that the final expression is returned.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  makeReturn: <span class="hljs-function"><span class="hljs-params">(res)</span> -></span>
 | 
						||
    len = @expressions.length
 | 
						||
    <span class="hljs-keyword">while</span> len--
 | 
						||
      expr = @expressions[len]
 | 
						||
      @expressions[len] = expr.makeReturn res
 | 
						||
      @expressions.splice(len, <span class="hljs-number">1</span>) <span class="hljs-keyword">if</span> expr <span class="hljs-keyword">instanceof</span> Return <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> expr.expression
 | 
						||
      <span class="hljs-keyword">break</span>
 | 
						||
    <span class="hljs-keyword">this</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-52">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-52">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>A <strong>Block</strong> is the only node that can serve as the root.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileToFragments: <span class="hljs-function"><span class="hljs-params">(o = {}, level)</span> -></span>
 | 
						||
    <span class="hljs-keyword">if</span> o.scope <span class="hljs-keyword">then</span> <span class="hljs-keyword">super</span> o, level <span class="hljs-keyword">else</span> @compileRoot o</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-53">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-53">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Compile all expressions within the <strong>Block</strong> body. If we need to return
 | 
						||
the result, and it’s an expression, simply return it. If it’s a statement,
 | 
						||
ask the statement to do so.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    @tab  = o.indent
 | 
						||
    top   = o.level <span class="hljs-keyword">is</span> LEVEL_TOP
 | 
						||
    compiledNodes = []
 | 
						||
 | 
						||
    <span class="hljs-keyword">for</span> node, index <span class="hljs-keyword">in</span> @expressions
 | 
						||
      node = node.unwrapAll()
 | 
						||
      node = (node.unfoldSoak(o) <span class="hljs-keyword">or</span> node)
 | 
						||
      <span class="hljs-keyword">if</span> node <span class="hljs-keyword">instanceof</span> Block</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-54">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-54">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>This is a nested block. We don’t do anything special here like
 | 
						||
enclose it in a new scope; we just compile the statements in this
 | 
						||
block along with our own.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        compiledNodes.push node.compileNode o
 | 
						||
      <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> node.hoisted</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-55">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-55">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>This is a hoisted expression.
 | 
						||
We want to compile this and ignore the result.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        node.compileToFragments o
 | 
						||
      <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> top
 | 
						||
        node.front = <span class="hljs-literal">yes</span>
 | 
						||
        fragments = node.compileToFragments o
 | 
						||
        <span class="hljs-keyword">unless</span> node.isStatement o
 | 
						||
          fragments = indentInitial fragments, @
 | 
						||
          [..., lastFragment] = fragments
 | 
						||
          <span class="hljs-keyword">unless</span> lastFragment.code <span class="hljs-keyword">is</span> <span class="hljs-string">''</span> <span class="hljs-keyword">or</span> lastFragment.isComment
 | 
						||
            fragments.push @makeCode <span class="hljs-string">';'</span>
 | 
						||
        compiledNodes.push fragments
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        compiledNodes.push node.compileToFragments o, LEVEL_LIST
 | 
						||
    <span class="hljs-keyword">if</span> top
 | 
						||
      <span class="hljs-keyword">if</span> @spaced
 | 
						||
        <span class="hljs-keyword">return</span> [].concat @joinFragmentArrays(compiledNodes, <span class="hljs-string">'\n\n'</span>), @makeCode(<span class="hljs-string">'\n'</span>)
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        <span class="hljs-keyword">return</span> @joinFragmentArrays(compiledNodes, <span class="hljs-string">'\n'</span>)
 | 
						||
    <span class="hljs-keyword">if</span> compiledNodes.length
 | 
						||
      answer = @joinFragmentArrays(compiledNodes, <span class="hljs-string">', '</span>)
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      answer = [@makeCode <span class="hljs-string">'void 0'</span>]
 | 
						||
    <span class="hljs-keyword">if</span> compiledNodes.length > <span class="hljs-number">1</span> <span class="hljs-keyword">and</span> o.level >= LEVEL_LIST <span class="hljs-keyword">then</span> @wrapInParentheses answer <span class="hljs-keyword">else</span> answer</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-56">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-56">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>If we happen to be the top-level <strong>Block</strong>, wrap everything in a safety
 | 
						||
closure, unless requested not to. It would be better not to generate them
 | 
						||
in the first place, but for now, clean up obvious double-parentheses.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileRoot: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    o.indent  = <span class="hljs-keyword">if</span> o.bare <span class="hljs-keyword">then</span> <span class="hljs-string">''</span> <span class="hljs-keyword">else</span> TAB
 | 
						||
    o.level   = LEVEL_TOP
 | 
						||
    @spaced   = <span class="hljs-literal">yes</span>
 | 
						||
    o.scope   = <span class="hljs-keyword">new</span> Scope <span class="hljs-literal">null</span>, <span class="hljs-keyword">this</span>, <span class="hljs-literal">null</span>, o.referencedVars ? []</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-57">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-57">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Mark given local variables in the root scope as parameters so they don’t
 | 
						||
end up being declared on this block.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    o.scope.parameter name <span class="hljs-keyword">for</span> name <span class="hljs-keyword">in</span> o.locals <span class="hljs-keyword">or</span> []
 | 
						||
    fragments = @compileWithDeclarations o
 | 
						||
    HoistTarget.expand fragments
 | 
						||
    fragments = @compileComments fragments
 | 
						||
    <span class="hljs-keyword">return</span> fragments <span class="hljs-keyword">if</span> o.bare
 | 
						||
    [].concat @makeCode(<span class="hljs-string">"(function() {\n"</span>), fragments, @makeCode(<span class="hljs-string">"\n}).call(this);\n"</span>)</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-58">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-58">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Compile the expressions body for the contents of a function, with
 | 
						||
declarations of all inner variables pushed up to the top.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileWithDeclarations: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    fragments = []
 | 
						||
    post = []
 | 
						||
    <span class="hljs-keyword">for</span> exp, i <span class="hljs-keyword">in</span> @expressions
 | 
						||
      exp = exp.unwrap()
 | 
						||
      <span class="hljs-keyword">break</span> <span class="hljs-keyword">unless</span> exp <span class="hljs-keyword">instanceof</span> Literal
 | 
						||
    o = merge(o, level: LEVEL_TOP)
 | 
						||
    <span class="hljs-keyword">if</span> i
 | 
						||
      rest = @expressions.splice i, <span class="hljs-number">9e9</span>
 | 
						||
      [spaced,    @spaced] = [@spaced, <span class="hljs-literal">no</span>]
 | 
						||
      [fragments, @spaced] = [@compileNode(o), spaced]
 | 
						||
      @expressions = rest
 | 
						||
    post = @compileNode o
 | 
						||
    {scope} = o
 | 
						||
    <span class="hljs-keyword">if</span> scope.expressions <span class="hljs-keyword">is</span> <span class="hljs-keyword">this</span>
 | 
						||
      declars = o.scope.hasDeclarations()
 | 
						||
      assigns = scope.hasAssignments
 | 
						||
      <span class="hljs-keyword">if</span> declars <span class="hljs-keyword">or</span> assigns
 | 
						||
        fragments.push @makeCode <span class="hljs-string">'\n'</span> <span class="hljs-keyword">if</span> i
 | 
						||
        fragments.push @makeCode <span class="hljs-string">"<span class="hljs-subst">#{@tab}</span>var "</span>
 | 
						||
        <span class="hljs-keyword">if</span> declars
 | 
						||
          fragments.push @makeCode scope.declaredVariables().join(<span class="hljs-string">', '</span>)
 | 
						||
        <span class="hljs-keyword">if</span> assigns
 | 
						||
          fragments.push @makeCode <span class="hljs-string">",\n<span class="hljs-subst">#{@tab + TAB}</span>"</span> <span class="hljs-keyword">if</span> declars
 | 
						||
          fragments.push @makeCode scope.assignedVariables().join(<span class="hljs-string">",\n<span class="hljs-subst">#{@tab + TAB}</span>"</span>)
 | 
						||
        fragments.push @makeCode <span class="hljs-string">";\n<span class="hljs-subst">#{<span class="hljs-keyword">if</span> @spaced <span class="hljs-keyword">then</span> <span class="hljs-string">'\n'</span> <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>}</span>"</span>
 | 
						||
      <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> fragments.length <span class="hljs-keyword">and</span> post.length
 | 
						||
        fragments.push @makeCode <span class="hljs-string">"\n"</span>
 | 
						||
    fragments.concat post
 | 
						||
 | 
						||
  compileComments: <span class="hljs-function"><span class="hljs-params">(fragments)</span> -></span>
 | 
						||
    <span class="hljs-keyword">for</span> fragment, fragmentIndex <span class="hljs-keyword">in</span> fragments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-59">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-59">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Insert comments into the output at the next or previous newline.
 | 
						||
If there are no newlines at which to place comments, create them.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      <span class="hljs-keyword">if</span> fragment.precedingComments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-60">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-60">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Determine the indentation level of the fragment that we are about
 | 
						||
to insert comments before, and use that indentation level for our
 | 
						||
inserted comments. At this point, the fragments’ <code>code</code> property
 | 
						||
is the generated output JavaScript, and CoffeeScript always
 | 
						||
generates output indented by two spaces; so all we need to do is
 | 
						||
search for a <code>code</code> property that begins with at least two spaces.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        fragmentIndent = <span class="hljs-string">''</span>
 | 
						||
        <span class="hljs-keyword">for</span> pastFragment <span class="hljs-keyword">in</span> fragments[<span class="hljs-number">0.</span>..(fragmentIndex + <span class="hljs-number">1</span>)] <span class="hljs-keyword">by</span> <span class="hljs-number">-1</span>
 | 
						||
          indent = <span class="hljs-regexp">/^ {2,}/m</span>.exec pastFragment.code
 | 
						||
          <span class="hljs-keyword">if</span> indent
 | 
						||
            fragmentIndent = indent[<span class="hljs-number">0</span>]
 | 
						||
            <span class="hljs-keyword">break</span>
 | 
						||
          <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> <span class="hljs-string">'\n'</span> <span class="hljs-keyword">in</span> pastFragment.code
 | 
						||
            <span class="hljs-keyword">break</span>
 | 
						||
        code = <span class="hljs-string">"\n<span class="hljs-subst">#{fragmentIndent}</span>"</span> + (
 | 
						||
            <span class="hljs-keyword">for</span> commentFragment <span class="hljs-keyword">in</span> fragment.precedingComments
 | 
						||
              <span class="hljs-keyword">if</span> commentFragment.isHereComment <span class="hljs-keyword">and</span> commentFragment.multiline
 | 
						||
                multident commentFragment.code, fragmentIndent, <span class="hljs-literal">no</span>
 | 
						||
              <span class="hljs-keyword">else</span>
 | 
						||
                commentFragment.code
 | 
						||
          ).join(<span class="hljs-string">"\n<span class="hljs-subst">#{fragmentIndent}</span>"</span>).replace <span class="hljs-regexp">/^(\s*)$/gm</span>, <span class="hljs-string">''</span>
 | 
						||
        <span class="hljs-keyword">for</span> pastFragment, pastFragmentIndex <span class="hljs-keyword">in</span> fragments[<span class="hljs-number">0.</span>..(fragmentIndex + <span class="hljs-number">1</span>)] <span class="hljs-keyword">by</span> <span class="hljs-number">-1</span>
 | 
						||
          newLineIndex = pastFragment.code.lastIndexOf <span class="hljs-string">'\n'</span>
 | 
						||
          <span class="hljs-keyword">if</span> newLineIndex <span class="hljs-keyword">is</span> <span class="hljs-number">-1</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-61">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-61">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Keep searching previous fragments until we can’t go back any
 | 
						||
further, either because there are no fragments left or we’ve
 | 
						||
discovered that we’re in a code block that is interpolated
 | 
						||
inside a string.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>            <span class="hljs-keyword">if</span> pastFragmentIndex <span class="hljs-keyword">is</span> <span class="hljs-number">0</span>
 | 
						||
              pastFragment.code = <span class="hljs-string">'\n'</span> + pastFragment.code
 | 
						||
              newLineIndex = <span class="hljs-number">0</span>
 | 
						||
            <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> pastFragment.isStringWithInterpolations <span class="hljs-keyword">and</span> pastFragment.code <span class="hljs-keyword">is</span> <span class="hljs-string">'{'</span>
 | 
						||
              code = code[<span class="hljs-number">1.</span>.] + <span class="hljs-string">'\n'</span> <span class="hljs-comment"># Move newline to end.</span>
 | 
						||
              newLineIndex = <span class="hljs-number">1</span>
 | 
						||
            <span class="hljs-keyword">else</span>
 | 
						||
              <span class="hljs-keyword">continue</span>
 | 
						||
          <span class="hljs-keyword">delete</span> fragment.precedingComments
 | 
						||
          pastFragment.code = pastFragment.code[<span class="hljs-number">0.</span>..newLineIndex] +
 | 
						||
            code + pastFragment.code[newLineIndex..]
 | 
						||
          <span class="hljs-keyword">break</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-62">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-62">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Yes, this is awfully similar to the previous <code>if</code> block, but if you
 | 
						||
look closely you’ll find lots of tiny differences that make this
 | 
						||
confusing if it were abstracted into a function that both blocks share.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      <span class="hljs-keyword">if</span> fragment.followingComments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-63">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-63">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Does the first trailing comment follow at the end of a line of code,
 | 
						||
like <code>; // Comment</code>, or does it start a new line after a line of code?</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        trail = fragment.followingComments[<span class="hljs-number">0</span>].trail
 | 
						||
        fragmentIndent = <span class="hljs-string">''</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-64">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-64">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Find the indent of the next line of code, if we have any non-trailing
 | 
						||
comments to output. We need to first find the next newline, as these
 | 
						||
comments will be output after that; and then the indent of the line
 | 
						||
that follows the next newline.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        <span class="hljs-keyword">unless</span> trail <span class="hljs-keyword">and</span> fragment.followingComments.length <span class="hljs-keyword">is</span> <span class="hljs-number">1</span>
 | 
						||
          onNextLine = <span class="hljs-literal">no</span>
 | 
						||
          <span class="hljs-keyword">for</span> upcomingFragment <span class="hljs-keyword">in</span> fragments[fragmentIndex...]
 | 
						||
            <span class="hljs-keyword">unless</span> onNextLine
 | 
						||
              <span class="hljs-keyword">if</span> <span class="hljs-string">'\n'</span> <span class="hljs-keyword">in</span> upcomingFragment.code
 | 
						||
                onNextLine = <span class="hljs-literal">yes</span>
 | 
						||
              <span class="hljs-keyword">else</span>
 | 
						||
                <span class="hljs-keyword">continue</span>
 | 
						||
            <span class="hljs-keyword">else</span>
 | 
						||
              indent = <span class="hljs-regexp">/^ {2,}/m</span>.exec upcomingFragment.code
 | 
						||
              <span class="hljs-keyword">if</span> indent
 | 
						||
                fragmentIndent = indent[<span class="hljs-number">0</span>]
 | 
						||
                <span class="hljs-keyword">break</span>
 | 
						||
              <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> <span class="hljs-string">'\n'</span> <span class="hljs-keyword">in</span> upcomingFragment.code
 | 
						||
                <span class="hljs-keyword">break</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-65">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-65">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Is this comment following the indent inserted by bare mode?
 | 
						||
If so, there’s no need to indent this further.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        code = <span class="hljs-keyword">if</span> fragmentIndex <span class="hljs-keyword">is</span> <span class="hljs-number">1</span> <span class="hljs-keyword">and</span> <span class="hljs-regexp">/^\s+$/</span>.test fragments[<span class="hljs-number">0</span>].code
 | 
						||
          <span class="hljs-string">''</span>
 | 
						||
        <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> trail
 | 
						||
          <span class="hljs-string">' '</span>
 | 
						||
        <span class="hljs-keyword">else</span>
 | 
						||
          <span class="hljs-string">"\n<span class="hljs-subst">#{fragmentIndent}</span>"</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-66">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-66">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Assemble properly indented comments.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        code += (
 | 
						||
            <span class="hljs-keyword">for</span> commentFragment <span class="hljs-keyword">in</span> fragment.followingComments
 | 
						||
              <span class="hljs-keyword">if</span> commentFragment.isHereComment <span class="hljs-keyword">and</span> commentFragment.multiline
 | 
						||
                multident commentFragment.code, fragmentIndent, <span class="hljs-literal">no</span>
 | 
						||
              <span class="hljs-keyword">else</span>
 | 
						||
                commentFragment.code
 | 
						||
          ).join(<span class="hljs-string">"\n<span class="hljs-subst">#{fragmentIndent}</span>"</span>).replace <span class="hljs-regexp">/^(\s*)$/gm</span>, <span class="hljs-string">''</span>
 | 
						||
        <span class="hljs-keyword">for</span> upcomingFragment, upcomingFragmentIndex <span class="hljs-keyword">in</span> fragments[fragmentIndex...]
 | 
						||
          newLineIndex = upcomingFragment.code.indexOf <span class="hljs-string">'\n'</span>
 | 
						||
          <span class="hljs-keyword">if</span> newLineIndex <span class="hljs-keyword">is</span> <span class="hljs-number">-1</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-67">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-67">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Keep searching upcoming fragments until we can’t go any
 | 
						||
further, either because there are no fragments left or we’ve
 | 
						||
discovered that we’re in a code block that is interpolated
 | 
						||
inside a string.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>            <span class="hljs-keyword">if</span> upcomingFragmentIndex <span class="hljs-keyword">is</span> fragments.length - <span class="hljs-number">1</span>
 | 
						||
              upcomingFragment.code = upcomingFragment.code + <span class="hljs-string">'\n'</span>
 | 
						||
              newLineIndex = upcomingFragment.code.length
 | 
						||
            <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> upcomingFragment.isStringWithInterpolations <span class="hljs-keyword">and</span> upcomingFragment.code <span class="hljs-keyword">is</span> <span class="hljs-string">'}'</span>
 | 
						||
              code = <span class="hljs-string">"<span class="hljs-subst">#{code}</span>\n"</span>
 | 
						||
              newLineIndex = <span class="hljs-number">0</span>
 | 
						||
            <span class="hljs-keyword">else</span>
 | 
						||
              <span class="hljs-keyword">continue</span>
 | 
						||
          <span class="hljs-keyword">delete</span> fragment.followingComments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-68">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-68">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Avoid inserting extra blank lines.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>          code = code.replace <span class="hljs-regexp">/^\n/</span>, <span class="hljs-string">''</span> <span class="hljs-keyword">if</span> upcomingFragment.code <span class="hljs-keyword">is</span> <span class="hljs-string">'\n'</span>
 | 
						||
          upcomingFragment.code = upcomingFragment.code[<span class="hljs-number">0.</span>..newLineIndex] +
 | 
						||
            code + upcomingFragment.code[newLineIndex..]
 | 
						||
          <span class="hljs-keyword">break</span>
 | 
						||
 | 
						||
    fragments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-69">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-69">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Wrap up the given nodes as a <strong>Block</strong>, unless it already happens
 | 
						||
to be one.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  @wrap: <span class="hljs-function"><span class="hljs-params">(nodes)</span> -></span>
 | 
						||
    <span class="hljs-keyword">return</span> nodes[<span class="hljs-number">0</span>] <span class="hljs-keyword">if</span> nodes.length <span class="hljs-keyword">is</span> <span class="hljs-number">1</span> <span class="hljs-keyword">and</span> nodes[<span class="hljs-number">0</span>] <span class="hljs-keyword">instanceof</span> Block
 | 
						||
    <span class="hljs-keyword">new</span> Block nodes</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-70">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-70">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="literal">Literal</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-71">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-71">¶</a>
 | 
						||
              </div>
 | 
						||
              <p><code>Literal</code> is a base class for static values that can be passed through
 | 
						||
directly into JavaScript without translation, such as: strings, numbers,
 | 
						||
<code>true</code>, <code>false</code>, <code>null</code>…</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Literal = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Literal</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@value)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
  shouldCache: NO
 | 
						||
 | 
						||
  assigns: <span class="hljs-function"><span class="hljs-params">(name)</span> -></span>
 | 
						||
    name <span class="hljs-keyword">is</span> @value
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    [@makeCode @value]
 | 
						||
 | 
						||
  toString: <span class="hljs-function">-></span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-72">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-72">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>This is only intended for debugging.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-string">" <span class="hljs-subst">#{<span class="hljs-keyword">if</span> @isStatement() <span class="hljs-keyword">then</span> <span class="hljs-keyword">super</span>() <span class="hljs-keyword">else</span> @constructor.name}</span>: <span class="hljs-subst">#{@value}</span>"</span>
 | 
						||
 | 
						||
exports.NumberLiteral = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NumberLiteral</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Literal</span></span>
 | 
						||
 | 
						||
exports.InfinityLiteral = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">InfinityLiteral</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">NumberLiteral</span></span>
 | 
						||
  compileNode: <span class="hljs-function">-></span>
 | 
						||
    [@makeCode <span class="hljs-string">'2e308'</span>]
 | 
						||
 | 
						||
exports.NaNLiteral = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NaNLiteral</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">NumberLiteral</span></span>
 | 
						||
  constructor: <span class="hljs-function">-></span>
 | 
						||
    <span class="hljs-keyword">super</span> <span class="hljs-string">'NaN'</span>
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    code = [@makeCode <span class="hljs-string">'0/0'</span>]
 | 
						||
    <span class="hljs-keyword">if</span> o.level >= LEVEL_OP <span class="hljs-keyword">then</span> @wrapInParentheses code <span class="hljs-keyword">else</span> code
 | 
						||
 | 
						||
exports.StringLiteral = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StringLiteral</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Literal</span></span>
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    res = <span class="hljs-keyword">if</span> @csx <span class="hljs-keyword">then</span> [@makeCode @unquote(<span class="hljs-literal">yes</span>, <span class="hljs-literal">yes</span>)] <span class="hljs-keyword">else</span> <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
  unquote: <span class="hljs-function"><span class="hljs-params">(doubleQuote = <span class="hljs-literal">no</span>, newLine = <span class="hljs-literal">no</span>)</span> -></span>
 | 
						||
    unquoted = @value[<span class="hljs-number">1.</span>..<span class="hljs-number">-1</span>]
 | 
						||
    unquoted = unquoted.replace <span class="hljs-regexp">/\\"/g</span>, <span class="hljs-string">'"'</span>  <span class="hljs-keyword">if</span> doubleQuote
 | 
						||
    unquoted = unquoted.replace <span class="hljs-regexp">/\\n/g</span>, <span class="hljs-string">'\n'</span> <span class="hljs-keyword">if</span> newLine
 | 
						||
    unquoted
 | 
						||
 | 
						||
exports.RegexLiteral = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RegexLiteral</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Literal</span></span>
 | 
						||
 | 
						||
exports.PassthroughLiteral = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PassthroughLiteral</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Literal</span></span>
 | 
						||
 | 
						||
exports.IdentifierLiteral = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IdentifierLiteral</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Literal</span></span>
 | 
						||
  isAssignable: YES
 | 
						||
 | 
						||
  eachName: <span class="hljs-function"><span class="hljs-params">(iterator)</span> -></span>
 | 
						||
    iterator @
 | 
						||
 | 
						||
exports.CSXTag = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CSXTag</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">IdentifierLiteral</span></span>
 | 
						||
 | 
						||
exports.PropertyName = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PropertyName</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Literal</span></span>
 | 
						||
  isAssignable: YES
 | 
						||
 | 
						||
exports.StatementLiteral = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StatementLiteral</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Literal</span></span>
 | 
						||
  isStatement: YES
 | 
						||
 | 
						||
  makeReturn: THIS
 | 
						||
 | 
						||
  jumps: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span> <span class="hljs-keyword">if</span> @value <span class="hljs-keyword">is</span> <span class="hljs-string">'break'</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> (o?.<span class="hljs-keyword">loop</span> <span class="hljs-keyword">or</span> o?.block)
 | 
						||
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span> <span class="hljs-keyword">if</span> @value <span class="hljs-keyword">is</span> <span class="hljs-string">'continue'</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> o?.<span class="hljs-keyword">loop</span>
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    [@makeCode <span class="hljs-string">"<span class="hljs-subst">#{@tab}</span><span class="hljs-subst">#{@value}</span>;"</span>]
 | 
						||
 | 
						||
exports.ThisLiteral = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ThisLiteral</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Literal</span></span>
 | 
						||
  constructor: <span class="hljs-function">-></span>
 | 
						||
    <span class="hljs-keyword">super</span> <span class="hljs-string">'this'</span>
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    code = <span class="hljs-keyword">if</span> o.scope.method?.bound <span class="hljs-keyword">then</span> o.scope.method.context <span class="hljs-keyword">else</span> @value
 | 
						||
    [@makeCode code]
 | 
						||
 | 
						||
exports.UndefinedLiteral = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UndefinedLiteral</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Literal</span></span>
 | 
						||
  constructor: <span class="hljs-function">-></span>
 | 
						||
    <span class="hljs-keyword">super</span> <span class="hljs-string">'undefined'</span>
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    [@makeCode <span class="hljs-keyword">if</span> o.level >= LEVEL_ACCESS <span class="hljs-keyword">then</span> <span class="hljs-string">'(void 0)'</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'void 0'</span>]
 | 
						||
 | 
						||
exports.NullLiteral = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NullLiteral</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Literal</span></span>
 | 
						||
  constructor: <span class="hljs-function">-></span>
 | 
						||
    <span class="hljs-keyword">super</span> <span class="hljs-string">'null'</span>
 | 
						||
 | 
						||
exports.BooleanLiteral = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BooleanLiteral</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Literal</span></span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-73">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-73">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="return">Return</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-74">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-74">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>A <code>return</code> is a <em>pureStatement</em>—wrapping it in a closure wouldn’t make sense.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Return = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Return</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@expression)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'expression'</span>]
 | 
						||
 | 
						||
  isStatement:     YES
 | 
						||
  makeReturn:      THIS
 | 
						||
  jumps:           THIS
 | 
						||
 | 
						||
  compileToFragments: <span class="hljs-function"><span class="hljs-params">(o, level)</span> -></span>
 | 
						||
    expr = @expression?.makeReturn()
 | 
						||
    <span class="hljs-keyword">if</span> expr <span class="hljs-keyword">and</span> expr <span class="hljs-keyword">not</span> <span class="hljs-keyword">instanceof</span> Return <span class="hljs-keyword">then</span> expr.compileToFragments o, level <span class="hljs-keyword">else</span> <span class="hljs-keyword">super</span> o, level
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    answer = []</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-75">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-75">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>TODO: If we call <code>expression.compile()</code> here twice, we’ll sometimes
 | 
						||
get back different results!</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> @expression
 | 
						||
      answer = @expression.compileToFragments o, LEVEL_PAREN
 | 
						||
      unshiftAfterComments answer, @makeCode <span class="hljs-string">"<span class="hljs-subst">#{@tab}</span>return "</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-76">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-76">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Since the <code>return</code> got indented by <code>@tab</code>, preceding comments that are
 | 
						||
multiline need to be indented.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      <span class="hljs-keyword">for</span> fragment <span class="hljs-keyword">in</span> answer
 | 
						||
        <span class="hljs-keyword">if</span> fragment.isHereComment <span class="hljs-keyword">and</span> <span class="hljs-string">'\n'</span> <span class="hljs-keyword">in</span> fragment.code
 | 
						||
          fragment.code = multident fragment.code, @tab
 | 
						||
        <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> fragment.isLineComment
 | 
						||
          fragment.code = <span class="hljs-string">"<span class="hljs-subst">#{@tab}</span><span class="hljs-subst">#{fragment.code}</span>"</span>
 | 
						||
        <span class="hljs-keyword">else</span>
 | 
						||
          <span class="hljs-keyword">break</span>
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      answer.push @makeCode <span class="hljs-string">"<span class="hljs-subst">#{@tab}</span>return"</span>
 | 
						||
    answer.push @makeCode <span class="hljs-string">';'</span>
 | 
						||
    answer</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-77">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-77">¶</a>
 | 
						||
              </div>
 | 
						||
              <p><code>yield return</code> works exactly like <code>return</code>, except that it turns the function
 | 
						||
into a generator.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.YieldReturn = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">YieldReturn</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Return</span></span>
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    <span class="hljs-keyword">unless</span> o.scope.parent?
 | 
						||
      @error <span class="hljs-string">'yield can only occur inside functions'</span>
 | 
						||
    <span class="hljs-keyword">super</span> o
 | 
						||
 | 
						||
exports.AwaitReturn = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AwaitReturn</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Return</span></span>
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    <span class="hljs-keyword">unless</span> o.scope.parent?
 | 
						||
      @error <span class="hljs-string">'await can only occur inside functions'</span>
 | 
						||
    <span class="hljs-keyword">super</span> o</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-78">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-78">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="value">Value</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-79">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-79">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>A value, variable or literal or parenthesized, indexed or dotted into,
 | 
						||
or vanilla.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Value = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Value</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(base, props, tag, isDefaultValue = <span class="hljs-literal">no</span>)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
    <span class="hljs-keyword">return</span> base <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> props <span class="hljs-keyword">and</span> base <span class="hljs-keyword">instanceof</span> Value
 | 
						||
    @base           = base
 | 
						||
    @properties     = props <span class="hljs-keyword">or</span> []
 | 
						||
    @[tag]          = <span class="hljs-literal">yes</span> <span class="hljs-keyword">if</span> tag
 | 
						||
    @isDefaultValue = isDefaultValue</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-80">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-80">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>If this is a <code>@foo =</code> assignment, if there are comments on <code>@</code> move them
 | 
						||
to be on <code>foo</code>.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> @base?.comments <span class="hljs-keyword">and</span> @base <span class="hljs-keyword">instanceof</span> ThisLiteral <span class="hljs-keyword">and</span> @properties[<span class="hljs-number">0</span>]?.name?
 | 
						||
      moveComments @base, @properties[<span class="hljs-number">0</span>].name
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'base'</span>, <span class="hljs-string">'properties'</span>]</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-81">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-81">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Add a property (or <em>properties</em> ) <code>Access</code> to the list.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  add: <span class="hljs-function"><span class="hljs-params">(props)</span> -></span>
 | 
						||
    @properties = @properties.concat props
 | 
						||
    @forceUpdateLocation = <span class="hljs-literal">yes</span>
 | 
						||
    <span class="hljs-keyword">this</span>
 | 
						||
 | 
						||
  hasProperties: <span class="hljs-function">-></span>
 | 
						||
    @properties.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span>
 | 
						||
 | 
						||
  bareLiteral: <span class="hljs-function"><span class="hljs-params">(type)</span> -></span>
 | 
						||
    <span class="hljs-keyword">not</span> @properties.length <span class="hljs-keyword">and</span> @base <span class="hljs-keyword">instanceof</span> type</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-82">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-82">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Some boolean checks for the benefit of other nodes.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  isArray        : <span class="hljs-function">-></span> @bareLiteral(Arr)
 | 
						||
  isRange        : <span class="hljs-function">-></span> @bareLiteral(Range)
 | 
						||
  shouldCache    : <span class="hljs-function">-></span> @hasProperties() <span class="hljs-keyword">or</span> @base.shouldCache()
 | 
						||
  isAssignable   : <span class="hljs-function">-></span> @hasProperties() <span class="hljs-keyword">or</span> @base.isAssignable()
 | 
						||
  isNumber       : <span class="hljs-function">-></span> @bareLiteral(NumberLiteral)
 | 
						||
  isString       : <span class="hljs-function">-></span> @bareLiteral(StringLiteral)
 | 
						||
  isRegex        : <span class="hljs-function">-></span> @bareLiteral(RegexLiteral)
 | 
						||
  isUndefined    : <span class="hljs-function">-></span> @bareLiteral(UndefinedLiteral)
 | 
						||
  isNull         : <span class="hljs-function">-></span> @bareLiteral(NullLiteral)
 | 
						||
  isBoolean      : <span class="hljs-function">-></span> @bareLiteral(BooleanLiteral)
 | 
						||
  isAtomic       : <span class="hljs-function">-></span>
 | 
						||
    <span class="hljs-keyword">for</span> node <span class="hljs-keyword">in</span> @properties.concat @base
 | 
						||
      <span class="hljs-keyword">return</span> <span class="hljs-literal">no</span> <span class="hljs-keyword">if</span> node.soak <span class="hljs-keyword">or</span> node <span class="hljs-keyword">instanceof</span> Call
 | 
						||
    <span class="hljs-literal">yes</span>
 | 
						||
 | 
						||
  isNotCallable  : <span class="hljs-function">-></span> @isNumber() <span class="hljs-keyword">or</span> @isString() <span class="hljs-keyword">or</span> @isRegex() <span class="hljs-keyword">or</span>
 | 
						||
                      @isArray() <span class="hljs-keyword">or</span> @isRange() <span class="hljs-keyword">or</span> @isSplice() <span class="hljs-keyword">or</span> @isObject() <span class="hljs-keyword">or</span>
 | 
						||
                      @isUndefined() <span class="hljs-keyword">or</span> @isNull() <span class="hljs-keyword">or</span> @isBoolean()
 | 
						||
 | 
						||
  isStatement : <span class="hljs-function"><span class="hljs-params">(o)</span>    -></span> <span class="hljs-keyword">not</span> @properties.length <span class="hljs-keyword">and</span> @base.isStatement o
 | 
						||
  assigns     : <span class="hljs-function"><span class="hljs-params">(name)</span> -></span> <span class="hljs-keyword">not</span> @properties.length <span class="hljs-keyword">and</span> @base.assigns name
 | 
						||
  jumps       : <span class="hljs-function"><span class="hljs-params">(o)</span>    -></span> <span class="hljs-keyword">not</span> @properties.length <span class="hljs-keyword">and</span> @base.jumps o
 | 
						||
 | 
						||
  isObject: <span class="hljs-function"><span class="hljs-params">(onlyGenerated)</span> -></span>
 | 
						||
    <span class="hljs-keyword">return</span> <span class="hljs-literal">no</span> <span class="hljs-keyword">if</span> @properties.length
 | 
						||
    (@base <span class="hljs-keyword">instanceof</span> Obj) <span class="hljs-keyword">and</span> (<span class="hljs-keyword">not</span> onlyGenerated <span class="hljs-keyword">or</span> @base.generated)
 | 
						||
 | 
						||
  isSplice: <span class="hljs-function">-></span>
 | 
						||
    [..., lastProp] = @properties
 | 
						||
    lastProp <span class="hljs-keyword">instanceof</span> Slice
 | 
						||
 | 
						||
  looksStatic: <span class="hljs-function"><span class="hljs-params">(className)</span> -></span>
 | 
						||
    (@this <span class="hljs-keyword">or</span> @base <span class="hljs-keyword">instanceof</span> ThisLiteral <span class="hljs-keyword">or</span> @base.value <span class="hljs-keyword">is</span> className) <span class="hljs-keyword">and</span>
 | 
						||
      @properties.length <span class="hljs-keyword">is</span> <span class="hljs-number">1</span> <span class="hljs-keyword">and</span> @properties[<span class="hljs-number">0</span>].name?.value <span class="hljs-keyword">isnt</span> <span class="hljs-string">'prototype'</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-83">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-83">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>The value can be unwrapped as its inner node, if there are no attached
 | 
						||
properties.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  unwrap: <span class="hljs-function">-></span>
 | 
						||
    <span class="hljs-keyword">if</span> @properties.length <span class="hljs-keyword">then</span> <span class="hljs-keyword">this</span> <span class="hljs-keyword">else</span> @base</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-84">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-84">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>A reference has base part (<code>this</code> value) and name part.
 | 
						||
We cache them separately for compiling complex expressions.
 | 
						||
<code>a()[b()] ?= c</code> -> <code>(_base = a())[_name = b()] ? _base[_name] = c</code></p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  cacheReference: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    [..., name] = @properties
 | 
						||
    <span class="hljs-keyword">if</span> @properties.length < <span class="hljs-number">2</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @base.shouldCache() <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> name?.shouldCache()
 | 
						||
      <span class="hljs-keyword">return</span> [<span class="hljs-keyword">this</span>, <span class="hljs-keyword">this</span>]  <span class="hljs-comment"># `a` `a.b`</span>
 | 
						||
    base = <span class="hljs-keyword">new</span> Value @base, @properties[...<span class="hljs-number">-1</span>]
 | 
						||
    <span class="hljs-keyword">if</span> base.shouldCache()  <span class="hljs-comment"># `a().b`</span>
 | 
						||
      bref = <span class="hljs-keyword">new</span> IdentifierLiteral o.scope.freeVariable <span class="hljs-string">'base'</span>
 | 
						||
      base = <span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Parens <span class="hljs-keyword">new</span> Assign bref, base
 | 
						||
    <span class="hljs-keyword">return</span> [base, bref] <span class="hljs-keyword">unless</span> name  <span class="hljs-comment"># `a()`</span>
 | 
						||
    <span class="hljs-keyword">if</span> name.shouldCache()  <span class="hljs-comment"># `a[b()]`</span>
 | 
						||
      nref = <span class="hljs-keyword">new</span> IdentifierLiteral o.scope.freeVariable <span class="hljs-string">'name'</span>
 | 
						||
      name = <span class="hljs-keyword">new</span> Index <span class="hljs-keyword">new</span> Assign nref, name.index
 | 
						||
      nref = <span class="hljs-keyword">new</span> Index nref
 | 
						||
    [base.add(name), <span class="hljs-keyword">new</span> Value(bref <span class="hljs-keyword">or</span> base.base, [nref <span class="hljs-keyword">or</span> name])]</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-85">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-85">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>We compile a value to JavaScript by compiling and joining each property.
 | 
						||
Things get much more interesting if the chain of properties has <em>soak</em>
 | 
						||
operators <code>?.</code> interspersed. Then we have to take care not to accidentally
 | 
						||
evaluate anything twice when building the soak chain.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    @base.front = @front
 | 
						||
    props = @properties
 | 
						||
    fragments = @base.compileToFragments o, (<span class="hljs-keyword">if</span> props.length <span class="hljs-keyword">then</span> LEVEL_ACCESS <span class="hljs-keyword">else</span> <span class="hljs-literal">null</span>)
 | 
						||
    <span class="hljs-keyword">if</span> props.length <span class="hljs-keyword">and</span> SIMPLENUM.test fragmentsToText fragments
 | 
						||
      fragments.push @makeCode <span class="hljs-string">'.'</span>
 | 
						||
    <span class="hljs-keyword">for</span> prop <span class="hljs-keyword">in</span> props
 | 
						||
      fragments.push (prop.compileToFragments o)...
 | 
						||
    fragments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-86">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-86">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Unfold a soak into an <code>If</code>: <code>a?.b</code> -> <code>a.b if a?</code></p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  unfoldSoak: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    @unfoldedSoak ?= <span class="hljs-keyword">do</span> =>
 | 
						||
      ifn = @base.unfoldSoak o
 | 
						||
      <span class="hljs-keyword">if</span> ifn
 | 
						||
        ifn.body.properties.push @properties...
 | 
						||
        <span class="hljs-keyword">return</span> ifn
 | 
						||
      <span class="hljs-keyword">for</span> prop, i <span class="hljs-keyword">in</span> @properties <span class="hljs-keyword">when</span> prop.soak
 | 
						||
        prop.soak = <span class="hljs-literal">off</span>
 | 
						||
        fst = <span class="hljs-keyword">new</span> Value @base, @properties[...i]
 | 
						||
        snd = <span class="hljs-keyword">new</span> Value @base, @properties[i..]
 | 
						||
        <span class="hljs-keyword">if</span> fst.shouldCache()
 | 
						||
          ref = <span class="hljs-keyword">new</span> IdentifierLiteral o.scope.freeVariable <span class="hljs-string">'ref'</span>
 | 
						||
          fst = <span class="hljs-keyword">new</span> Parens <span class="hljs-keyword">new</span> Assign ref, fst
 | 
						||
          snd.base = ref
 | 
						||
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> If <span class="hljs-keyword">new</span> Existence(fst), snd, soak: <span class="hljs-literal">on</span>
 | 
						||
      <span class="hljs-literal">no</span>
 | 
						||
 | 
						||
  eachName: <span class="hljs-function"><span class="hljs-params">(iterator)</span> -></span>
 | 
						||
    <span class="hljs-keyword">if</span> @hasProperties()
 | 
						||
      iterator @
 | 
						||
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> @base.isAssignable()
 | 
						||
      @base.eachName iterator
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      @error <span class="hljs-string">'tried to assign to unassignable value'</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-87">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-87">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="herecomment">HereComment</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-88">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-88">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Comment delimited by <code>###</code> (becoming <code>/* */</code>).</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.HereComment = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HereComment</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">({ @content, @newLine, @unshift })</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    multiline = <span class="hljs-string">'\n'</span> <span class="hljs-keyword">in</span> @content
 | 
						||
    hasLeadingMarks = <span class="hljs-regexp">/\n\s*[#|\*]/</span>.test @content
 | 
						||
    @content = @content.replace <span class="hljs-regexp">/^([ \t]*)#(?=\s)/gm</span>, <span class="hljs-string">' *'</span> <span class="hljs-keyword">if</span> hasLeadingMarks</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-89">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-89">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Unindent multiline comments. They will be reindented later.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> multiline
 | 
						||
      largestIndent = <span class="hljs-string">''</span>
 | 
						||
      <span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> @content.split <span class="hljs-string">'\n'</span>
 | 
						||
        leadingWhitespace = <span class="hljs-regexp">/^\s*/</span>.exec(line)[<span class="hljs-number">0</span>]
 | 
						||
        <span class="hljs-keyword">if</span> leadingWhitespace.length > largestIndent.length
 | 
						||
          largestIndent = leadingWhitespace
 | 
						||
      @content = @content.replace <span class="hljs-regexp">///^(<span class="hljs-subst">#{leadingWhitespace}</span>)///</span>gm, <span class="hljs-string">''</span>
 | 
						||
 | 
						||
    @content = <span class="hljs-string">"/*<span class="hljs-subst">#{@content}</span><span class="hljs-subst">#{<span class="hljs-keyword">if</span> hasLeadingMarks <span class="hljs-keyword">then</span> <span class="hljs-string">' '</span> <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>}</span>*/"</span>
 | 
						||
    fragment = @makeCode @content
 | 
						||
    fragment.newLine = @newLine
 | 
						||
    fragment.unshift = @unshift
 | 
						||
    fragment.multiline = multiline</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-90">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-90">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Don’t rely on <code>fragment.type</code>, which can break when the compiler is minified.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    fragment.isComment = fragment.isHereComment = <span class="hljs-literal">yes</span>
 | 
						||
    fragment</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-91">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-91">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="linecomment">LineComment</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-92">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-92">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Comment running from <code>#</code> to the end of a line (becoming <code>//</code>).</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.LineComment = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LineComment</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">({ @content, @newLine, @unshift })</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    fragment = @makeCode(<span class="hljs-keyword">if</span> <span class="hljs-regexp">/^\s*$/</span>.test @content <span class="hljs-keyword">then</span> <span class="hljs-string">''</span> <span class="hljs-keyword">else</span> <span class="hljs-string">"//<span class="hljs-subst">#{@content}</span>"</span>)
 | 
						||
    fragment.newLine = @newLine
 | 
						||
    fragment.unshift = @unshift
 | 
						||
    fragment.trail = <span class="hljs-keyword">not</span> @newLine <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @unshift</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-93">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-93">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Don’t rely on <code>fragment.type</code>, which can break when the compiler is minified.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    fragment.isComment = fragment.isLineComment = <span class="hljs-literal">yes</span>
 | 
						||
    fragment</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-94">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-94">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="call">Call</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-95">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-95">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Node for a function invocation.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Call = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Call</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@variable, @args = [], @soak, @token)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
    @isNew = <span class="hljs-literal">no</span>
 | 
						||
    <span class="hljs-keyword">if</span> @variable <span class="hljs-keyword">instanceof</span> Value <span class="hljs-keyword">and</span> @variable.isNotCallable()
 | 
						||
      @variable.error <span class="hljs-string">"literal is not a function"</span>
 | 
						||
 | 
						||
    @csx = @variable.base <span class="hljs-keyword">instanceof</span> CSXTag</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-96">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-96">¶</a>
 | 
						||
              </div>
 | 
						||
              <p><code>@variable</code> never gets output as a result of this node getting created as
 | 
						||
part of <code>RegexWithInterpolations</code>, so for that case move any comments to
 | 
						||
the <code>args</code> property that gets passed into <code>RegexWithInterpolations</code> via
 | 
						||
the grammar.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> @variable.base?.value <span class="hljs-keyword">is</span> <span class="hljs-string">'RegExp'</span> <span class="hljs-keyword">and</span> @args.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span>
 | 
						||
      moveComments @variable, @args[<span class="hljs-number">0</span>]
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'variable'</span>, <span class="hljs-string">'args'</span>]</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-97">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-97">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>When setting the location, we sometimes need to update the start location to
 | 
						||
account for a newly-discovered <code>new</code> operator to the left of us. This
 | 
						||
expands the range on the left, but not the right.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  updateLocationDataIfMissing: <span class="hljs-function"><span class="hljs-params">(locationData)</span> -></span>
 | 
						||
    <span class="hljs-keyword">if</span> @locationData <span class="hljs-keyword">and</span> @needsUpdatedStartLocation
 | 
						||
      @locationData.first_line = locationData.first_line
 | 
						||
      @locationData.first_column = locationData.first_column
 | 
						||
      base = @variable?.base <span class="hljs-keyword">or</span> @variable
 | 
						||
      <span class="hljs-keyword">if</span> base.needsUpdatedStartLocation
 | 
						||
        @variable.locationData.first_line = locationData.first_line
 | 
						||
        @variable.locationData.first_column = locationData.first_column
 | 
						||
        base.updateLocationDataIfMissing locationData
 | 
						||
      <span class="hljs-keyword">delete</span> @needsUpdatedStartLocation
 | 
						||
    <span class="hljs-keyword">super</span> locationData</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-98">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-98">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Tag this invocation as creating a new instance.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  newInstance: <span class="hljs-function">-></span>
 | 
						||
    base = @variable?.base <span class="hljs-keyword">or</span> @variable
 | 
						||
    <span class="hljs-keyword">if</span> base <span class="hljs-keyword">instanceof</span> Call <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> base.isNew
 | 
						||
      base.newInstance()
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      @isNew = <span class="hljs-literal">true</span>
 | 
						||
    @needsUpdatedStartLocation = <span class="hljs-literal">true</span>
 | 
						||
    <span class="hljs-keyword">this</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-99">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-99">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Soaked chained invocations unfold into if/else ternary structures.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  unfoldSoak: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    <span class="hljs-keyword">if</span> @soak
 | 
						||
      <span class="hljs-keyword">if</span> @variable <span class="hljs-keyword">instanceof</span> Super
 | 
						||
        left = <span class="hljs-keyword">new</span> Literal @variable.compile o
 | 
						||
        rite = <span class="hljs-keyword">new</span> Value left
 | 
						||
        @variable.error <span class="hljs-string">"Unsupported reference to 'super'"</span> <span class="hljs-keyword">unless</span> @variable.accessor?
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        <span class="hljs-keyword">return</span> ifn <span class="hljs-keyword">if</span> ifn = unfoldSoak o, <span class="hljs-keyword">this</span>, <span class="hljs-string">'variable'</span>
 | 
						||
        [left, rite] = <span class="hljs-keyword">new</span> Value(@variable).cacheReference o
 | 
						||
      rite = <span class="hljs-keyword">new</span> Call rite, @args
 | 
						||
      rite.isNew = @isNew
 | 
						||
      left = <span class="hljs-keyword">new</span> Literal <span class="hljs-string">"typeof <span class="hljs-subst">#{ left.compile o }</span> === \"function\""</span>
 | 
						||
      <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> If left, <span class="hljs-keyword">new</span> Value(rite), soak: <span class="hljs-literal">yes</span>
 | 
						||
    call = <span class="hljs-keyword">this</span>
 | 
						||
    list = []
 | 
						||
    <span class="hljs-keyword">loop</span>
 | 
						||
      <span class="hljs-keyword">if</span> call.variable <span class="hljs-keyword">instanceof</span> Call
 | 
						||
        list.push call
 | 
						||
        call = call.variable
 | 
						||
        <span class="hljs-keyword">continue</span>
 | 
						||
      <span class="hljs-keyword">break</span> <span class="hljs-keyword">unless</span> call.variable <span class="hljs-keyword">instanceof</span> Value
 | 
						||
      list.push call
 | 
						||
      <span class="hljs-keyword">break</span> <span class="hljs-keyword">unless</span> (call = call.variable.base) <span class="hljs-keyword">instanceof</span> Call
 | 
						||
    <span class="hljs-keyword">for</span> call <span class="hljs-keyword">in</span> list.reverse()
 | 
						||
      <span class="hljs-keyword">if</span> ifn
 | 
						||
        <span class="hljs-keyword">if</span> call.variable <span class="hljs-keyword">instanceof</span> Call
 | 
						||
          call.variable = ifn
 | 
						||
        <span class="hljs-keyword">else</span>
 | 
						||
          call.variable.base = ifn
 | 
						||
      ifn = unfoldSoak o, call, <span class="hljs-string">'variable'</span>
 | 
						||
    ifn</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-100">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-100">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Compile a vanilla function call.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    <span class="hljs-keyword">return</span> @compileCSX o <span class="hljs-keyword">if</span> @csx
 | 
						||
    @variable?.front = @front
 | 
						||
    compiledArgs = []
 | 
						||
    <span class="hljs-keyword">for</span> arg, argIndex <span class="hljs-keyword">in</span> @args
 | 
						||
      <span class="hljs-keyword">if</span> argIndex <span class="hljs-keyword">then</span> compiledArgs.push @makeCode <span class="hljs-string">", "</span>
 | 
						||
      compiledArgs.push (arg.compileToFragments o, LEVEL_LIST)...
 | 
						||
 | 
						||
    fragments = []
 | 
						||
    <span class="hljs-keyword">if</span> @isNew
 | 
						||
      @variable.error <span class="hljs-string">"Unsupported reference to 'super'"</span> <span class="hljs-keyword">if</span> @variable <span class="hljs-keyword">instanceof</span> Super
 | 
						||
      fragments.push @makeCode <span class="hljs-string">'new '</span>
 | 
						||
    fragments.push @variable.compileToFragments(o, LEVEL_ACCESS)...
 | 
						||
    fragments.push @makeCode(<span class="hljs-string">'('</span>), compiledArgs..., @makeCode(<span class="hljs-string">')'</span>)
 | 
						||
    fragments
 | 
						||
 | 
						||
  compileCSX: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    [attributes, content] = @args
 | 
						||
    attributes.base.csx = <span class="hljs-literal">yes</span>
 | 
						||
    content?.base.csx = <span class="hljs-literal">yes</span>
 | 
						||
    fragments = [@makeCode(<span class="hljs-string">'<'</span>)]
 | 
						||
    fragments.push (tag = @variable.compileToFragments(o, LEVEL_ACCESS))...
 | 
						||
    <span class="hljs-keyword">if</span> attributes.base <span class="hljs-keyword">instanceof</span> Arr
 | 
						||
      <span class="hljs-keyword">for</span> obj <span class="hljs-keyword">in</span> attributes.base.objects
 | 
						||
        attr = obj.base
 | 
						||
        attrProps = attr?.properties <span class="hljs-keyword">or</span> []</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-101">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-101">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Catch invalid CSX attributes: <div {a:"b", props} {props} "value" /></p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> (attr <span class="hljs-keyword">instanceof</span> Obj <span class="hljs-keyword">or</span> attr <span class="hljs-keyword">instanceof</span> IdentifierLiteral) <span class="hljs-keyword">or</span> (attr <span class="hljs-keyword">instanceof</span> Obj <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> attr.generated <span class="hljs-keyword">and</span> (attrProps.length > <span class="hljs-number">1</span> <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> (attrProps[<span class="hljs-number">0</span>] <span class="hljs-keyword">instanceof</span> Splat)))
 | 
						||
          obj.error <span class="hljs-string">"""
 | 
						||
            Unexpected token. Allowed CSX attributes are: id="val", src={source}, {props...} or attribute.
 | 
						||
          """</span>
 | 
						||
        obj.base.csx = <span class="hljs-literal">yes</span> <span class="hljs-keyword">if</span> obj.base <span class="hljs-keyword">instanceof</span> Obj
 | 
						||
        fragments.push @makeCode <span class="hljs-string">' '</span>
 | 
						||
        fragments.push obj.compileToFragments(o, LEVEL_PAREN)...
 | 
						||
    <span class="hljs-keyword">if</span> content
 | 
						||
      fragments.push @makeCode(<span class="hljs-string">'>'</span>)
 | 
						||
      fragments.push content.compileNode(o, LEVEL_LIST)...
 | 
						||
      fragments.push [@makeCode(<span class="hljs-string">'</'</span>), tag..., @makeCode(<span class="hljs-string">'>'</span>)]...
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      fragments.push @makeCode(<span class="hljs-string">' />'</span>)
 | 
						||
    fragments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-102">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-102">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="super">Super</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-103">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-103">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Takes care of converting <code>super()</code> calls into calls against the prototype’s
 | 
						||
function of the same name.
 | 
						||
When <code>expressions</code> are set the call will be compiled in such a way that the
 | 
						||
expressions are evaluated without altering the return value of the <code>SuperCall</code>
 | 
						||
expression.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.SuperCall = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SuperCall</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Call</span></span>
 | 
						||
  children: Call::children.concat [<span class="hljs-string">'expressions'</span>]
 | 
						||
 | 
						||
  isStatement: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    @expressions?.length <span class="hljs-keyword">and</span> o.level <span class="hljs-keyword">is</span> LEVEL_TOP
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span> o <span class="hljs-keyword">unless</span> @expressions?.length
 | 
						||
 | 
						||
    superCall   = <span class="hljs-keyword">new</span> Literal fragmentsToText <span class="hljs-keyword">super</span> o
 | 
						||
    replacement = <span class="hljs-keyword">new</span> Block @expressions.slice()
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> o.level > LEVEL_TOP</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-104">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-104">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>If we might be in an expression we need to cache and return the result</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      [superCall, ref] = superCall.cache o, <span class="hljs-literal">null</span>, YES
 | 
						||
      replacement.push ref
 | 
						||
 | 
						||
    replacement.unshift superCall
 | 
						||
    replacement.compileToFragments o, <span class="hljs-keyword">if</span> o.level <span class="hljs-keyword">is</span> LEVEL_TOP <span class="hljs-keyword">then</span> o.level <span class="hljs-keyword">else</span> LEVEL_LIST
 | 
						||
 | 
						||
exports.Super = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Super</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@accessor)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'accessor'</span>]
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    method = o.scope.namedMethod()
 | 
						||
    @error <span class="hljs-string">'cannot use super outside of an instance method'</span> <span class="hljs-keyword">unless</span> method?.isMethod
 | 
						||
 | 
						||
    <span class="hljs-keyword">unless</span> method.ctor? <span class="hljs-keyword">or</span> @accessor?
 | 
						||
      {name, variable} = method
 | 
						||
      <span class="hljs-keyword">if</span> name.shouldCache() <span class="hljs-keyword">or</span> (name <span class="hljs-keyword">instanceof</span> Index <span class="hljs-keyword">and</span> name.index.isAssignable())
 | 
						||
        nref = <span class="hljs-keyword">new</span> IdentifierLiteral o.scope.parent.freeVariable <span class="hljs-string">'name'</span>
 | 
						||
        name.index = <span class="hljs-keyword">new</span> Assign nref, name.index
 | 
						||
      @accessor = <span class="hljs-keyword">if</span> nref? <span class="hljs-keyword">then</span> <span class="hljs-keyword">new</span> Index nref <span class="hljs-keyword">else</span> name
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> @accessor?.name?.comments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-105">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-105">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>A <code>super()</code> call gets compiled to e.g. <code>super.method()</code>, which means
 | 
						||
the <code>method</code> property name gets compiled for the first time here, and
 | 
						||
again when the <code>method:</code> property of the class gets compiled. Since
 | 
						||
this compilation happens first, comments attached to <code>method:</code> would
 | 
						||
get incorrectly output near <code>super.method()</code>, when we want them to
 | 
						||
get output on the second pass when <code>method:</code> is output. So set them
 | 
						||
aside during this compilation pass, and put them back on the object so
 | 
						||
that they’re there for the later compilation.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      salvagedComments = @accessor.name.comments
 | 
						||
      <span class="hljs-keyword">delete</span> @accessor.name.comments
 | 
						||
    fragments = (<span class="hljs-keyword">new</span> Value (<span class="hljs-keyword">new</span> Literal <span class="hljs-string">'super'</span>), <span class="hljs-keyword">if</span> @accessor <span class="hljs-keyword">then</span> [ @accessor ] <span class="hljs-keyword">else</span> [])
 | 
						||
    .compileToFragments o
 | 
						||
    attachCommentsToNode salvagedComments, @accessor.name <span class="hljs-keyword">if</span> salvagedComments
 | 
						||
    fragments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-106">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-106">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="regexwithinterpolations">RegexWithInterpolations</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-107">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-107">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Regexes with interpolations are in fact just a variation of a <code>Call</code> (a
 | 
						||
<code>RegExp()</code> call to be precise) with a <code>StringWithInterpolations</code> inside.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.RegexWithInterpolations = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RegexWithInterpolations</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Call</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(args = [])</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span> (<span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> IdentifierLiteral <span class="hljs-string">'RegExp'</span>), args, <span class="hljs-literal">false</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-108">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-108">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="taggedtemplatecall">TaggedTemplateCall</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>
 | 
						||
exports.TaggedTemplateCall = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TaggedTemplateCall</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Call</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(variable, arg, soak)</span> -></span>
 | 
						||
    arg = <span class="hljs-keyword">new</span> StringWithInterpolations Block.wrap([ <span class="hljs-keyword">new</span> Value arg ]) <span class="hljs-keyword">if</span> arg <span class="hljs-keyword">instanceof</span> StringLiteral
 | 
						||
    <span class="hljs-keyword">super</span> variable, [ arg ], soak
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    @variable.compileToFragments(o, LEVEL_ACCESS).concat @args[<span class="hljs-number">0</span>].compileToFragments(o, LEVEL_LIST)</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-109">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-109">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="extends">Extends</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-110">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-110">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Node to extend an object’s prototype with an ancestor object.
 | 
						||
After <code>goog.inherits</code> from the
 | 
						||
<a href="https://github.com/google/closure-library/blob/master/closure/goog/base.js">Closure Library</a>.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Extends = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Extends</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@child, @parent)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'child'</span>, <span class="hljs-string">'parent'</span>]</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-111">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-111">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Hooks one constructor into another’s prototype chain.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileToFragments: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    <span class="hljs-keyword">new</span> Call(<span class="hljs-keyword">new</span> Value(<span class="hljs-keyword">new</span> Literal utility <span class="hljs-string">'extend'</span>, o), [@child, @parent]).compileToFragments o</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-112">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-112">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="access">Access</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-113">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-113">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>A <code>.</code> access into a property of a value, or the <code>::</code> shorthand for
 | 
						||
an access into the object’s prototype.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Access = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Access</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@name, tag)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
    @soak  = tag <span class="hljs-keyword">is</span> <span class="hljs-string">'soak'</span>
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'name'</span>]
 | 
						||
 | 
						||
  compileToFragments: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    name = @name.compileToFragments o
 | 
						||
    node = @name.unwrap()
 | 
						||
    <span class="hljs-keyword">if</span> node <span class="hljs-keyword">instanceof</span> PropertyName
 | 
						||
      [@makeCode(<span class="hljs-string">'.'</span>), name...]
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      [@makeCode(<span class="hljs-string">'['</span>), name..., @makeCode(<span class="hljs-string">']'</span>)]
 | 
						||
 | 
						||
  shouldCache: NO</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-114">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-114">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="index">Index</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-115">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-115">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>A <code>[ ... ]</code> indexed access into an array or object.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Index = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Index</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@index)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'index'</span>]
 | 
						||
 | 
						||
  compileToFragments: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    [].concat @makeCode(<span class="hljs-string">"["</span>), @index.compileToFragments(o, LEVEL_PAREN), @makeCode(<span class="hljs-string">"]"</span>)
 | 
						||
 | 
						||
  shouldCache: <span class="hljs-function">-></span>
 | 
						||
    @index.shouldCache()</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-116">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-116">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="range">Range</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-117">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-117">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>A range literal. Ranges can be used to extract portions (slices) of arrays,
 | 
						||
to specify a range for comprehensions, or as a value, to be expanded into the
 | 
						||
corresponding array of integers at runtime.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Range = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Range</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'from'</span>, <span class="hljs-string">'to'</span>]
 | 
						||
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@from, @to, tag)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
    @exclusive = tag <span class="hljs-keyword">is</span> <span class="hljs-string">'exclusive'</span>
 | 
						||
    @equals = <span class="hljs-keyword">if</span> @exclusive <span class="hljs-keyword">then</span> <span class="hljs-string">''</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'='</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-118">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-118">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Compiles the range’s source variables – where it starts and where it ends.
 | 
						||
But only if they need to be cached to avoid double evaluation.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileVariables: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    o = merge o, top: <span class="hljs-literal">true</span>
 | 
						||
    shouldCache = del o, <span class="hljs-string">'shouldCache'</span>
 | 
						||
    [@fromC, @fromVar] = @cacheToCodeFragments @from.cache o, LEVEL_LIST, shouldCache
 | 
						||
    [@toC, @toVar]     = @cacheToCodeFragments @to.cache o, LEVEL_LIST, shouldCache
 | 
						||
    [@step, @stepVar]  = @cacheToCodeFragments step.cache o, LEVEL_LIST, shouldCache <span class="hljs-keyword">if</span> step = del o, <span class="hljs-string">'step'</span>
 | 
						||
    @fromNum = <span class="hljs-keyword">if</span> @from.isNumber() <span class="hljs-keyword">then</span> Number @fromVar <span class="hljs-keyword">else</span> <span class="hljs-literal">null</span>
 | 
						||
    @toNum   = <span class="hljs-keyword">if</span> @to.isNumber()   <span class="hljs-keyword">then</span> Number @toVar   <span class="hljs-keyword">else</span> <span class="hljs-literal">null</span>
 | 
						||
    @stepNum = <span class="hljs-keyword">if</span> step?.isNumber() <span class="hljs-keyword">then</span> Number @stepVar <span class="hljs-keyword">else</span> <span class="hljs-literal">null</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-119">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-119">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>When compiled normally, the range returns the contents of the <em>for loop</em>
 | 
						||
needed to iterate over the values in the range. Used by comprehensions.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    @compileVariables o <span class="hljs-keyword">unless</span> @fromVar
 | 
						||
    <span class="hljs-keyword">return</span> @compileArray(o) <span class="hljs-keyword">unless</span> o.index</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-120">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-120">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Set up endpoints.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    known    = @fromNum? <span class="hljs-keyword">and</span> @toNum?
 | 
						||
    idx      = del o, <span class="hljs-string">'index'</span>
 | 
						||
    idxName  = del o, <span class="hljs-string">'name'</span>
 | 
						||
    namedIndex = idxName <span class="hljs-keyword">and</span> idxName <span class="hljs-keyword">isnt</span> idx
 | 
						||
    varPart  = <span class="hljs-string">"<span class="hljs-subst">#{idx}</span> = <span class="hljs-subst">#{@fromC}</span>"</span>
 | 
						||
    varPart += <span class="hljs-string">", <span class="hljs-subst">#{@toC}</span>"</span> <span class="hljs-keyword">if</span> @toC <span class="hljs-keyword">isnt</span> @toVar
 | 
						||
    varPart += <span class="hljs-string">", <span class="hljs-subst">#{@step}</span>"</span> <span class="hljs-keyword">if</span> @step <span class="hljs-keyword">isnt</span> @stepVar
 | 
						||
    [lt, gt] = [<span class="hljs-string">"<span class="hljs-subst">#{idx}</span> <<span class="hljs-subst">#{@equals}</span>"</span>, <span class="hljs-string">"<span class="hljs-subst">#{idx}</span> ><span class="hljs-subst">#{@equals}</span>"</span>]</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-121">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-121">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Generate the condition.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    condPart = <span class="hljs-keyword">if</span> @stepNum?
 | 
						||
      <span class="hljs-keyword">if</span> @stepNum > <span class="hljs-number">0</span> <span class="hljs-keyword">then</span> <span class="hljs-string">"<span class="hljs-subst">#{lt}</span> <span class="hljs-subst">#{@toVar}</span>"</span> <span class="hljs-keyword">else</span> <span class="hljs-string">"<span class="hljs-subst">#{gt}</span> <span class="hljs-subst">#{@toVar}</span>"</span>
 | 
						||
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> known
 | 
						||
      [<span class="hljs-keyword">from</span>, to] = [@fromNum, @toNum]
 | 
						||
      <span class="hljs-keyword">if</span> <span class="hljs-keyword">from</span> <= to <span class="hljs-keyword">then</span> <span class="hljs-string">"<span class="hljs-subst">#{lt}</span> <span class="hljs-subst">#{to}</span>"</span> <span class="hljs-keyword">else</span> <span class="hljs-string">"<span class="hljs-subst">#{gt}</span> <span class="hljs-subst">#{to}</span>"</span>
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      cond = <span class="hljs-keyword">if</span> @stepVar <span class="hljs-keyword">then</span> <span class="hljs-string">"<span class="hljs-subst">#{@stepVar}</span> > 0"</span> <span class="hljs-keyword">else</span> <span class="hljs-string">"<span class="hljs-subst">#{@fromVar}</span> <= <span class="hljs-subst">#{@toVar}</span>"</span>
 | 
						||
      <span class="hljs-string">"<span class="hljs-subst">#{cond}</span> ? <span class="hljs-subst">#{lt}</span> <span class="hljs-subst">#{@toVar}</span> : <span class="hljs-subst">#{gt}</span> <span class="hljs-subst">#{@toVar}</span>"</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-122">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-122">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Generate the step.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    stepPart = <span class="hljs-keyword">if</span> @stepVar
 | 
						||
      <span class="hljs-string">"<span class="hljs-subst">#{idx}</span> += <span class="hljs-subst">#{@stepVar}</span>"</span>
 | 
						||
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> known
 | 
						||
      <span class="hljs-keyword">if</span> namedIndex
 | 
						||
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">from</span> <= to <span class="hljs-keyword">then</span> <span class="hljs-string">"++<span class="hljs-subst">#{idx}</span>"</span> <span class="hljs-keyword">else</span> <span class="hljs-string">"--<span class="hljs-subst">#{idx}</span>"</span>
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">from</span> <= to <span class="hljs-keyword">then</span> <span class="hljs-string">"<span class="hljs-subst">#{idx}</span>++"</span> <span class="hljs-keyword">else</span> <span class="hljs-string">"<span class="hljs-subst">#{idx}</span>--"</span>
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      <span class="hljs-keyword">if</span> namedIndex
 | 
						||
        <span class="hljs-string">"<span class="hljs-subst">#{cond}</span> ? ++<span class="hljs-subst">#{idx}</span> : --<span class="hljs-subst">#{idx}</span>"</span>
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        <span class="hljs-string">"<span class="hljs-subst">#{cond}</span> ? <span class="hljs-subst">#{idx}</span>++ : <span class="hljs-subst">#{idx}</span>--"</span>
 | 
						||
 | 
						||
    varPart  = <span class="hljs-string">"<span class="hljs-subst">#{idxName}</span> = <span class="hljs-subst">#{varPart}</span>"</span> <span class="hljs-keyword">if</span> namedIndex
 | 
						||
    stepPart = <span class="hljs-string">"<span class="hljs-subst">#{idxName}</span> = <span class="hljs-subst">#{stepPart}</span>"</span> <span class="hljs-keyword">if</span> namedIndex</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-123">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-123">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>The final loop body.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    [@makeCode <span class="hljs-string">"<span class="hljs-subst">#{varPart}</span>; <span class="hljs-subst">#{condPart}</span>; <span class="hljs-subst">#{stepPart}</span>"</span>]</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-124">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-124">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>When used as a value, expand the range into the equivalent array.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileArray: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    known = @fromNum? <span class="hljs-keyword">and</span> @toNum?
 | 
						||
    <span class="hljs-keyword">if</span> known <span class="hljs-keyword">and</span> Math.abs(@fromNum - @toNum) <= <span class="hljs-number">20</span>
 | 
						||
      range = [@fromNum..@toNum]
 | 
						||
      range.pop() <span class="hljs-keyword">if</span> @exclusive
 | 
						||
      <span class="hljs-keyword">return</span> [@makeCode <span class="hljs-string">"[<span class="hljs-subst">#{ range.join(<span class="hljs-string">', '</span>) }</span>]"</span>]
 | 
						||
    idt    = @tab + TAB
 | 
						||
    i      = o.scope.freeVariable <span class="hljs-string">'i'</span>, single: <span class="hljs-literal">true</span>
 | 
						||
    result = o.scope.freeVariable <span class="hljs-string">'results'</span>
 | 
						||
    pre    = <span class="hljs-string">"\n<span class="hljs-subst">#{idt}</span><span class="hljs-subst">#{result}</span> = [];"</span>
 | 
						||
    <span class="hljs-keyword">if</span> known
 | 
						||
      o.index = i
 | 
						||
      body    = fragmentsToText @compileNode o
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      vars    = <span class="hljs-string">"<span class="hljs-subst">#{i}</span> = <span class="hljs-subst">#{@fromC}</span>"</span> + <span class="hljs-keyword">if</span> @toC <span class="hljs-keyword">isnt</span> @toVar <span class="hljs-keyword">then</span> <span class="hljs-string">", <span class="hljs-subst">#{@toC}</span>"</span> <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>
 | 
						||
      cond    = <span class="hljs-string">"<span class="hljs-subst">#{@fromVar}</span> <= <span class="hljs-subst">#{@toVar}</span>"</span>
 | 
						||
      body    = <span class="hljs-string">"var <span class="hljs-subst">#{vars}</span>; <span class="hljs-subst">#{cond}</span> ? <span class="hljs-subst">#{i}</span> <<span class="hljs-subst">#{@equals}</span> <span class="hljs-subst">#{@toVar}</span> : <span class="hljs-subst">#{i}</span> ><span class="hljs-subst">#{@equals}</span> <span class="hljs-subst">#{@toVar}</span>; <span class="hljs-subst">#{cond}</span> ? <span class="hljs-subst">#{i}</span>++ : <span class="hljs-subst">#{i}</span>--"</span>
 | 
						||
    post   = <span class="hljs-string">"{ <span class="hljs-subst">#{result}</span>.push(<span class="hljs-subst">#{i}</span>); }\n<span class="hljs-subst">#{idt}</span>return <span class="hljs-subst">#{result}</span>;\n<span class="hljs-subst">#{o.indent}</span>"</span>
 | 
						||
<span class="hljs-function">    <span class="hljs-title">hasArgs</span> = <span class="hljs-params">(node)</span> -></span> node?.contains isLiteralArguments
 | 
						||
    args   = <span class="hljs-string">', arguments'</span> <span class="hljs-keyword">if</span> hasArgs(@from) <span class="hljs-keyword">or</span> hasArgs(@to)
 | 
						||
    [@makeCode <span class="hljs-string">"(function() {<span class="hljs-subst">#{pre}</span>\n<span class="hljs-subst">#{idt}</span>for (<span class="hljs-subst">#{body}</span>)<span class="hljs-subst">#{post}</span>}).apply(this<span class="hljs-subst">#{args ? <span class="hljs-string">''</span>}</span>)"</span>]</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-125">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-125">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="slice">Slice</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-126">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-126">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>An array slice literal. Unlike JavaScript’s <code>Array#slice</code>, the second parameter
 | 
						||
specifies the index of the end of the slice, just as the first parameter
 | 
						||
is the index of the beginning.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Slice = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Slice</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'range'</span>]
 | 
						||
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@range)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-127">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-127">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>We have to be careful when trying to slice through the end of the array,
 | 
						||
<code>9e9</code> is used because not all implementations respect <code>undefined</code> or <code>1/0</code>.
 | 
						||
<code>9e9</code> should be safe because <code>9e9</code> > <code>2**32</code>, the max array length.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    {to, <span class="hljs-keyword">from</span>} = @range
 | 
						||
    fromCompiled = <span class="hljs-keyword">from</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">from</span>.compileToFragments(o, LEVEL_PAREN) <span class="hljs-keyword">or</span> [@makeCode <span class="hljs-string">'0'</span>]</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-128">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-128">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>TODO: jwalton - move this into the ‘if’?</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> to
 | 
						||
      compiled     = to.compileToFragments o, LEVEL_PAREN
 | 
						||
      compiledText = fragmentsToText compiled
 | 
						||
      <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> (<span class="hljs-keyword">not</span> @range.exclusive <span class="hljs-keyword">and</span> +compiledText <span class="hljs-keyword">is</span> <span class="hljs-number">-1</span>)
 | 
						||
        toStr = <span class="hljs-string">', '</span> + <span class="hljs-keyword">if</span> @range.exclusive
 | 
						||
          compiledText
 | 
						||
        <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> to.isNumber()
 | 
						||
          <span class="hljs-string">"<span class="hljs-subst">#{+compiledText + <span class="hljs-number">1</span>}</span>"</span>
 | 
						||
        <span class="hljs-keyword">else</span>
 | 
						||
          compiled = to.compileToFragments o, LEVEL_ACCESS
 | 
						||
          <span class="hljs-string">"+<span class="hljs-subst">#{fragmentsToText compiled}</span> + 1 || 9e9"</span>
 | 
						||
    [@makeCode <span class="hljs-string">".slice(<span class="hljs-subst">#{ fragmentsToText fromCompiled }</span><span class="hljs-subst">#{ toStr <span class="hljs-keyword">or</span> <span class="hljs-string">''</span> }</span>)"</span>]</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-129">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-129">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="obj">Obj</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-130">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-130">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>An object literal, nothing fancy.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Obj = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Obj</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(props, @generated = <span class="hljs-literal">no</span>, @lhs = <span class="hljs-literal">no</span>)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
    @objects = @properties = props <span class="hljs-keyword">or</span> []
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'properties'</span>]
 | 
						||
 | 
						||
  isAssignable: <span class="hljs-function">-></span>
 | 
						||
    <span class="hljs-keyword">for</span> prop <span class="hljs-keyword">in</span> @properties</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-131">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-131">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Check for reserved words.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      message = isUnassignable prop.unwrapAll().value
 | 
						||
      prop.error message <span class="hljs-keyword">if</span> message
 | 
						||
 | 
						||
      prop = prop.value <span class="hljs-keyword">if</span> prop <span class="hljs-keyword">instanceof</span> Assign <span class="hljs-keyword">and</span> prop.context <span class="hljs-keyword">is</span> <span class="hljs-string">'object'</span>
 | 
						||
      <span class="hljs-keyword">return</span> <span class="hljs-literal">no</span> <span class="hljs-keyword">unless</span> prop.isAssignable()
 | 
						||
    <span class="hljs-literal">yes</span>
 | 
						||
 | 
						||
  shouldCache: <span class="hljs-function">-></span>
 | 
						||
    <span class="hljs-keyword">not</span> @isAssignable()</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-132">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-132">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Check if object contains splat.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  hasSplat: <span class="hljs-function">-></span>
 | 
						||
    splat = <span class="hljs-literal">yes</span> <span class="hljs-keyword">for</span> prop <span class="hljs-keyword">in</span> @properties <span class="hljs-keyword">when</span> prop <span class="hljs-keyword">instanceof</span> Splat
 | 
						||
    splat ? <span class="hljs-literal">no</span>
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    props = @properties
 | 
						||
    <span class="hljs-keyword">if</span> @generated
 | 
						||
      <span class="hljs-keyword">for</span> node <span class="hljs-keyword">in</span> props <span class="hljs-keyword">when</span> node <span class="hljs-keyword">instanceof</span> Value
 | 
						||
        node.error <span class="hljs-string">'cannot have an implicit value in an implicit object'</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-133">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-133">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Object spread properties. <a href="https://github.com/tc39/proposal-object-rest-spread/blob/master/Spread.md">https://github.com/tc39/proposal-object-rest-spread/blob/master/Spread.md</a></p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">return</span> @compileSpread o <span class="hljs-keyword">if</span> @hasSplat() <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @csx
 | 
						||
 | 
						||
    idt      = o.indent += TAB
 | 
						||
    lastNode = @lastNode @properties</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-134">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-134">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>CSX attributes <div id="val" attr={aaa} {props...} /></p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">return</span> @compileCSXAttributes o <span class="hljs-keyword">if</span> @csx</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-135">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-135">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>If this object is the left-hand side of an assignment, all its children
 | 
						||
are too.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> @lhs
 | 
						||
      <span class="hljs-keyword">for</span> prop <span class="hljs-keyword">in</span> props <span class="hljs-keyword">when</span> prop <span class="hljs-keyword">instanceof</span> Assign
 | 
						||
        {value} = prop
 | 
						||
        unwrappedVal = value.unwrapAll()
 | 
						||
        <span class="hljs-keyword">if</span> unwrappedVal <span class="hljs-keyword">instanceof</span> Arr <span class="hljs-keyword">or</span> unwrappedVal <span class="hljs-keyword">instanceof</span> Obj
 | 
						||
          unwrappedVal.lhs = <span class="hljs-literal">yes</span>
 | 
						||
        <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> unwrappedVal <span class="hljs-keyword">instanceof</span> Assign
 | 
						||
          unwrappedVal.nestedLhs = <span class="hljs-literal">yes</span>
 | 
						||
 | 
						||
    isCompact = <span class="hljs-literal">yes</span>
 | 
						||
    <span class="hljs-keyword">for</span> prop <span class="hljs-keyword">in</span> @properties
 | 
						||
      <span class="hljs-keyword">if</span> prop <span class="hljs-keyword">instanceof</span> Assign <span class="hljs-keyword">and</span> prop.context <span class="hljs-keyword">is</span> <span class="hljs-string">'object'</span>
 | 
						||
        isCompact = <span class="hljs-literal">no</span>
 | 
						||
 | 
						||
    answer = []
 | 
						||
    answer.push @makeCode <span class="hljs-keyword">if</span> isCompact <span class="hljs-keyword">then</span> <span class="hljs-string">''</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'\n'</span>
 | 
						||
    <span class="hljs-keyword">for</span> prop, i <span class="hljs-keyword">in</span> props
 | 
						||
      join = <span class="hljs-keyword">if</span> i <span class="hljs-keyword">is</span> props.length - <span class="hljs-number">1</span>
 | 
						||
        <span class="hljs-string">''</span>
 | 
						||
      <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> isCompact
 | 
						||
        <span class="hljs-string">', '</span>
 | 
						||
      <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> prop <span class="hljs-keyword">is</span> lastNode
 | 
						||
        <span class="hljs-string">'\n'</span>
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        <span class="hljs-string">',\n'</span>
 | 
						||
      indent = <span class="hljs-keyword">if</span> isCompact <span class="hljs-keyword">then</span> <span class="hljs-string">''</span> <span class="hljs-keyword">else</span> idt
 | 
						||
 | 
						||
      key = <span class="hljs-keyword">if</span> prop <span class="hljs-keyword">instanceof</span> Assign <span class="hljs-keyword">and</span> prop.context <span class="hljs-keyword">is</span> <span class="hljs-string">'object'</span>
 | 
						||
        prop.variable
 | 
						||
      <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> prop <span class="hljs-keyword">instanceof</span> Assign
 | 
						||
        prop.operatorToken.error <span class="hljs-string">"unexpected <span class="hljs-subst">#{prop.operatorToken.value}</span>"</span> <span class="hljs-keyword">unless</span> @lhs
 | 
						||
        prop.variable
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        prop
 | 
						||
      <span class="hljs-keyword">if</span> key <span class="hljs-keyword">instanceof</span> Value <span class="hljs-keyword">and</span> key.hasProperties()
 | 
						||
        key.error <span class="hljs-string">'invalid object key'</span> <span class="hljs-keyword">if</span> prop.context <span class="hljs-keyword">is</span> <span class="hljs-string">'object'</span> <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> key.<span class="hljs-keyword">this</span>
 | 
						||
        key  = key.properties[<span class="hljs-number">0</span>].name
 | 
						||
        prop = <span class="hljs-keyword">new</span> Assign key, prop, <span class="hljs-string">'object'</span>
 | 
						||
      <span class="hljs-keyword">if</span> key <span class="hljs-keyword">is</span> prop
 | 
						||
        <span class="hljs-keyword">if</span> prop.shouldCache()
 | 
						||
          [key, value] = prop.base.cache o
 | 
						||
          key  = <span class="hljs-keyword">new</span> PropertyName key.value <span class="hljs-keyword">if</span> key <span class="hljs-keyword">instanceof</span> IdentifierLiteral
 | 
						||
          prop = <span class="hljs-keyword">new</span> Assign key, value, <span class="hljs-string">'object'</span>
 | 
						||
        <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> prop.bareLiteral?(IdentifierLiteral)
 | 
						||
          prop = <span class="hljs-keyword">new</span> Assign prop, prop, <span class="hljs-string">'object'</span>
 | 
						||
      <span class="hljs-keyword">if</span> indent <span class="hljs-keyword">then</span> answer.push @makeCode indent
 | 
						||
      answer.push prop.compileToFragments(o, LEVEL_TOP)...
 | 
						||
      <span class="hljs-keyword">if</span> join <span class="hljs-keyword">then</span> answer.push @makeCode join
 | 
						||
    answer.push @makeCode <span class="hljs-keyword">if</span> isCompact <span class="hljs-keyword">then</span> <span class="hljs-string">''</span> <span class="hljs-keyword">else</span> <span class="hljs-string">"\n<span class="hljs-subst">#{@tab}</span>"</span>
 | 
						||
    answer = @wrapInBraces answer
 | 
						||
    <span class="hljs-keyword">if</span> @front <span class="hljs-keyword">then</span> @wrapInParentheses answer <span class="hljs-keyword">else</span> answer
 | 
						||
 | 
						||
  assigns: <span class="hljs-function"><span class="hljs-params">(name)</span> -></span>
 | 
						||
    <span class="hljs-keyword">for</span> prop <span class="hljs-keyword">in</span> @properties <span class="hljs-keyword">when</span> prop.assigns name <span class="hljs-keyword">then</span> <span class="hljs-keyword">return</span> <span class="hljs-literal">yes</span>
 | 
						||
    <span class="hljs-literal">no</span>
 | 
						||
 | 
						||
  eachName: <span class="hljs-function"><span class="hljs-params">(iterator)</span> -></span>
 | 
						||
    <span class="hljs-keyword">for</span> prop <span class="hljs-keyword">in</span> @properties
 | 
						||
      prop = prop.value <span class="hljs-keyword">if</span> prop <span class="hljs-keyword">instanceof</span> Assign <span class="hljs-keyword">and</span> prop.context <span class="hljs-keyword">is</span> <span class="hljs-string">'object'</span>
 | 
						||
      prop = prop.unwrapAll()
 | 
						||
      prop.eachName iterator <span class="hljs-keyword">if</span> prop.eachName?</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-136">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-136">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Object spread properties. <a href="https://github.com/tc39/proposal-object-rest-spread/blob/master/Spread.md">https://github.com/tc39/proposal-object-rest-spread/blob/master/Spread.md</a>
 | 
						||
<code>obj2 = {a: 1, obj..., c: 3, d: 4}</code> → <code>obj2 = Object.assign({}, {a: 1}, obj, {c: 3, d: 4})</code></p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileSpread: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    props = @properties</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-137">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-137">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Store object spreads.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    splatSlice = []
 | 
						||
    propSlices = []
 | 
						||
    slices = []
 | 
						||
<span class="hljs-function">    <span class="hljs-title">addSlice</span> = -></span>
 | 
						||
      slices.push <span class="hljs-keyword">new</span> Obj propSlices <span class="hljs-keyword">if</span> propSlices.length
 | 
						||
      slices.push splatSlice... <span class="hljs-keyword">if</span> splatSlice.length
 | 
						||
      splatSlice = []
 | 
						||
      propSlices = []
 | 
						||
    <span class="hljs-keyword">for</span> prop <span class="hljs-keyword">in</span> props
 | 
						||
      <span class="hljs-keyword">if</span> prop <span class="hljs-keyword">instanceof</span> Splat
 | 
						||
        splatSlice.push <span class="hljs-keyword">new</span> Value prop.name
 | 
						||
        addSlice()
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        propSlices.push prop
 | 
						||
    addSlice()
 | 
						||
    slices.unshift <span class="hljs-keyword">new</span> Obj <span class="hljs-keyword">unless</span> slices[<span class="hljs-number">0</span>] <span class="hljs-keyword">instanceof</span> Obj
 | 
						||
    _extends = <span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Literal utility <span class="hljs-string">'_extends'</span>, o
 | 
						||
    (<span class="hljs-keyword">new</span> Call _extends, slices).compileToFragments o
 | 
						||
 | 
						||
  compileCSXAttributes: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    props = @properties
 | 
						||
    answer = []
 | 
						||
    <span class="hljs-keyword">for</span> prop, i <span class="hljs-keyword">in</span> props
 | 
						||
      prop.csx = <span class="hljs-literal">yes</span>
 | 
						||
      join = <span class="hljs-keyword">if</span> i <span class="hljs-keyword">is</span> props.length - <span class="hljs-number">1</span> <span class="hljs-keyword">then</span> <span class="hljs-string">''</span> <span class="hljs-keyword">else</span> <span class="hljs-string">' '</span>
 | 
						||
      prop = <span class="hljs-keyword">new</span> Literal <span class="hljs-string">"{<span class="hljs-subst">#{prop.compile(o)}</span>}"</span> <span class="hljs-keyword">if</span> prop <span class="hljs-keyword">instanceof</span> Splat
 | 
						||
      answer.push prop.compileToFragments(o, LEVEL_TOP)...
 | 
						||
      answer.push @makeCode join
 | 
						||
    <span class="hljs-keyword">if</span> @front <span class="hljs-keyword">then</span> @wrapInParentheses answer <span class="hljs-keyword">else</span> answer</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-138">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-138">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="arr">Arr</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-139">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-139">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>An array literal.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Arr = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Arr</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(objs, @lhs = <span class="hljs-literal">no</span>)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
    @objects = objs <span class="hljs-keyword">or</span> []
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'objects'</span>]
 | 
						||
 | 
						||
  isAssignable: <span class="hljs-function">-></span>
 | 
						||
    <span class="hljs-keyword">return</span> <span class="hljs-literal">no</span> <span class="hljs-keyword">unless</span> @objects.length
 | 
						||
 | 
						||
    <span class="hljs-keyword">for</span> obj, i <span class="hljs-keyword">in</span> @objects
 | 
						||
      <span class="hljs-keyword">return</span> <span class="hljs-literal">no</span> <span class="hljs-keyword">if</span> obj <span class="hljs-keyword">instanceof</span> Splat <span class="hljs-keyword">and</span> i + <span class="hljs-number">1</span> <span class="hljs-keyword">isnt</span> @objects.length
 | 
						||
      <span class="hljs-keyword">return</span> <span class="hljs-literal">no</span> <span class="hljs-keyword">unless</span> obj.isAssignable() <span class="hljs-keyword">and</span> (<span class="hljs-keyword">not</span> obj.isAtomic <span class="hljs-keyword">or</span> obj.isAtomic())
 | 
						||
    <span class="hljs-literal">yes</span>
 | 
						||
 | 
						||
  shouldCache: <span class="hljs-function">-></span>
 | 
						||
    <span class="hljs-keyword">not</span> @isAssignable()
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    <span class="hljs-keyword">return</span> [@makeCode <span class="hljs-string">'[]'</span>] <span class="hljs-keyword">unless</span> @objects.length
 | 
						||
    o.indent += TAB
 | 
						||
 | 
						||
    answer = []
 | 
						||
    <span class="hljs-keyword">for</span> obj, objIndex <span class="hljs-keyword">in</span> @objects
 | 
						||
      unwrappedObj = obj.unwrapAll()</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-140">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-140">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Let <code>compileCommentFragments</code> know to intersperse block comments
 | 
						||
into the fragments created when compiling this array.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      <span class="hljs-keyword">if</span> unwrappedObj.comments <span class="hljs-keyword">and</span>
 | 
						||
         unwrappedObj.comments.filter(<span class="hljs-function"><span class="hljs-params">(comment)</span> -></span> <span class="hljs-keyword">not</span> comment.here).length <span class="hljs-keyword">is</span> <span class="hljs-number">0</span>
 | 
						||
        unwrappedObj.includeCommentFragments = YES</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-141">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-141">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>If this array is the left-hand side of an assignment, all its children
 | 
						||
are too.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      <span class="hljs-keyword">if</span> @lhs
 | 
						||
        unwrappedObj.lhs = <span class="hljs-literal">yes</span> <span class="hljs-keyword">if</span> unwrappedObj <span class="hljs-keyword">instanceof</span> Arr <span class="hljs-keyword">or</span> unwrappedObj <span class="hljs-keyword">instanceof</span> Obj
 | 
						||
 | 
						||
    compiledObjs = (obj.compileToFragments o, LEVEL_LIST <span class="hljs-keyword">for</span> obj <span class="hljs-keyword">in</span> @objects)</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-142">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-142">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>If <code>compiledObjs</code> includes newlines, we will output this as a multiline
 | 
						||
array (i.e. with a newline and indentation after the <code>[</code>). If an element
 | 
						||
contains line comments, that should also trigger multiline output since
 | 
						||
by definition line comments will introduce newlines into our output.
 | 
						||
The exception is if only the first element has line comments; in that
 | 
						||
case, output as the compact form if we otherwise would have, so that the
 | 
						||
first element’s line comments get output before or after the array.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    includesLineCommentsOnNonFirstElement = <span class="hljs-literal">no</span>
 | 
						||
    <span class="hljs-keyword">for</span> fragments, index <span class="hljs-keyword">in</span> compiledObjs
 | 
						||
      <span class="hljs-keyword">for</span> fragment <span class="hljs-keyword">in</span> fragments
 | 
						||
        <span class="hljs-keyword">if</span> fragment.isHereComment
 | 
						||
          fragment.code = fragment.code.trim()
 | 
						||
        <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> index <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span> <span class="hljs-keyword">and</span> includesLineCommentsOnNonFirstElement <span class="hljs-keyword">is</span> <span class="hljs-literal">no</span> <span class="hljs-keyword">and</span> hasLineComments fragment
 | 
						||
          includesLineCommentsOnNonFirstElement = <span class="hljs-literal">yes</span>
 | 
						||
      <span class="hljs-keyword">if</span> index <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span>
 | 
						||
        answer.push @makeCode <span class="hljs-string">', '</span>
 | 
						||
      answer.push fragments...
 | 
						||
    <span class="hljs-keyword">if</span> includesLineCommentsOnNonFirstElement <span class="hljs-keyword">or</span> <span class="hljs-string">'\n'</span> <span class="hljs-keyword">in</span> fragmentsToText(answer)
 | 
						||
      <span class="hljs-keyword">for</span> fragment, fragmentIndex <span class="hljs-keyword">in</span> answer
 | 
						||
        <span class="hljs-keyword">if</span> fragment.isHereComment
 | 
						||
          fragment.code = <span class="hljs-string">"<span class="hljs-subst">#{multident(fragment.code, o.indent, <span class="hljs-literal">no</span>)}</span>\n<span class="hljs-subst">#{o.indent}</span>"</span>
 | 
						||
        <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> fragment.code <span class="hljs-keyword">is</span> <span class="hljs-string">', '</span>
 | 
						||
          fragment.code = <span class="hljs-string">",\n<span class="hljs-subst">#{o.indent}</span>"</span>
 | 
						||
      answer.unshift @makeCode <span class="hljs-string">"[\n<span class="hljs-subst">#{o.indent}</span>"</span>
 | 
						||
      answer.push @makeCode <span class="hljs-string">"\n<span class="hljs-subst">#{@tab}</span>]"</span>
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      <span class="hljs-keyword">for</span> fragment <span class="hljs-keyword">in</span> answer <span class="hljs-keyword">when</span> fragment.isHereComment
 | 
						||
        fragment.code = <span class="hljs-string">"<span class="hljs-subst">#{fragment.code}</span> "</span>
 | 
						||
      answer.unshift @makeCode <span class="hljs-string">'['</span>
 | 
						||
      answer.push @makeCode <span class="hljs-string">']'</span>
 | 
						||
    answer
 | 
						||
 | 
						||
  assigns: <span class="hljs-function"><span class="hljs-params">(name)</span> -></span>
 | 
						||
    <span class="hljs-keyword">for</span> obj <span class="hljs-keyword">in</span> @objects <span class="hljs-keyword">when</span> obj.assigns name <span class="hljs-keyword">then</span> <span class="hljs-keyword">return</span> <span class="hljs-literal">yes</span>
 | 
						||
    <span class="hljs-literal">no</span>
 | 
						||
 | 
						||
  eachName: <span class="hljs-function"><span class="hljs-params">(iterator)</span> -></span>
 | 
						||
    <span class="hljs-keyword">for</span> obj <span class="hljs-keyword">in</span> @objects
 | 
						||
      obj = obj.unwrapAll()
 | 
						||
      obj.eachName iterator</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-143">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-143">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="class">Class</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-144">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-144">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>The CoffeeScript class definition.
 | 
						||
Initialize a <strong>Class</strong> with its name, an optional superclass, and a body.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>
 | 
						||
exports.Class = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Class</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  children: [<span class="hljs-string">'variable'</span>, <span class="hljs-string">'parent'</span>, <span class="hljs-string">'body'</span>]
 | 
						||
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@variable, @parent, @body = <span class="hljs-keyword">new</span> Block)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    @name          = @determineName()
 | 
						||
    executableBody = @walkBody()</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-145">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-145">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Special handling to allow <code>class expr.A extends A</code> declarations</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    parentName    = @parent.base.value <span class="hljs-keyword">if</span> @parent <span class="hljs-keyword">instanceof</span> Value <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @parent.hasProperties()
 | 
						||
    @hasNameClash = @name? <span class="hljs-keyword">and</span> @name <span class="hljs-keyword">is</span> parentName
 | 
						||
 | 
						||
    node = @
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> executableBody <span class="hljs-keyword">or</span> @hasNameClash
 | 
						||
      node = <span class="hljs-keyword">new</span> ExecutableClassBody node, executableBody
 | 
						||
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> @name? <span class="hljs-keyword">and</span> o.level <span class="hljs-keyword">is</span> LEVEL_TOP</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-146">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-146">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Anonymous classes are only valid in expressions</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      node = <span class="hljs-keyword">new</span> Parens node
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> @boundMethods.length <span class="hljs-keyword">and</span> @parent
 | 
						||
      @variable ?= <span class="hljs-keyword">new</span> IdentifierLiteral o.scope.freeVariable <span class="hljs-string">'_class'</span>
 | 
						||
      [@variable, @variableRef] = @variable.cache o <span class="hljs-keyword">unless</span> @variableRef?
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> @variable
 | 
						||
      node = <span class="hljs-keyword">new</span> Assign @variable, node, <span class="hljs-literal">null</span>, { @moduleDeclaration }
 | 
						||
 | 
						||
    @compileNode = @compileClassDeclaration
 | 
						||
    <span class="hljs-keyword">try</span>
 | 
						||
      <span class="hljs-keyword">return</span> node.compileToFragments o
 | 
						||
    <span class="hljs-keyword">finally</span>
 | 
						||
      <span class="hljs-keyword">delete</span> @compileNode
 | 
						||
 | 
						||
  compileClassDeclaration: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    @ctor ?= @makeDefaultConstructor() <span class="hljs-keyword">if</span> @externalCtor <span class="hljs-keyword">or</span> @boundMethods.length
 | 
						||
    @ctor?.noReturn = <span class="hljs-literal">true</span>
 | 
						||
 | 
						||
    @proxyBoundMethods() <span class="hljs-keyword">if</span> @boundMethods.length
 | 
						||
 | 
						||
    o.indent += TAB
 | 
						||
 | 
						||
    result = []
 | 
						||
    result.push @makeCode <span class="hljs-string">"class "</span>
 | 
						||
    result.push @makeCode <span class="hljs-string">"<span class="hljs-subst">#{@name}</span> "</span> <span class="hljs-keyword">if</span> @name
 | 
						||
    result.push @makeCode(<span class="hljs-string">'extends '</span>), @parent.compileToFragments(o)..., @makeCode <span class="hljs-string">' '</span> <span class="hljs-keyword">if</span> @parent
 | 
						||
 | 
						||
    result.push @makeCode <span class="hljs-string">'{'</span>
 | 
						||
    <span class="hljs-keyword">unless</span> @body.isEmpty()
 | 
						||
      @body.spaced = <span class="hljs-literal">true</span>
 | 
						||
      result.push @makeCode <span class="hljs-string">'\n'</span>
 | 
						||
      result.push @body.compileToFragments(o, LEVEL_TOP)...
 | 
						||
      result.push @makeCode <span class="hljs-string">"\n<span class="hljs-subst">#{@tab}</span>"</span>
 | 
						||
    result.push @makeCode <span class="hljs-string">'}'</span>
 | 
						||
 | 
						||
    result</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-147">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-147">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Figure out the appropriate name for this class</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  determineName: <span class="hljs-function">-></span>
 | 
						||
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span> <span class="hljs-keyword">unless</span> @variable
 | 
						||
    [..., tail] = @variable.properties
 | 
						||
    node = <span class="hljs-keyword">if</span> tail
 | 
						||
      tail <span class="hljs-keyword">instanceof</span> Access <span class="hljs-keyword">and</span> tail.name
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      @variable.base
 | 
						||
    <span class="hljs-keyword">unless</span> node <span class="hljs-keyword">instanceof</span> IdentifierLiteral <span class="hljs-keyword">or</span> node <span class="hljs-keyword">instanceof</span> PropertyName
 | 
						||
      <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>
 | 
						||
    name = node.value
 | 
						||
    <span class="hljs-keyword">unless</span> tail
 | 
						||
      message = isUnassignable name
 | 
						||
      @variable.error message <span class="hljs-keyword">if</span> message
 | 
						||
    <span class="hljs-keyword">if</span> name <span class="hljs-keyword">in</span> JS_FORBIDDEN <span class="hljs-keyword">then</span> <span class="hljs-string">"_<span class="hljs-subst">#{name}</span>"</span> <span class="hljs-keyword">else</span> name
 | 
						||
 | 
						||
  walkBody: <span class="hljs-function">-></span>
 | 
						||
    @ctor          = <span class="hljs-literal">null</span>
 | 
						||
    @boundMethods  = []
 | 
						||
    executableBody = <span class="hljs-literal">null</span>
 | 
						||
 | 
						||
    initializer     = []
 | 
						||
    { expressions } = @body
 | 
						||
 | 
						||
    i = <span class="hljs-number">0</span>
 | 
						||
    <span class="hljs-keyword">for</span> expression <span class="hljs-keyword">in</span> expressions.slice()
 | 
						||
      <span class="hljs-keyword">if</span> expression <span class="hljs-keyword">instanceof</span> Value <span class="hljs-keyword">and</span> expression.isObject <span class="hljs-literal">true</span>
 | 
						||
        { properties } = expression.base
 | 
						||
        exprs     = []
 | 
						||
        end       = <span class="hljs-number">0</span>
 | 
						||
        start     = <span class="hljs-number">0</span>
 | 
						||
<span class="hljs-function">        <span class="hljs-title">pushSlice</span> = -></span> exprs.push <span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Obj properties[start...end], <span class="hljs-literal">true</span> <span class="hljs-keyword">if</span> end > start
 | 
						||
 | 
						||
        <span class="hljs-keyword">while</span> assign = properties[end]
 | 
						||
          <span class="hljs-keyword">if</span> initializerExpression = @addInitializerExpression assign
 | 
						||
            pushSlice()
 | 
						||
            exprs.push initializerExpression
 | 
						||
            initializer.push initializerExpression
 | 
						||
            start = end + <span class="hljs-number">1</span>
 | 
						||
          end++
 | 
						||
        pushSlice()
 | 
						||
 | 
						||
        expressions[i..i] = exprs
 | 
						||
        i += exprs.length
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        <span class="hljs-keyword">if</span> initializerExpression = @addInitializerExpression expression
 | 
						||
          initializer.push initializerExpression
 | 
						||
          expressions[i] = initializerExpression
 | 
						||
        i += <span class="hljs-number">1</span>
 | 
						||
 | 
						||
    <span class="hljs-keyword">for</span> method <span class="hljs-keyword">in</span> initializer <span class="hljs-keyword">when</span> method <span class="hljs-keyword">instanceof</span> Code
 | 
						||
      <span class="hljs-keyword">if</span> method.ctor
 | 
						||
        method.error <span class="hljs-string">'Cannot define more than one constructor in a class'</span> <span class="hljs-keyword">if</span> @ctor
 | 
						||
        @ctor = method
 | 
						||
      <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> method.isStatic <span class="hljs-keyword">and</span> method.bound
 | 
						||
        method.context = @name
 | 
						||
      <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> method.bound
 | 
						||
        @boundMethods.push method
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> initializer.length <span class="hljs-keyword">isnt</span> expressions.length
 | 
						||
      @body.expressions = (expression.hoist() <span class="hljs-keyword">for</span> expression <span class="hljs-keyword">in</span> initializer)
 | 
						||
      <span class="hljs-keyword">new</span> Block expressions</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-148">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-148">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Add an expression to the class initializer</p>
 | 
						||
<p>NOTE Currently, only methods and static methods are valid in ES class initializers.
 | 
						||
When additional expressions become valid, this method should be updated to handle them.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  addInitializerExpression: <span class="hljs-function"><span class="hljs-params">(node)</span> -></span>
 | 
						||
    <span class="hljs-keyword">if</span> @validInitializerMethod node
 | 
						||
      @addInitializerMethod node
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      <span class="hljs-literal">null</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-149">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-149">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Checks if the given node is a valid ES class initializer method.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  validInitializerMethod: <span class="hljs-function"><span class="hljs-params">(node)</span> -></span>
 | 
						||
    <span class="hljs-keyword">return</span> <span class="hljs-literal">no</span> <span class="hljs-keyword">unless</span> node <span class="hljs-keyword">instanceof</span> Assign <span class="hljs-keyword">and</span> node.value <span class="hljs-keyword">instanceof</span> Code
 | 
						||
    <span class="hljs-keyword">return</span> <span class="hljs-literal">yes</span> <span class="hljs-keyword">if</span> node.context <span class="hljs-keyword">is</span> <span class="hljs-string">'object'</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> node.variable.hasProperties()
 | 
						||
    <span class="hljs-keyword">return</span> node.variable.looksStatic(@name) <span class="hljs-keyword">and</span> (@name <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> node.value.bound)</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-150">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-150">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Returns a configured class initializer method</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  addInitializerMethod: <span class="hljs-function"><span class="hljs-params">(assign)</span> -></span>
 | 
						||
    { variable, value: method } = assign
 | 
						||
    method.isMethod = <span class="hljs-literal">yes</span>
 | 
						||
    method.isStatic = variable.looksStatic @name
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> method.isStatic
 | 
						||
      method.name = variable.properties[<span class="hljs-number">0</span>]
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      methodName  = variable.base
 | 
						||
      method.name = <span class="hljs-keyword">new</span> (<span class="hljs-keyword">if</span> methodName.shouldCache() <span class="hljs-keyword">then</span> Index <span class="hljs-keyword">else</span> Access) methodName
 | 
						||
      method.name.updateLocationDataIfMissing methodName.locationData
 | 
						||
      method.ctor = (<span class="hljs-keyword">if</span> @parent <span class="hljs-keyword">then</span> <span class="hljs-string">'derived'</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'base'</span>) <span class="hljs-keyword">if</span> methodName.value <span class="hljs-keyword">is</span> <span class="hljs-string">'constructor'</span>
 | 
						||
      method.error <span class="hljs-string">'Cannot define a constructor as a bound (fat arrow) function'</span> <span class="hljs-keyword">if</span> method.bound <span class="hljs-keyword">and</span> method.ctor
 | 
						||
 | 
						||
    method
 | 
						||
 | 
						||
  makeDefaultConstructor: <span class="hljs-function">-></span>
 | 
						||
    ctor = @addInitializerMethod <span class="hljs-keyword">new</span> Assign (<span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> PropertyName <span class="hljs-string">'constructor'</span>), <span class="hljs-keyword">new</span> Code
 | 
						||
    @body.unshift ctor
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> @parent
 | 
						||
      ctor.body.push <span class="hljs-keyword">new</span> SuperCall <span class="hljs-keyword">new</span> Super, [<span class="hljs-keyword">new</span> Splat <span class="hljs-keyword">new</span> IdentifierLiteral <span class="hljs-string">'arguments'</span>]
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> @externalCtor
 | 
						||
      applyCtor = <span class="hljs-keyword">new</span> Value @externalCtor, [ <span class="hljs-keyword">new</span> Access <span class="hljs-keyword">new</span> PropertyName <span class="hljs-string">'apply'</span> ]
 | 
						||
      applyArgs = [ <span class="hljs-keyword">new</span> ThisLiteral, <span class="hljs-keyword">new</span> IdentifierLiteral <span class="hljs-string">'arguments'</span> ]
 | 
						||
      ctor.body.push <span class="hljs-keyword">new</span> Call applyCtor, applyArgs
 | 
						||
      ctor.body.makeReturn()
 | 
						||
 | 
						||
    ctor
 | 
						||
 | 
						||
  proxyBoundMethods: <span class="hljs-function">-></span>
 | 
						||
    @ctor.thisAssignments = <span class="hljs-keyword">for</span> method <span class="hljs-keyword">in</span> @boundMethods
 | 
						||
      method.classVariable = @variableRef <span class="hljs-keyword">if</span> @parent
 | 
						||
 | 
						||
      name = <span class="hljs-keyword">new</span> Value(<span class="hljs-keyword">new</span> ThisLiteral, [ method.name ])
 | 
						||
      <span class="hljs-keyword">new</span> Assign name, <span class="hljs-keyword">new</span> Call(<span class="hljs-keyword">new</span> Value(name, [<span class="hljs-keyword">new</span> Access <span class="hljs-keyword">new</span> PropertyName <span class="hljs-string">'bind'</span>]), [<span class="hljs-keyword">new</span> ThisLiteral])
 | 
						||
 | 
						||
    <span class="hljs-literal">null</span>
 | 
						||
 | 
						||
exports.ExecutableClassBody = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ExecutableClassBody</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  children: [ <span class="hljs-string">'class'</span>, <span class="hljs-string">'body'</span> ]
 | 
						||
 | 
						||
  defaultClassVariableName: <span class="hljs-string">'_Class'</span>
 | 
						||
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@class, @body = <span class="hljs-keyword">new</span> Block)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    <span class="hljs-keyword">if</span> jumpNode = @body.jumps()
 | 
						||
      jumpNode.error <span class="hljs-string">'Class bodies cannot contain pure statements'</span>
 | 
						||
    <span class="hljs-keyword">if</span> argumentsNode = @body.contains isLiteralArguments
 | 
						||
      argumentsNode.error <span class="hljs-string">"Class bodies shouldn't reference arguments"</span>
 | 
						||
 | 
						||
    @name      = @class.name ? @defaultClassVariableName
 | 
						||
    directives = @walkBody()
 | 
						||
    @setContext()
 | 
						||
 | 
						||
    ident   = <span class="hljs-keyword">new</span> IdentifierLiteral @name
 | 
						||
    params  = []
 | 
						||
    args    = []
 | 
						||
    wrapper = <span class="hljs-keyword">new</span> Code params, @body
 | 
						||
    klass   = <span class="hljs-keyword">new</span> Parens <span class="hljs-keyword">new</span> Call wrapper, args
 | 
						||
 | 
						||
    @body.spaced = <span class="hljs-literal">true</span>
 | 
						||
 | 
						||
    o.classScope = wrapper.makeScope o.scope
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> @class.hasNameClash
 | 
						||
      parent = <span class="hljs-keyword">new</span> IdentifierLiteral o.classScope.freeVariable <span class="hljs-string">'superClass'</span>
 | 
						||
      wrapper.params.push <span class="hljs-keyword">new</span> Param parent
 | 
						||
      args.push @class.parent
 | 
						||
      @class.parent = parent
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> @externalCtor
 | 
						||
      externalCtor = <span class="hljs-keyword">new</span> IdentifierLiteral o.classScope.freeVariable <span class="hljs-string">'ctor'</span>, reserve: <span class="hljs-literal">no</span>
 | 
						||
      @class.externalCtor = externalCtor
 | 
						||
      @externalCtor.variable.base = externalCtor
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> @name <span class="hljs-keyword">isnt</span> @class.name
 | 
						||
      @body.expressions.unshift <span class="hljs-keyword">new</span> Assign (<span class="hljs-keyword">new</span> IdentifierLiteral @name), @class
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      @body.expressions.unshift @class
 | 
						||
    @body.expressions.unshift directives...
 | 
						||
    @body.push ident
 | 
						||
 | 
						||
    klass.compileToFragments o</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-151">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-151">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Traverse the class’s children and:</p>
 | 
						||
<ul>
 | 
						||
<li>Hoist valid ES properties into <code>@properties</code></li>
 | 
						||
<li>Hoist static assignments into <code>@properties</code></li>
 | 
						||
<li>Convert invalid ES properties into class or prototype assignments</li>
 | 
						||
</ul>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  walkBody: <span class="hljs-function">-></span>
 | 
						||
    directives  = []
 | 
						||
 | 
						||
    index = <span class="hljs-number">0</span>
 | 
						||
    <span class="hljs-keyword">while</span> expr = @body.expressions[index]
 | 
						||
      <span class="hljs-keyword">break</span> <span class="hljs-keyword">unless</span> expr <span class="hljs-keyword">instanceof</span> Value <span class="hljs-keyword">and</span> expr.isString()
 | 
						||
      <span class="hljs-keyword">if</span> expr.hoisted
 | 
						||
        index++
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        directives.push @body.expressions.splice(index, <span class="hljs-number">1</span>)...
 | 
						||
 | 
						||
    @traverseChildren <span class="hljs-literal">false</span>, <span class="hljs-function"><span class="hljs-params">(child)</span> =></span>
 | 
						||
      <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span> <span class="hljs-keyword">if</span> child <span class="hljs-keyword">instanceof</span> Class <span class="hljs-keyword">or</span> child <span class="hljs-keyword">instanceof</span> HoistTarget
 | 
						||
 | 
						||
      cont = <span class="hljs-literal">true</span>
 | 
						||
      <span class="hljs-keyword">if</span> child <span class="hljs-keyword">instanceof</span> Block
 | 
						||
        <span class="hljs-keyword">for</span> node, i <span class="hljs-keyword">in</span> child.expressions
 | 
						||
          <span class="hljs-keyword">if</span> node <span class="hljs-keyword">instanceof</span> Value <span class="hljs-keyword">and</span> node.isObject(<span class="hljs-literal">true</span>)
 | 
						||
            cont = <span class="hljs-literal">false</span>
 | 
						||
            child.expressions[i] = @addProperties node.base.properties
 | 
						||
          <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> node <span class="hljs-keyword">instanceof</span> Assign <span class="hljs-keyword">and</span> node.variable.looksStatic @name
 | 
						||
            node.value.isStatic = <span class="hljs-literal">yes</span>
 | 
						||
        child.expressions = flatten child.expressions
 | 
						||
      cont
 | 
						||
 | 
						||
    directives
 | 
						||
 | 
						||
  setContext: <span class="hljs-function">-></span>
 | 
						||
    @body.traverseChildren <span class="hljs-literal">false</span>, <span class="hljs-function"><span class="hljs-params">(node)</span> =></span>
 | 
						||
      <span class="hljs-keyword">if</span> node <span class="hljs-keyword">instanceof</span> ThisLiteral
 | 
						||
        node.value   = @name
 | 
						||
      <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> node <span class="hljs-keyword">instanceof</span> Code <span class="hljs-keyword">and</span> node.bound <span class="hljs-keyword">and</span> node.isStatic
 | 
						||
        node.context = @name</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-152">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-152">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Make class/prototype assignments for invalid ES properties</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  addProperties: <span class="hljs-function"><span class="hljs-params">(assigns)</span> -></span>
 | 
						||
    result = <span class="hljs-keyword">for</span> assign <span class="hljs-keyword">in</span> assigns
 | 
						||
      variable = assign.variable
 | 
						||
      base     = variable?.base
 | 
						||
      value    = assign.value
 | 
						||
      <span class="hljs-keyword">delete</span> assign.context
 | 
						||
 | 
						||
      <span class="hljs-keyword">if</span> base.value <span class="hljs-keyword">is</span> <span class="hljs-string">'constructor'</span>
 | 
						||
        <span class="hljs-keyword">if</span> value <span class="hljs-keyword">instanceof</span> Code
 | 
						||
          base.error <span class="hljs-string">'constructors must be defined at the top level of a class body'</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-153">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-153">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>The class scope is not available yet, so return the assignment to update later</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        assign = @externalCtor = <span class="hljs-keyword">new</span> Assign <span class="hljs-keyword">new</span> Value, value
 | 
						||
      <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> assign.variable.<span class="hljs-keyword">this</span>
 | 
						||
        name      = <span class="hljs-keyword">new</span> (<span class="hljs-keyword">if</span> base.shouldCache() <span class="hljs-keyword">then</span> Index <span class="hljs-keyword">else</span> Access) base
 | 
						||
        prototype = <span class="hljs-keyword">new</span> Access <span class="hljs-keyword">new</span> PropertyName <span class="hljs-string">'prototype'</span>
 | 
						||
        variable  = <span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> ThisLiteral(), [ prototype, name ]
 | 
						||
 | 
						||
        assign.variable = variable
 | 
						||
      <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> assign.value <span class="hljs-keyword">instanceof</span> Code
 | 
						||
        assign.value.isStatic = <span class="hljs-literal">true</span>
 | 
						||
 | 
						||
      assign
 | 
						||
    compact result</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-154">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-154">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="import-and-export">Import and Export</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>
 | 
						||
exports.ModuleDeclaration = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ModuleDeclaration</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@clause, @source)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
    @checkSource()
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'clause'</span>, <span class="hljs-string">'source'</span>]
 | 
						||
 | 
						||
  isStatement: YES
 | 
						||
  jumps:       THIS
 | 
						||
  makeReturn:  THIS
 | 
						||
 | 
						||
  checkSource: <span class="hljs-function">-></span>
 | 
						||
    <span class="hljs-keyword">if</span> @source? <span class="hljs-keyword">and</span> @source <span class="hljs-keyword">instanceof</span> StringWithInterpolations
 | 
						||
      @source.error <span class="hljs-string">'the name of the module to be imported from must be an uninterpolated string'</span>
 | 
						||
 | 
						||
  checkScope: <span class="hljs-function"><span class="hljs-params">(o, moduleDeclarationType)</span> -></span>
 | 
						||
    <span class="hljs-keyword">if</span> o.indent.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span>
 | 
						||
      @error <span class="hljs-string">"<span class="hljs-subst">#{moduleDeclarationType}</span> statements must be at top-level scope"</span>
 | 
						||
 | 
						||
exports.ImportDeclaration = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ImportDeclaration</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ModuleDeclaration</span></span>
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    @checkScope o, <span class="hljs-string">'import'</span>
 | 
						||
    o.importedSymbols = []
 | 
						||
 | 
						||
    code = []
 | 
						||
    code.push @makeCode <span class="hljs-string">"<span class="hljs-subst">#{@tab}</span>import "</span>
 | 
						||
    code.push @clause.compileNode(o)... <span class="hljs-keyword">if</span> @clause?
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> @source?.value?
 | 
						||
      code.push @makeCode <span class="hljs-string">' from '</span> <span class="hljs-keyword">unless</span> @clause <span class="hljs-keyword">is</span> <span class="hljs-literal">null</span>
 | 
						||
      code.push @makeCode @source.value
 | 
						||
 | 
						||
    code.push @makeCode <span class="hljs-string">';'</span>
 | 
						||
    code
 | 
						||
 | 
						||
exports.ImportClause = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ImportClause</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@defaultBinding, @namedImports)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'defaultBinding'</span>, <span class="hljs-string">'namedImports'</span>]
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    code = []
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> @defaultBinding?
 | 
						||
      code.push @defaultBinding.compileNode(o)...
 | 
						||
      code.push @makeCode <span class="hljs-string">', '</span> <span class="hljs-keyword">if</span> @namedImports?
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> @namedImports?
 | 
						||
      code.push @namedImports.compileNode(o)...
 | 
						||
 | 
						||
    code
 | 
						||
 | 
						||
exports.ExportDeclaration = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ExportDeclaration</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ModuleDeclaration</span></span>
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    @checkScope o, <span class="hljs-string">'export'</span>
 | 
						||
 | 
						||
    code = []
 | 
						||
    code.push @makeCode <span class="hljs-string">"<span class="hljs-subst">#{@tab}</span>export "</span>
 | 
						||
    code.push @makeCode <span class="hljs-string">'default '</span> <span class="hljs-keyword">if</span> @ <span class="hljs-keyword">instanceof</span> ExportDefaultDeclaration
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> @ <span class="hljs-keyword">not</span> <span class="hljs-keyword">instanceof</span> ExportDefaultDeclaration <span class="hljs-keyword">and</span>
 | 
						||
       (@clause <span class="hljs-keyword">instanceof</span> Assign <span class="hljs-keyword">or</span> @clause <span class="hljs-keyword">instanceof</span> Class)</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-155">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-155">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Prevent exporting an anonymous class; all exported members must be named</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      <span class="hljs-keyword">if</span> @clause <span class="hljs-keyword">instanceof</span> Class <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @clause.variable
 | 
						||
        @clause.error <span class="hljs-string">'anonymous classes cannot be exported'</span>
 | 
						||
 | 
						||
      code.push @makeCode <span class="hljs-string">'var '</span>
 | 
						||
      @clause.moduleDeclaration = <span class="hljs-string">'export'</span>
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> @clause.body? <span class="hljs-keyword">and</span> @clause.body <span class="hljs-keyword">instanceof</span> Block
 | 
						||
      code = code.concat @clause.compileToFragments o, LEVEL_TOP
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      code = code.concat @clause.compileNode o
 | 
						||
 | 
						||
    code.push @makeCode <span class="hljs-string">" from <span class="hljs-subst">#{@source.value}</span>"</span> <span class="hljs-keyword">if</span> @source?.value?
 | 
						||
    code.push @makeCode <span class="hljs-string">';'</span>
 | 
						||
    code
 | 
						||
 | 
						||
exports.ExportNamedDeclaration = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ExportNamedDeclaration</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ExportDeclaration</span></span>
 | 
						||
 | 
						||
exports.ExportDefaultDeclaration = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ExportDefaultDeclaration</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ExportDeclaration</span></span>
 | 
						||
 | 
						||
exports.ExportAllDeclaration = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ExportAllDeclaration</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ExportDeclaration</span></span>
 | 
						||
 | 
						||
exports.ModuleSpecifierList = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ModuleSpecifierList</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@specifiers)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'specifiers'</span>]
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    code = []
 | 
						||
    o.indent += TAB
 | 
						||
    compiledList = (specifier.compileToFragments o, LEVEL_LIST <span class="hljs-keyword">for</span> specifier <span class="hljs-keyword">in</span> @specifiers)
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> @specifiers.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span>
 | 
						||
      code.push @makeCode <span class="hljs-string">"{\n<span class="hljs-subst">#{o.indent}</span>"</span>
 | 
						||
      <span class="hljs-keyword">for</span> fragments, index <span class="hljs-keyword">in</span> compiledList
 | 
						||
        code.push @makeCode(<span class="hljs-string">",\n<span class="hljs-subst">#{o.indent}</span>"</span>) <span class="hljs-keyword">if</span> index
 | 
						||
        code.push fragments...
 | 
						||
      code.push @makeCode <span class="hljs-string">"\n}"</span>
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      code.push @makeCode <span class="hljs-string">'{}'</span>
 | 
						||
    code
 | 
						||
 | 
						||
exports.ImportSpecifierList = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ImportSpecifierList</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ModuleSpecifierList</span></span>
 | 
						||
 | 
						||
exports.ExportSpecifierList = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ExportSpecifierList</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ModuleSpecifierList</span></span>
 | 
						||
 | 
						||
exports.ModuleSpecifier = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ModuleSpecifier</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@original, @alias, @moduleDeclarationType)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> @original.comments <span class="hljs-keyword">or</span> @alias?.comments
 | 
						||
      @comments = []
 | 
						||
      @comments.push @original.comments... <span class="hljs-keyword">if</span> @original.comments
 | 
						||
      @comments.push @alias.comments...    <span class="hljs-keyword">if</span> @alias?.comments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-156">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-156">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>The name of the variable entering the local scope</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    @identifier = <span class="hljs-keyword">if</span> @alias? <span class="hljs-keyword">then</span> @alias.value <span class="hljs-keyword">else</span> @original.value
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'original'</span>, <span class="hljs-string">'alias'</span>]
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    o.scope.find @identifier, @moduleDeclarationType
 | 
						||
    code = []
 | 
						||
    code.push @makeCode @original.value
 | 
						||
    code.push @makeCode <span class="hljs-string">" as <span class="hljs-subst">#{@alias.value}</span>"</span> <span class="hljs-keyword">if</span> @alias?
 | 
						||
    code
 | 
						||
 | 
						||
exports.ImportSpecifier = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ImportSpecifier</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ModuleSpecifier</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(imported, local)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span> imported, local, <span class="hljs-string">'import'</span>
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-157">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-157">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Per the spec, symbols can’t be imported multiple times
 | 
						||
(e.g. <code>import { foo, foo } from 'lib'</code> is invalid)</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> @identifier <span class="hljs-keyword">in</span> o.importedSymbols <span class="hljs-keyword">or</span> o.scope.check(@identifier)
 | 
						||
      @error <span class="hljs-string">"'<span class="hljs-subst">#{@identifier}</span>' has already been declared"</span>
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      o.importedSymbols.push @identifier
 | 
						||
    <span class="hljs-keyword">super</span> o
 | 
						||
 | 
						||
exports.ImportDefaultSpecifier = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ImportDefaultSpecifier</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ImportSpecifier</span></span>
 | 
						||
 | 
						||
exports.ImportNamespaceSpecifier = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ImportNamespaceSpecifier</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ImportSpecifier</span></span>
 | 
						||
 | 
						||
exports.ExportSpecifier = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ExportSpecifier</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ModuleSpecifier</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(local, exported)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span> local, exported, <span class="hljs-string">'export'</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-158">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-158">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="assign">Assign</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-159">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-159">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>The <strong>Assign</strong> is used to assign a local variable to value, or to set the
 | 
						||
property of an object – including within object literals.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Assign = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Assign</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@variable, @value, @context, options = {})</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
    {@param, @subpattern, @operatorToken, @moduleDeclaration} = options
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'variable'</span>, <span class="hljs-string">'value'</span>]
 | 
						||
 | 
						||
  isAssignable: YES
 | 
						||
 | 
						||
  isStatement: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    o?.level <span class="hljs-keyword">is</span> LEVEL_TOP <span class="hljs-keyword">and</span> @context? <span class="hljs-keyword">and</span> (@moduleDeclaration <span class="hljs-keyword">or</span> <span class="hljs-string">"?"</span> <span class="hljs-keyword">in</span> @context)
 | 
						||
 | 
						||
  checkAssignability: <span class="hljs-function"><span class="hljs-params">(o, varBase)</span> -></span>
 | 
						||
    <span class="hljs-keyword">if</span> Object::hasOwnProperty.call(o.scope.positions, varBase.value) <span class="hljs-keyword">and</span>
 | 
						||
       o.scope.variables[o.scope.positions[varBase.value]].type <span class="hljs-keyword">is</span> <span class="hljs-string">'import'</span>
 | 
						||
      varBase.error <span class="hljs-string">"'<span class="hljs-subst">#{varBase.value}</span>' is read-only"</span>
 | 
						||
 | 
						||
  assigns: <span class="hljs-function"><span class="hljs-params">(name)</span> -></span>
 | 
						||
    @[<span class="hljs-keyword">if</span> @context <span class="hljs-keyword">is</span> <span class="hljs-string">'object'</span> <span class="hljs-keyword">then</span> <span class="hljs-string">'value'</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'variable'</span>].assigns name
 | 
						||
 | 
						||
  unfoldSoak: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    unfoldSoak o, <span class="hljs-keyword">this</span>, <span class="hljs-string">'variable'</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-160">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-160">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Compile an assignment, delegating to <code>compileDestructuring</code> or
 | 
						||
<code>compileSplice</code> if appropriate. Keep track of the name of the base object
 | 
						||
we’ve been assigned to, for correct internal references. If the variable
 | 
						||
has not been seen yet within the current scope, declare it.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    isValue = @variable <span class="hljs-keyword">instanceof</span> Value
 | 
						||
    <span class="hljs-keyword">if</span> isValue</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-161">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-161">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>When compiling <code>@variable</code>, remember if it is part of a function parameter.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      @variable.param = @param</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-162">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-162">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>If <code>@variable</code> is an array or an object, we’re destructuring;
 | 
						||
if it’s also <code>isAssignable()</code>, the destructuring syntax is supported
 | 
						||
in ES and we can output it as is; otherwise we <code>@compileDestructuring</code>
 | 
						||
and convert this ES-unsupported destructuring into acceptable output.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      <span class="hljs-keyword">if</span> @variable.isArray() <span class="hljs-keyword">or</span> @variable.isObject()</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-163">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-163">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>This is the left-hand side of an assignment; let <code>Arr</code> and <code>Obj</code>
 | 
						||
know that, so that those nodes know that they’re assignable as
 | 
						||
destructured variables.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        @variable.base.lhs = <span class="hljs-literal">yes</span>
 | 
						||
        <span class="hljs-keyword">return</span> @compileDestructuring o <span class="hljs-keyword">unless</span> @variable.isAssignable()</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-164">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-164">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Object destructuring. Can be removed once ES proposal hits Stage 4.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        objDestructAnswer = @compileObjectDestruct(o) <span class="hljs-keyword">if</span> @variable.isObject() <span class="hljs-keyword">and</span> @variable.contains (node) ->
 | 
						||
          node <span class="hljs-keyword">instanceof</span> Obj <span class="hljs-keyword">and</span> node.hasSplat()
 | 
						||
        <span class="hljs-keyword">return</span> objDestructAnswer <span class="hljs-keyword">if</span> objDestructAnswer
 | 
						||
 | 
						||
      <span class="hljs-keyword">return</span> @compileSplice       o <span class="hljs-keyword">if</span> @variable.isSplice()
 | 
						||
      <span class="hljs-keyword">return</span> @compileConditional  o <span class="hljs-keyword">if</span> @context <span class="hljs-keyword">in</span> [<span class="hljs-string">'||='</span>, <span class="hljs-string">'&&='</span>, <span class="hljs-string">'?='</span>]
 | 
						||
      <span class="hljs-keyword">return</span> @compileSpecialMath  o <span class="hljs-keyword">if</span> @context <span class="hljs-keyword">in</span> [<span class="hljs-string">'**='</span>, <span class="hljs-string">'//='</span>, <span class="hljs-string">'%%='</span>]
 | 
						||
 | 
						||
    <span class="hljs-keyword">unless</span> @context
 | 
						||
      varBase = @variable.unwrapAll()
 | 
						||
      <span class="hljs-keyword">unless</span> varBase.isAssignable()
 | 
						||
        @variable.error <span class="hljs-string">"'<span class="hljs-subst">#{@variable.compile o}</span>' can't be assigned"</span>
 | 
						||
 | 
						||
      varBase.eachName (name) =>
 | 
						||
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> name.hasProperties?()
 | 
						||
 | 
						||
        message = isUnassignable name.value
 | 
						||
        name.error message <span class="hljs-keyword">if</span> message</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-165">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-165">¶</a>
 | 
						||
              </div>
 | 
						||
              <p><code>moduleDeclaration</code> can be <code>'import'</code> or <code>'export'</code></p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        @checkAssignability o, name
 | 
						||
        <span class="hljs-keyword">if</span> @moduleDeclaration
 | 
						||
          o.scope.add name.value, @moduleDeclaration
 | 
						||
        <span class="hljs-keyword">else</span>
 | 
						||
          o.scope.find name.value
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> @value <span class="hljs-keyword">instanceof</span> Code
 | 
						||
      <span class="hljs-keyword">if</span> @value.isStatic
 | 
						||
        @value.name = @variable.properties[<span class="hljs-number">0</span>]
 | 
						||
      <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> @variable.properties?.length >= <span class="hljs-number">2</span>
 | 
						||
        [properties..., prototype, name] = @variable.properties
 | 
						||
        @value.name = name <span class="hljs-keyword">if</span> prototype.name?.value <span class="hljs-keyword">is</span> <span class="hljs-string">'prototype'</span>
 | 
						||
 | 
						||
    @value.base.csxAttribute = <span class="hljs-literal">yes</span> <span class="hljs-keyword">if</span> @csx
 | 
						||
    val = @value.compileToFragments o, LEVEL_LIST
 | 
						||
    compiledName = @variable.compileToFragments o, LEVEL_LIST
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> @context <span class="hljs-keyword">is</span> <span class="hljs-string">'object'</span>
 | 
						||
      <span class="hljs-keyword">if</span> @variable.shouldCache()
 | 
						||
        compiledName.unshift @makeCode <span class="hljs-string">'['</span>
 | 
						||
        compiledName.push @makeCode <span class="hljs-string">']'</span>
 | 
						||
      <span class="hljs-keyword">return</span> compiledName.concat @makeCode(<span class="hljs-keyword">if</span> @csx <span class="hljs-keyword">then</span> <span class="hljs-string">'='</span> <span class="hljs-keyword">else</span> <span class="hljs-string">': '</span>), val
 | 
						||
 | 
						||
    answer = compiledName.concat @makeCode(<span class="hljs-string">" <span class="hljs-subst">#{ @context <span class="hljs-keyword">or</span> <span class="hljs-string">'='</span> }</span> "</span>), val</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-166">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-166">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Per <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Assignment_without_declaration">https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Assignment_without_declaration</a>,
 | 
						||
if we’re destructuring without declaring, the destructuring assignment must be wrapped in parentheses.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> o.level > LEVEL_LIST <span class="hljs-keyword">or</span> (o.level <span class="hljs-keyword">is</span> LEVEL_TOP <span class="hljs-keyword">and</span> isValue <span class="hljs-keyword">and</span> @variable.base <span class="hljs-keyword">instanceof</span> Obj <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @nestedLhs <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @param)
 | 
						||
      @wrapInParentheses answer
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      answer</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-167">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-167">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Check object destructuring variable for rest elements;
 | 
						||
can be removed once ES proposal hits Stage 4.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileObjectDestruct: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-168">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-168">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Per <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Assignment_without_declaration">https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Assignment_without_declaration</a>,
 | 
						||
if we’re destructuring without declaring, the destructuring assignment
 | 
						||
must be wrapped in parentheses: <code>({a, b} = obj)</code>. Helper function
 | 
						||
<code>setScopeVar()</code> declares variables <code>a</code> and <code>b</code> at the top of the
 | 
						||
current scope.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre><span class="hljs-function">    <span class="hljs-title">setScopeVar</span> = <span class="hljs-params">(prop)</span> -></span>
 | 
						||
      newVar = <span class="hljs-literal">false</span>
 | 
						||
      <span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> prop <span class="hljs-keyword">instanceof</span> Assign <span class="hljs-keyword">and</span> prop.value.base <span class="hljs-keyword">instanceof</span> Obj
 | 
						||
      <span class="hljs-keyword">if</span> prop <span class="hljs-keyword">instanceof</span> Assign
 | 
						||
        <span class="hljs-keyword">if</span> prop.value.base <span class="hljs-keyword">instanceof</span> IdentifierLiteral
 | 
						||
          newVar = prop.value.base.compileWithoutComments o
 | 
						||
        <span class="hljs-keyword">else</span>
 | 
						||
          newVar = prop.variable.base.compileWithoutComments o
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        newVar = prop.compileWithoutComments o
 | 
						||
      o.scope.add(newVar, <span class="hljs-string">'var'</span>, <span class="hljs-literal">true</span>) <span class="hljs-keyword">if</span> newVar</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-169">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-169">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Returns a safe (cached) reference to the key for a given property</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre><span class="hljs-function">    <span class="hljs-title">getPropKey</span> = <span class="hljs-params">(prop)</span> -></span>
 | 
						||
      <span class="hljs-keyword">if</span> prop <span class="hljs-keyword">instanceof</span> Assign
 | 
						||
        [prop.variable, key] = prop.variable.cache o
 | 
						||
        key
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        prop</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-170">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-170">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Returns the name of a given property for use with excludeProps
 | 
						||
Property names are quoted (e.g. <code>a: b</code> -> ‘a’), and everything else uses the key reference
 | 
						||
(e.g. <code>'a': b -> 'a'</code>, <code>"#{a}": b</code> -> <cached>`)</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre><span class="hljs-function">    <span class="hljs-title">getPropName</span> = <span class="hljs-params">(prop)</span> -></span>
 | 
						||
      key = getPropKey prop
 | 
						||
      cached = prop <span class="hljs-keyword">instanceof</span> Assign <span class="hljs-keyword">and</span> prop.variable <span class="hljs-keyword">isnt</span> key
 | 
						||
      <span class="hljs-keyword">if</span> cached <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> key.isAssignable()
 | 
						||
        key
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        <span class="hljs-keyword">new</span> Literal <span class="hljs-string">"'<span class="hljs-subst">#{key.compileWithoutComments o}</span>'"</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-171">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-171">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Recursive function for searching and storing rest elements in objects.
 | 
						||
e.g. <code>{[properties...]} = source</code>.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre><span class="hljs-function">    <span class="hljs-title">traverseRest</span> = <span class="hljs-params">(properties, source)</span> =></span>
 | 
						||
      restElements = []
 | 
						||
      restIndex = <span class="hljs-literal">undefined</span>
 | 
						||
      source = <span class="hljs-keyword">new</span> Value source <span class="hljs-keyword">unless</span> source.properties?
 | 
						||
 | 
						||
      <span class="hljs-keyword">for</span> prop, index <span class="hljs-keyword">in</span> properties
 | 
						||
        nestedSourceDefault = nestedSource = nestedProperties = <span class="hljs-literal">null</span>
 | 
						||
        setScopeVar prop.unwrap()
 | 
						||
        <span class="hljs-keyword">if</span> prop <span class="hljs-keyword">instanceof</span> Assign</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-172">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-172">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>prop is <code>k: expr</code>, we need to check <code>expr</code> for nested splats</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>          <span class="hljs-keyword">if</span> prop.value.isObject?()</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-173">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-173">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>prop is <code>k = {...}</code></p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>            <span class="hljs-keyword">continue</span> <span class="hljs-keyword">unless</span> prop.context <span class="hljs-keyword">is</span> <span class="hljs-string">'object'</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-174">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-174">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>prop is <code>k: {...}</code></p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>            nestedProperties = prop.value.base.properties
 | 
						||
          <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> prop.value <span class="hljs-keyword">instanceof</span> Assign <span class="hljs-keyword">and</span> prop.value.variable.isObject()</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-175">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-175">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>prop is <code>k: {...} = default</code></p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>            nestedProperties = prop.value.variable.base.properties
 | 
						||
            [prop.value.value, nestedSourceDefault] = prop.value.value.cache o
 | 
						||
          <span class="hljs-keyword">if</span> nestedProperties
 | 
						||
            nestedSource = <span class="hljs-keyword">new</span> Value source.base, source.properties.concat [<span class="hljs-keyword">new</span> Access getPropKey prop]
 | 
						||
            nestedSource = <span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Op <span class="hljs-string">'?'</span>, nestedSource, nestedSourceDefault <span class="hljs-keyword">if</span> nestedSourceDefault
 | 
						||
            restElements.push traverseRest(nestedProperties, nestedSource)...
 | 
						||
        <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> prop <span class="hljs-keyword">instanceof</span> Splat
 | 
						||
          prop.error <span class="hljs-string">"multiple rest elements are disallowed in object destructuring"</span> <span class="hljs-keyword">if</span> restIndex?
 | 
						||
          restIndex = index
 | 
						||
          restElements.push {
 | 
						||
            name: prop.name.unwrapAll()
 | 
						||
            source
 | 
						||
            excludeProps: <span class="hljs-keyword">new</span> Arr (getPropName p <span class="hljs-keyword">for</span> p <span class="hljs-keyword">in</span> properties <span class="hljs-keyword">when</span> p <span class="hljs-keyword">isnt</span> prop)
 | 
						||
          }
 | 
						||
 | 
						||
      <span class="hljs-keyword">if</span> restIndex?</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-176">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-176">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Remove rest element from the properties after iteration</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        properties.splice restIndex, <span class="hljs-number">1</span>
 | 
						||
 | 
						||
      restElements</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-177">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-177">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Cache the value for reuse with rest elements.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> @value.shouldCache()
 | 
						||
      valueRefTemp = <span class="hljs-keyword">new</span> IdentifierLiteral o.scope.freeVariable <span class="hljs-string">'ref'</span>, reserve: <span class="hljs-literal">false</span>
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      valueRefTemp = @value.base</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-178">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-178">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Find all rest elements.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    restElements = traverseRest @variable.base.properties, valueRefTemp
 | 
						||
    <span class="hljs-keyword">return</span> <span class="hljs-literal">no</span> <span class="hljs-keyword">unless</span> restElements <span class="hljs-keyword">and</span> restElements.length > <span class="hljs-number">0</span>
 | 
						||
 | 
						||
    [@value, valueRef] = @value.cache o
 | 
						||
    result = <span class="hljs-keyword">new</span> Block [@]
 | 
						||
 | 
						||
    <span class="hljs-keyword">for</span> restElement <span class="hljs-keyword">in</span> restElements
 | 
						||
      value = <span class="hljs-keyword">new</span> Call <span class="hljs-keyword">new</span> Value(<span class="hljs-keyword">new</span> Literal utility <span class="hljs-string">'objectWithoutKeys'</span>, o), [restElement.source, restElement.excludeProps]
 | 
						||
      result.push <span class="hljs-keyword">new</span> Assign restElement.name, value
 | 
						||
 | 
						||
    fragments = result.compileToFragments o
 | 
						||
    <span class="hljs-keyword">if</span> o.level <span class="hljs-keyword">is</span> LEVEL_TOP</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-179">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-179">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Remove leading tab and trailing semicolon</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      fragments.shift()
 | 
						||
      fragments.pop()
 | 
						||
 | 
						||
    fragments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-180">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-180">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Brief implementation of recursive pattern matching, when assigning array or
 | 
						||
object literals to a value. Peeks at their properties to assign inner names.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileDestructuring: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    top       = o.level <span class="hljs-keyword">is</span> LEVEL_TOP
 | 
						||
    {value}   = <span class="hljs-keyword">this</span>
 | 
						||
    {objects} = @variable.base
 | 
						||
    olen      = objects.length</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-181">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-181">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Special-case for <code>{} = a</code> and <code>[] = a</code> (empty patterns).
 | 
						||
Compile to simply <code>a</code>.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> olen <span class="hljs-keyword">is</span> <span class="hljs-number">0</span>
 | 
						||
      code = value.compileToFragments o
 | 
						||
      <span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> o.level >= LEVEL_OP <span class="hljs-keyword">then</span> @wrapInParentheses code <span class="hljs-keyword">else</span> code
 | 
						||
    [obj] = objects</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-182">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-182">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Disallow <code>[...] = a</code> for some reason. (Could be equivalent to <code>[] = a</code>?)</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> olen <span class="hljs-keyword">is</span> <span class="hljs-number">1</span> <span class="hljs-keyword">and</span> obj <span class="hljs-keyword">instanceof</span> Expansion
 | 
						||
      obj.error <span class="hljs-string">'Destructuring assignment has no target'</span>
 | 
						||
 | 
						||
    isObject = @variable.isObject()</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-183">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-183">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Special case for when there’s only one thing destructured off of
 | 
						||
something. <code>{a} = b</code>, <code>[a] = b</code>, <code>{a: b} = c</code></p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> top <span class="hljs-keyword">and</span> olen <span class="hljs-keyword">is</span> <span class="hljs-number">1</span> <span class="hljs-keyword">and</span> obj <span class="hljs-keyword">not</span> <span class="hljs-keyword">instanceof</span> Splat</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-184">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-184">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Pick the property straight off the value when there’s just one to pick
 | 
						||
(no need to cache the value into a variable).</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      defaultValue = <span class="hljs-literal">undefined</span>
 | 
						||
      <span class="hljs-keyword">if</span> obj <span class="hljs-keyword">instanceof</span> Assign <span class="hljs-keyword">and</span> obj.context <span class="hljs-keyword">is</span> <span class="hljs-string">'object'</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-185">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-185">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>A regular object pattern-match.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        {variable: {base: idx}, value: obj} = obj
 | 
						||
        <span class="hljs-keyword">if</span> obj <span class="hljs-keyword">instanceof</span> Assign
 | 
						||
          defaultValue = obj.value
 | 
						||
          obj = obj.variable
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        <span class="hljs-keyword">if</span> obj <span class="hljs-keyword">instanceof</span> Assign
 | 
						||
          defaultValue = obj.value
 | 
						||
          obj = obj.variable
 | 
						||
        idx = <span class="hljs-keyword">if</span> isObject</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-186">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-186">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>A shorthand <code>{a, b, @c} = val</code> pattern-match.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>          <span class="hljs-keyword">if</span> obj.<span class="hljs-keyword">this</span>
 | 
						||
            obj.properties[<span class="hljs-number">0</span>].name
 | 
						||
          <span class="hljs-keyword">else</span>
 | 
						||
            <span class="hljs-keyword">new</span> PropertyName obj.unwrap().value
 | 
						||
        <span class="hljs-keyword">else</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-187">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-187">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>A regular array pattern-match.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>          <span class="hljs-keyword">new</span> NumberLiteral <span class="hljs-number">0</span>
 | 
						||
      acc   = idx.unwrap() <span class="hljs-keyword">instanceof</span> PropertyName
 | 
						||
      value = <span class="hljs-keyword">new</span> Value value
 | 
						||
      value.properties.push <span class="hljs-keyword">new</span> (<span class="hljs-keyword">if</span> acc <span class="hljs-keyword">then</span> Access <span class="hljs-keyword">else</span> Index) idx
 | 
						||
      message = isUnassignable obj.unwrap().value
 | 
						||
      obj.error message <span class="hljs-keyword">if</span> message
 | 
						||
      <span class="hljs-keyword">if</span> defaultValue
 | 
						||
        defaultValue.isDefaultValue = <span class="hljs-literal">yes</span>
 | 
						||
        value = <span class="hljs-keyword">new</span> Op <span class="hljs-string">'?'</span>, value, defaultValue
 | 
						||
      <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Assign(obj, value, <span class="hljs-literal">null</span>, param: @param).compileToFragments o, LEVEL_TOP
 | 
						||
 | 
						||
    vvar     = value.compileToFragments o, LEVEL_LIST
 | 
						||
    vvarText = fragmentsToText vvar
 | 
						||
    assigns  = []
 | 
						||
    expandedIdx = <span class="hljs-literal">false</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-188">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-188">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>At this point, there are several things to destructure. So the <code>fn()</code> in
 | 
						||
<code>{a, b} = fn()</code> must be cached, for example. Make vvar into a simple
 | 
						||
variable if it isn’t already.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> value.unwrap() <span class="hljs-keyword">not</span> <span class="hljs-keyword">instanceof</span> IdentifierLiteral <span class="hljs-keyword">or</span> @variable.assigns(vvarText)
 | 
						||
      ref = o.scope.freeVariable <span class="hljs-string">'ref'</span>
 | 
						||
      assigns.push [@makeCode(ref + <span class="hljs-string">' = '</span>), vvar...]
 | 
						||
      vvar = [@makeCode ref]
 | 
						||
      vvarText = ref</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-189">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-189">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>And here comes the big loop that handles all of these cases:
 | 
						||
<code>[a, b] = c</code>
 | 
						||
<code>[a..., b] = c</code>
 | 
						||
<code>[..., a, b] = c</code>
 | 
						||
<code>[@a, b] = c</code>
 | 
						||
<code>[a = 1, b] = c</code>
 | 
						||
<code>{a, b} = c</code>
 | 
						||
<code>{@a, b} = c</code>
 | 
						||
<code>{a = 1, b} = c</code>
 | 
						||
etc.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">for</span> obj, i <span class="hljs-keyword">in</span> objects
 | 
						||
      idx = i
 | 
						||
      <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> expandedIdx <span class="hljs-keyword">and</span> obj <span class="hljs-keyword">instanceof</span> Splat
 | 
						||
        name = obj.name.unwrap().value
 | 
						||
        obj = obj.unwrap()
 | 
						||
        val = <span class="hljs-string">"<span class="hljs-subst">#{olen}</span> <= <span class="hljs-subst">#{vvarText}</span>.length ? <span class="hljs-subst">#{utility <span class="hljs-string">'slice'</span>, o}</span>.call(<span class="hljs-subst">#{vvarText}</span>, <span class="hljs-subst">#{i}</span>"</span>
 | 
						||
        rest = olen - i - <span class="hljs-number">1</span>
 | 
						||
        <span class="hljs-keyword">if</span> rest <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span>
 | 
						||
          ivar = o.scope.freeVariable <span class="hljs-string">'i'</span>, single: <span class="hljs-literal">true</span>
 | 
						||
          val += <span class="hljs-string">", <span class="hljs-subst">#{ivar}</span> = <span class="hljs-subst">#{vvarText}</span>.length - <span class="hljs-subst">#{rest}</span>) : (<span class="hljs-subst">#{ivar}</span> = <span class="hljs-subst">#{i}</span>, [])"</span>
 | 
						||
        <span class="hljs-keyword">else</span>
 | 
						||
          val += <span class="hljs-string">") : []"</span>
 | 
						||
        val   = <span class="hljs-keyword">new</span> Literal val
 | 
						||
        expandedIdx = <span class="hljs-string">"<span class="hljs-subst">#{ivar}</span>++"</span>
 | 
						||
      <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> expandedIdx <span class="hljs-keyword">and</span> obj <span class="hljs-keyword">instanceof</span> Expansion
 | 
						||
        rest = olen - i - <span class="hljs-number">1</span>
 | 
						||
        <span class="hljs-keyword">if</span> rest <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span>
 | 
						||
          <span class="hljs-keyword">if</span> rest <span class="hljs-keyword">is</span> <span class="hljs-number">1</span>
 | 
						||
            expandedIdx = <span class="hljs-string">"<span class="hljs-subst">#{vvarText}</span>.length - 1"</span>
 | 
						||
          <span class="hljs-keyword">else</span>
 | 
						||
            ivar = o.scope.freeVariable <span class="hljs-string">'i'</span>, single: <span class="hljs-literal">true</span>
 | 
						||
            val = <span class="hljs-keyword">new</span> Literal <span class="hljs-string">"<span class="hljs-subst">#{ivar}</span> = <span class="hljs-subst">#{vvarText}</span>.length - <span class="hljs-subst">#{rest}</span>"</span>
 | 
						||
            expandedIdx = <span class="hljs-string">"<span class="hljs-subst">#{ivar}</span>++"</span>
 | 
						||
            assigns.push val.compileToFragments o, LEVEL_LIST
 | 
						||
        <span class="hljs-keyword">continue</span>
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        <span class="hljs-keyword">if</span> obj <span class="hljs-keyword">instanceof</span> Splat <span class="hljs-keyword">or</span> obj <span class="hljs-keyword">instanceof</span> Expansion
 | 
						||
          obj.error <span class="hljs-string">"multiple splats/expansions are disallowed in an assignment"</span>
 | 
						||
        defaultValue = <span class="hljs-literal">undefined</span>
 | 
						||
        <span class="hljs-keyword">if</span> obj <span class="hljs-keyword">instanceof</span> Assign <span class="hljs-keyword">and</span> obj.context <span class="hljs-keyword">is</span> <span class="hljs-string">'object'</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-190">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-190">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>A regular object pattern-match.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>          {variable: {base: idx}, value: obj} = obj
 | 
						||
          <span class="hljs-keyword">if</span> obj <span class="hljs-keyword">instanceof</span> Assign
 | 
						||
            defaultValue = obj.value
 | 
						||
            obj = obj.variable
 | 
						||
        <span class="hljs-keyword">else</span>
 | 
						||
          <span class="hljs-keyword">if</span> obj <span class="hljs-keyword">instanceof</span> Assign
 | 
						||
            defaultValue = obj.value
 | 
						||
            obj = obj.variable
 | 
						||
          idx = <span class="hljs-keyword">if</span> isObject</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-191">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-191">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>A shorthand <code>{a, b, @c} = val</code> pattern-match.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>            <span class="hljs-keyword">if</span> obj.<span class="hljs-keyword">this</span>
 | 
						||
              obj.properties[<span class="hljs-number">0</span>].name
 | 
						||
            <span class="hljs-keyword">else</span>
 | 
						||
              <span class="hljs-keyword">new</span> PropertyName obj.unwrap().value
 | 
						||
          <span class="hljs-keyword">else</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-192">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-192">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>A regular array pattern-match.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>            <span class="hljs-keyword">new</span> Literal expandedIdx <span class="hljs-keyword">or</span> idx
 | 
						||
        name = obj.unwrap().value
 | 
						||
        acc = idx.unwrap() <span class="hljs-keyword">instanceof</span> PropertyName
 | 
						||
        val = <span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Literal(vvarText), [<span class="hljs-keyword">new</span> (<span class="hljs-keyword">if</span> acc <span class="hljs-keyword">then</span> Access <span class="hljs-keyword">else</span> Index) idx]
 | 
						||
        <span class="hljs-keyword">if</span> defaultValue
 | 
						||
          defaultValue.isDefaultValue = <span class="hljs-literal">yes</span>
 | 
						||
          val = <span class="hljs-keyword">new</span> Op <span class="hljs-string">'?'</span>, val, defaultValue
 | 
						||
      <span class="hljs-keyword">if</span> name?
 | 
						||
        message = isUnassignable name
 | 
						||
        obj.error message <span class="hljs-keyword">if</span> message
 | 
						||
      assigns.push <span class="hljs-keyword">new</span> Assign(obj, val, <span class="hljs-literal">null</span>, param: @param, subpattern: <span class="hljs-literal">yes</span>).compileToFragments o, LEVEL_LIST
 | 
						||
 | 
						||
    assigns.push vvar <span class="hljs-keyword">unless</span> top <span class="hljs-keyword">or</span> @subpattern
 | 
						||
    fragments = @joinFragmentArrays assigns, <span class="hljs-string">', '</span>
 | 
						||
    <span class="hljs-keyword">if</span> o.level < LEVEL_LIST <span class="hljs-keyword">then</span> fragments <span class="hljs-keyword">else</span> @wrapInParentheses fragments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-193">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-193">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>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.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileConditional: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    [left, right] = @variable.cacheReference o</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-194">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-194">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Disallow conditional assignment of undefined variables.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> left.properties.length <span class="hljs-keyword">and</span> left.base <span class="hljs-keyword">instanceof</span> Literal <span class="hljs-keyword">and</span>
 | 
						||
           left.base <span class="hljs-keyword">not</span> <span class="hljs-keyword">instanceof</span> ThisLiteral <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> o.scope.check left.base.value
 | 
						||
      @variable.error <span class="hljs-string">"the variable \"<span class="hljs-subst">#{left.base.value}</span>\" can't be assigned with <span class="hljs-subst">#{@context}</span> because it has not been declared before"</span>
 | 
						||
    <span class="hljs-keyword">if</span> <span class="hljs-string">"?"</span> <span class="hljs-keyword">in</span> @context
 | 
						||
      o.isExistentialEquals = <span class="hljs-literal">true</span>
 | 
						||
      <span class="hljs-keyword">new</span> If(<span class="hljs-keyword">new</span> Existence(left), right, type: <span class="hljs-string">'if'</span>).addElse(<span class="hljs-keyword">new</span> Assign(right, @value, <span class="hljs-string">'='</span>)).compileToFragments o
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      fragments = <span class="hljs-keyword">new</span> Op(@context[...<span class="hljs-number">-1</span>], left, <span class="hljs-keyword">new</span> Assign(right, @value, <span class="hljs-string">'='</span>)).compileToFragments o
 | 
						||
      <span class="hljs-keyword">if</span> o.level <= LEVEL_LIST <span class="hljs-keyword">then</span> fragments <span class="hljs-keyword">else</span> @wrapInParentheses fragments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-195">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-195">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Convert special math assignment operators like <code>a **= b</code> to the equivalent
 | 
						||
extended form <code>a = a ** b</code> and then compiles that.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileSpecialMath: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    [left, right] = @variable.cacheReference o
 | 
						||
    <span class="hljs-keyword">new</span> Assign(left, <span class="hljs-keyword">new</span> Op(@context[...<span class="hljs-number">-1</span>], right, @value)).compileToFragments o</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-196">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-196">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Compile the assignment from an array splice literal, using JavaScript’s
 | 
						||
<code>Array#splice</code> method.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileSplice: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    {range: {<span class="hljs-keyword">from</span>, to, exclusive}} = @variable.properties.pop()
 | 
						||
    unwrappedVar = @variable.unwrapAll()
 | 
						||
    <span class="hljs-keyword">if</span> unwrappedVar.comments
 | 
						||
      moveComments unwrappedVar, @
 | 
						||
      <span class="hljs-keyword">delete</span> @variable.comments
 | 
						||
    name = @variable.compile o
 | 
						||
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">from</span>
 | 
						||
      [fromDecl, fromRef] = @cacheToCodeFragments <span class="hljs-keyword">from</span>.cache o, LEVEL_OP
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      fromDecl = fromRef = <span class="hljs-string">'0'</span>
 | 
						||
    <span class="hljs-keyword">if</span> to
 | 
						||
      <span class="hljs-keyword">if</span> <span class="hljs-keyword">from</span>?.isNumber() <span class="hljs-keyword">and</span> to.isNumber()
 | 
						||
        to = to.compile(o) - fromRef
 | 
						||
        to += <span class="hljs-number">1</span> <span class="hljs-keyword">unless</span> exclusive
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        to = to.compile(o, LEVEL_ACCESS) + <span class="hljs-string">' - '</span> + fromRef
 | 
						||
        to += <span class="hljs-string">' + 1'</span> <span class="hljs-keyword">unless</span> exclusive
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      to = <span class="hljs-string">"9e9"</span>
 | 
						||
    [valDef, valRef] = @value.cache o, LEVEL_LIST
 | 
						||
    answer = [].concat @makeCode(<span class="hljs-string">"<span class="hljs-subst">#{utility <span class="hljs-string">'splice'</span>, o}</span>.apply(<span class="hljs-subst">#{name}</span>, [<span class="hljs-subst">#{fromDecl}</span>, <span class="hljs-subst">#{to}</span>].concat("</span>), valDef, @makeCode(<span class="hljs-string">")), "</span>), valRef
 | 
						||
    <span class="hljs-keyword">if</span> o.level > LEVEL_TOP <span class="hljs-keyword">then</span> @wrapInParentheses answer <span class="hljs-keyword">else</span> answer
 | 
						||
 | 
						||
  eachName: <span class="hljs-function"><span class="hljs-params">(iterator)</span> -></span>
 | 
						||
    @variable.unwrapAll().eachName iterator</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-197">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-197">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="funcglyph">FuncGlyph</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>
 | 
						||
exports.FuncGlyph = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FuncGlyph</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@glyph)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-198">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-198">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="code">Code</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-199">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-199">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>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 Code
 | 
						||
has no <em>children</em> – they’re within the inner scope.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Code = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Code</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(params, body, @funcGlyph)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
    @params      = params <span class="hljs-keyword">or</span> []
 | 
						||
    @body        = body <span class="hljs-keyword">or</span> <span class="hljs-keyword">new</span> Block
 | 
						||
    @bound       = @funcGlyph?.glyph <span class="hljs-keyword">is</span> <span class="hljs-string">'=>'</span>
 | 
						||
    @isGenerator = <span class="hljs-literal">no</span>
 | 
						||
    @isAsync     = <span class="hljs-literal">no</span>
 | 
						||
    @isMethod    = <span class="hljs-literal">no</span>
 | 
						||
 | 
						||
    @body.traverseChildren <span class="hljs-literal">no</span>, <span class="hljs-function"><span class="hljs-params">(node)</span> =></span>
 | 
						||
      <span class="hljs-keyword">if</span> (node <span class="hljs-keyword">instanceof</span> Op <span class="hljs-keyword">and</span> node.isYield()) <span class="hljs-keyword">or</span> node <span class="hljs-keyword">instanceof</span> YieldReturn
 | 
						||
        @isGenerator = <span class="hljs-literal">yes</span>
 | 
						||
      <span class="hljs-keyword">if</span> (node <span class="hljs-keyword">instanceof</span> Op <span class="hljs-keyword">and</span> node.isAwait()) <span class="hljs-keyword">or</span> node <span class="hljs-keyword">instanceof</span> AwaitReturn
 | 
						||
        @isAsync = <span class="hljs-literal">yes</span>
 | 
						||
      <span class="hljs-keyword">if</span> @isGenerator <span class="hljs-keyword">and</span> @isAsync
 | 
						||
        node.error <span class="hljs-string">"function can't contain both yield and await"</span>
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'params'</span>, <span class="hljs-string">'body'</span>]
 | 
						||
 | 
						||
  isStatement: <span class="hljs-function">-></span> @isMethod
 | 
						||
 | 
						||
  jumps: NO
 | 
						||
 | 
						||
  makeScope: <span class="hljs-function"><span class="hljs-params">(parentScope)</span> -></span> <span class="hljs-keyword">new</span> Scope parentScope, @body, <span class="hljs-keyword">this</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-200">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-200">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Compilation creates a new scope unless explicitly asked to share with the
 | 
						||
outer scope. Handles splat parameters in the parameter list by setting
 | 
						||
such parameters to be the final parameter in the function definition, as
 | 
						||
required per the ES2015 spec. If the CoffeeScript function definition had
 | 
						||
parameters after the splat, they are declared via expressions in the
 | 
						||
function body.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    <span class="hljs-keyword">if</span> @ctor
 | 
						||
      @name.error <span class="hljs-string">'Class constructor may not be async'</span>       <span class="hljs-keyword">if</span> @isAsync
 | 
						||
      @name.error <span class="hljs-string">'Class constructor may not be a generator'</span> <span class="hljs-keyword">if</span> @isGenerator
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> @bound
 | 
						||
      @context = o.scope.method.context <span class="hljs-keyword">if</span> o.scope.method?.bound
 | 
						||
      @context = <span class="hljs-string">'this'</span> <span class="hljs-keyword">unless</span> @context
 | 
						||
 | 
						||
    o.scope         = del(o, <span class="hljs-string">'classScope'</span>) <span class="hljs-keyword">or</span> @makeScope o.scope
 | 
						||
    o.scope.shared  = del(o, <span class="hljs-string">'sharedScope'</span>)
 | 
						||
    o.indent        += TAB
 | 
						||
    <span class="hljs-keyword">delete</span> o.bare
 | 
						||
    <span class="hljs-keyword">delete</span> o.isExistentialEquals
 | 
						||
    params           = []
 | 
						||
    exprs            = []
 | 
						||
    thisAssignments  = @thisAssignments?.slice() ? []
 | 
						||
    paramsAfterSplat = []
 | 
						||
    haveSplatParam   = <span class="hljs-literal">no</span>
 | 
						||
    haveBodyParam    = <span class="hljs-literal">no</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-201">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-201">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Check for duplicate parameters and separate <code>this</code> assignments.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    paramNames = []
 | 
						||
    @eachParamName (name, node, param) ->
 | 
						||
      node.error <span class="hljs-string">"multiple parameters named '<span class="hljs-subst">#{name}</span>'"</span> <span class="hljs-keyword">if</span> name <span class="hljs-keyword">in</span> paramNames
 | 
						||
      paramNames.push name
 | 
						||
      <span class="hljs-keyword">if</span> node.<span class="hljs-keyword">this</span>
 | 
						||
        name   = node.properties[<span class="hljs-number">0</span>].name.value
 | 
						||
        name   = <span class="hljs-string">"_<span class="hljs-subst">#{name}</span>"</span> <span class="hljs-keyword">if</span> name <span class="hljs-keyword">in</span> JS_FORBIDDEN
 | 
						||
        target = <span class="hljs-keyword">new</span> IdentifierLiteral o.scope.freeVariable name
 | 
						||
        param.renameParam node, target
 | 
						||
        thisAssignments.push <span class="hljs-keyword">new</span> Assign node, target</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-202">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-202">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Parse the parameters, adding them to the list of parameters to put in the
 | 
						||
function definition; and dealing with splats or expansions, including
 | 
						||
adding expressions to the function body to declare all parameter
 | 
						||
variables that would have been after the splat/expansion parameter.
 | 
						||
If we encounter a parameter that needs to be declared in the function
 | 
						||
body for any reason, for example it’s destructured with <code>this</code>, also
 | 
						||
declare and assign all subsequent parameters in the function body so that
 | 
						||
any non-idempotent parameters are evaluated in the correct order.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">for</span> param, i <span class="hljs-keyword">in</span> @params</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-203">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-203">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Was <code>...</code> used with this parameter? (Only one such parameter is allowed
 | 
						||
per function.) Splat/expansion parameters cannot have default values,
 | 
						||
so we need not worry about that.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      <span class="hljs-keyword">if</span> param.splat <span class="hljs-keyword">or</span> param <span class="hljs-keyword">instanceof</span> Expansion
 | 
						||
        <span class="hljs-keyword">if</span> haveSplatParam
 | 
						||
          param.error <span class="hljs-string">'only one splat or expansion parameter is allowed per function definition'</span>
 | 
						||
        <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> param <span class="hljs-keyword">instanceof</span> Expansion <span class="hljs-keyword">and</span> @params.length <span class="hljs-keyword">is</span> <span class="hljs-number">1</span>
 | 
						||
          param.error <span class="hljs-string">'an expansion parameter cannot be the only parameter in a function definition'</span>
 | 
						||
        haveSplatParam = <span class="hljs-literal">yes</span>
 | 
						||
        <span class="hljs-keyword">if</span> param.splat
 | 
						||
          <span class="hljs-keyword">if</span> param.name <span class="hljs-keyword">instanceof</span> Arr</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-204">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-204">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Splat arrays are treated oddly by ES; deal with them the legacy
 | 
						||
way in the function body. TODO: Should this be handled in the
 | 
						||
function parameter list, and if so, how?</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>            splatParamName = o.scope.freeVariable <span class="hljs-string">'arg'</span>
 | 
						||
            params.push ref = <span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> IdentifierLiteral splatParamName
 | 
						||
            exprs.push <span class="hljs-keyword">new</span> Assign <span class="hljs-keyword">new</span> Value(param.name), ref
 | 
						||
          <span class="hljs-keyword">else</span>
 | 
						||
            params.push ref = param.asReference o
 | 
						||
            splatParamName = fragmentsToText ref.compileNodeWithoutComments o
 | 
						||
          <span class="hljs-keyword">if</span> param.shouldCache()
 | 
						||
            exprs.push <span class="hljs-keyword">new</span> Assign <span class="hljs-keyword">new</span> Value(param.name), ref
 | 
						||
        <span class="hljs-keyword">else</span> <span class="hljs-comment"># `param` is an Expansion</span>
 | 
						||
          splatParamName = o.scope.freeVariable <span class="hljs-string">'args'</span>
 | 
						||
          params.push <span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> IdentifierLiteral splatParamName
 | 
						||
 | 
						||
        o.scope.parameter splatParamName</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-205">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-205">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Parse all other parameters; if a splat paramater has not yet been
 | 
						||
encountered, add these other parameters to the list to be output in
 | 
						||
the function definition.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      <span class="hljs-keyword">else</span>
 | 
						||
        <span class="hljs-keyword">if</span> param.shouldCache() <span class="hljs-keyword">or</span> haveBodyParam
 | 
						||
          param.assignedInBody = <span class="hljs-literal">yes</span>
 | 
						||
          haveBodyParam = <span class="hljs-literal">yes</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-206">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-206">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>This parameter cannot be declared or assigned in the parameter
 | 
						||
list. So put a reference in the parameter list and add a statement
 | 
						||
to the function body assigning it, e.g.
 | 
						||
<code>(arg) => { var a = arg.a; }</code>, with a default value if it has one.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>          <span class="hljs-keyword">if</span> param.value?
 | 
						||
            condition = <span class="hljs-keyword">new</span> Op <span class="hljs-string">'==='</span>, param, <span class="hljs-keyword">new</span> UndefinedLiteral
 | 
						||
            ifTrue = <span class="hljs-keyword">new</span> Assign <span class="hljs-keyword">new</span> Value(param.name), param.value
 | 
						||
            exprs.push <span class="hljs-keyword">new</span> If condition, ifTrue
 | 
						||
          <span class="hljs-keyword">else</span>
 | 
						||
            exprs.push <span class="hljs-keyword">new</span> Assign <span class="hljs-keyword">new</span> Value(param.name), param.asReference(o)</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-207">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-207">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>If this parameter comes before the splat or expansion, it will go
 | 
						||
in the function definition parameter list.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        <span class="hljs-keyword">unless</span> haveSplatParam</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-208">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-208">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>If this parameter has a default value, and it hasn’t already been
 | 
						||
set by the <code>shouldCache()</code> block above, define it as a statement in
 | 
						||
the function body. This parameter comes after the splat parameter,
 | 
						||
so we can’t define its default value in the parameter list.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>          <span class="hljs-keyword">if</span> param.shouldCache()
 | 
						||
            ref = param.asReference o
 | 
						||
          <span class="hljs-keyword">else</span>
 | 
						||
            <span class="hljs-keyword">if</span> param.value? <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> param.assignedInBody
 | 
						||
              ref = <span class="hljs-keyword">new</span> Assign <span class="hljs-keyword">new</span> Value(param.name), param.value, <span class="hljs-literal">null</span>, param: <span class="hljs-literal">yes</span>
 | 
						||
            <span class="hljs-keyword">else</span>
 | 
						||
              ref = param</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-209">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-209">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Add this parameter’s reference(s) to the function scope.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>          <span class="hljs-keyword">if</span> param.name <span class="hljs-keyword">instanceof</span> Arr <span class="hljs-keyword">or</span> param.name <span class="hljs-keyword">instanceof</span> Obj</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-210">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-210">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>This parameter is destructured.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>            param.name.lhs = <span class="hljs-literal">yes</span>
 | 
						||
            param.name.eachName (prop) ->
 | 
						||
              o.scope.parameter prop.value</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-211">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-211">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Compile <code>foo({a, b...}) -></code> to <code>foo(arg) -> {a, b...} = arg</code>.
 | 
						||
Can be removed once ES proposal hits Stage 4.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>            <span class="hljs-keyword">if</span> param.name <span class="hljs-keyword">instanceof</span> Obj <span class="hljs-keyword">and</span> param.name.hasSplat()
 | 
						||
              splatParamName = o.scope.freeVariable <span class="hljs-string">'arg'</span>
 | 
						||
              o.scope.parameter splatParamName
 | 
						||
              ref = <span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> IdentifierLiteral splatParamName
 | 
						||
              exprs.push <span class="hljs-keyword">new</span> Assign <span class="hljs-keyword">new</span> Value(param.name), ref</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-212">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-212">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Compile <code>foo({a, b...} = {}) -></code> to <code>foo(arg = {}) -> {a, b...} = arg</code>.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>              <span class="hljs-keyword">if</span> param.value?  <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> param.assignedInBody
 | 
						||
                ref = <span class="hljs-keyword">new</span> Assign ref, param.value, <span class="hljs-literal">null</span>, param: <span class="hljs-literal">yes</span>
 | 
						||
          <span class="hljs-keyword">else</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-213">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-213">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>This compilation of the parameter is only to get its name to add
 | 
						||
to the scope name tracking; since the compilation output here
 | 
						||
isn’t kept for eventual output, don’t include comments in this
 | 
						||
compilation, so that they get output the “real” time this param
 | 
						||
is compiled.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>            paramToAddToScope = <span class="hljs-keyword">if</span> param.value? <span class="hljs-keyword">then</span> param <span class="hljs-keyword">else</span> ref
 | 
						||
            o.scope.parameter fragmentsToText paramToAddToScope.compileToFragmentsWithoutComments o
 | 
						||
          params.push ref
 | 
						||
        <span class="hljs-keyword">else</span>
 | 
						||
          paramsAfterSplat.push param</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-214">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-214">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>If this parameter had a default value, since it’s no longer in the
 | 
						||
function parameter list we need to assign its default value
 | 
						||
(if necessary) as an expression in the body.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>          <span class="hljs-keyword">if</span> param.value? <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> param.shouldCache()
 | 
						||
            condition = <span class="hljs-keyword">new</span> Op <span class="hljs-string">'==='</span>, param, <span class="hljs-keyword">new</span> UndefinedLiteral
 | 
						||
            ifTrue = <span class="hljs-keyword">new</span> Assign <span class="hljs-keyword">new</span> Value(param.name), param.value
 | 
						||
            exprs.push <span class="hljs-keyword">new</span> If condition, ifTrue</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-215">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-215">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Add this parameter to the scope, since it wouldn’t have been added
 | 
						||
yet since it was skipped earlier.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>          o.scope.add param.name.value, <span class="hljs-string">'var'</span>, <span class="hljs-literal">yes</span> <span class="hljs-keyword">if</span> param.name?.value?</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-216">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-216">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>If there were parameters after the splat or expansion parameter, those
 | 
						||
parameters need to be assigned in the body of the function.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> paramsAfterSplat.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-217">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-217">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Create a destructured assignment, e.g. <code>[a, b, c] = [args..., b, c]</code></p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      exprs.unshift <span class="hljs-keyword">new</span> Assign <span class="hljs-keyword">new</span> Value(
 | 
						||
          <span class="hljs-keyword">new</span> Arr [<span class="hljs-keyword">new</span> Splat(<span class="hljs-keyword">new</span> IdentifierLiteral(splatParamName)), (param.asReference o <span class="hljs-keyword">for</span> param <span class="hljs-keyword">in</span> paramsAfterSplat)...]
 | 
						||
        ), <span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> IdentifierLiteral splatParamName</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-218">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-218">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Add new expressions to the function body</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    wasEmpty = @body.isEmpty()
 | 
						||
    @body.expressions.unshift thisAssignments... <span class="hljs-keyword">unless</span> @expandCtorSuper thisAssignments
 | 
						||
    @body.expressions.unshift exprs...
 | 
						||
    <span class="hljs-keyword">if</span> @isMethod <span class="hljs-keyword">and</span> @bound <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @isStatic <span class="hljs-keyword">and</span> @classVariable
 | 
						||
      boundMethodCheck = <span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Literal utility <span class="hljs-string">'boundMethodCheck'</span>, o
 | 
						||
      @body.expressions.unshift <span class="hljs-keyword">new</span> Call(boundMethodCheck, [<span class="hljs-keyword">new</span> Value(<span class="hljs-keyword">new</span> ThisLiteral), @classVariable])
 | 
						||
    @body.makeReturn() <span class="hljs-keyword">unless</span> wasEmpty <span class="hljs-keyword">or</span> @noReturn</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-219">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-219">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Assemble the output</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    modifiers = []
 | 
						||
    modifiers.push <span class="hljs-string">'static'</span> <span class="hljs-keyword">if</span> @isMethod <span class="hljs-keyword">and</span> @isStatic
 | 
						||
    modifiers.push <span class="hljs-string">'async'</span>  <span class="hljs-keyword">if</span> @isAsync
 | 
						||
    <span class="hljs-keyword">unless</span> @isMethod <span class="hljs-keyword">or</span> @bound
 | 
						||
      modifiers.push <span class="hljs-string">"function<span class="hljs-subst">#{<span class="hljs-keyword">if</span> @isGenerator <span class="hljs-keyword">then</span> <span class="hljs-string">'*'</span> <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>}</span>"</span>
 | 
						||
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> @isGenerator
 | 
						||
      modifiers.push <span class="hljs-string">'*'</span>
 | 
						||
 | 
						||
    signature = [@makeCode <span class="hljs-string">'('</span>]
 | 
						||
    <span class="hljs-keyword">for</span> param, i <span class="hljs-keyword">in</span> params
 | 
						||
      signature.push @makeCode <span class="hljs-string">', '</span> <span class="hljs-keyword">if</span> i <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span>
 | 
						||
      signature.push @makeCode <span class="hljs-string">'...'</span> <span class="hljs-keyword">if</span> haveSplatParam <span class="hljs-keyword">and</span> i <span class="hljs-keyword">is</span> params.length - <span class="hljs-number">1</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-220">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-220">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Compile this parameter, but if any generated variables get created
 | 
						||
(e.g. <code>ref</code>), shift those into the parent scope since we can’t put a
 | 
						||
<code>var</code> line inside a function parameter list.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      scopeVariablesCount = o.scope.variables.length
 | 
						||
      signature.push param.compileToFragments(o)...
 | 
						||
      <span class="hljs-keyword">if</span> scopeVariablesCount <span class="hljs-keyword">isnt</span> o.scope.variables.length
 | 
						||
        generatedVariables = o.scope.variables.splice scopeVariablesCount
 | 
						||
        o.scope.parent.variables.push generatedVariables...
 | 
						||
    signature.push @makeCode <span class="hljs-string">')'</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-221">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-221">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Block comments between <code>)</code> and <code>-></code>/<code>=></code> get output between <code>)</code> and <code>{</code>.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> @funcGlyph?.comments?
 | 
						||
      comment.unshift = <span class="hljs-literal">no</span> <span class="hljs-keyword">for</span> comment <span class="hljs-keyword">in</span> @funcGlyph.comments
 | 
						||
      @compileCommentFragments o, @funcGlyph, signature
 | 
						||
 | 
						||
    body = @body.compileWithDeclarations o <span class="hljs-keyword">unless</span> @body.isEmpty()</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-222">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-222">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>We need to compile the body before method names to ensure <code>super</code>
 | 
						||
references are handled.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> @isMethod
 | 
						||
      [methodScope, o.scope] = [o.scope, o.scope.parent]
 | 
						||
      name = @name.compileToFragments o
 | 
						||
      name.shift() <span class="hljs-keyword">if</span> name[<span class="hljs-number">0</span>].code <span class="hljs-keyword">is</span> <span class="hljs-string">'.'</span>
 | 
						||
      o.scope = methodScope
 | 
						||
 | 
						||
    answer = @joinFragmentArrays (@makeCode m <span class="hljs-keyword">for</span> m <span class="hljs-keyword">in</span> modifiers), <span class="hljs-string">' '</span>
 | 
						||
    answer.push @makeCode <span class="hljs-string">' '</span> <span class="hljs-keyword">if</span> modifiers.length <span class="hljs-keyword">and</span> name
 | 
						||
    answer.push name... <span class="hljs-keyword">if</span> name
 | 
						||
    answer.push signature...
 | 
						||
    answer.push @makeCode <span class="hljs-string">' =>'</span> <span class="hljs-keyword">if</span> @bound <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @isMethod
 | 
						||
    answer.push @makeCode <span class="hljs-string">' {'</span>
 | 
						||
    answer.push @makeCode(<span class="hljs-string">'\n'</span>), body..., @makeCode(<span class="hljs-string">"\n<span class="hljs-subst">#{@tab}</span>"</span>) <span class="hljs-keyword">if</span> body?.length
 | 
						||
    answer.push @makeCode <span class="hljs-string">'}'</span>
 | 
						||
 | 
						||
    <span class="hljs-keyword">return</span> indentInitial answer, @ <span class="hljs-keyword">if</span> @isMethod
 | 
						||
    <span class="hljs-keyword">if</span> @front <span class="hljs-keyword">or</span> (o.level >= LEVEL_ACCESS) <span class="hljs-keyword">then</span> @wrapInParentheses answer <span class="hljs-keyword">else</span> answer
 | 
						||
 | 
						||
  eachParamName: <span class="hljs-function"><span class="hljs-params">(iterator)</span> -></span>
 | 
						||
    param.eachName iterator <span class="hljs-keyword">for</span> param <span class="hljs-keyword">in</span> @params</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-223">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-223">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Short-circuit <code>traverseChildren</code> method to prevent it from crossing scope
 | 
						||
boundaries unless <code>crossScope</code> is <code>true</code>.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  traverseChildren: <span class="hljs-function"><span class="hljs-params">(crossScope, func)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>(crossScope, func) <span class="hljs-keyword">if</span> crossScope</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-224">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-224">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Short-circuit <code>replaceInContext</code> method to prevent it from crossing context boundaries. Bound
 | 
						||
functions have the same context.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  replaceInContext: <span class="hljs-function"><span class="hljs-params">(child, replacement)</span> -></span>
 | 
						||
    <span class="hljs-keyword">if</span> @bound
 | 
						||
      <span class="hljs-keyword">super</span> child, replacement
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      <span class="hljs-literal">false</span>
 | 
						||
 | 
						||
  expandCtorSuper: <span class="hljs-function"><span class="hljs-params">(thisAssignments)</span> -></span>
 | 
						||
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span> <span class="hljs-keyword">unless</span> @ctor
 | 
						||
 | 
						||
    @eachSuperCall Block.wrap(@params), <span class="hljs-function"><span class="hljs-params">(superCall)</span> -></span>
 | 
						||
      superCall.error <span class="hljs-string">"'super' is not allowed in constructor parameter defaults"</span>
 | 
						||
 | 
						||
    seenSuper = @eachSuperCall @body, <span class="hljs-function"><span class="hljs-params">(superCall)</span> =></span>
 | 
						||
      superCall.error <span class="hljs-string">"'super' is only allowed in derived class constructors"</span> <span class="hljs-keyword">if</span> @ctor <span class="hljs-keyword">is</span> <span class="hljs-string">'base'</span>
 | 
						||
      superCall.expressions = thisAssignments
 | 
						||
 | 
						||
    haveThisParam = thisAssignments.length <span class="hljs-keyword">and</span> thisAssignments.length <span class="hljs-keyword">isnt</span> @thisAssignments?.length
 | 
						||
    <span class="hljs-keyword">if</span> @ctor <span class="hljs-keyword">is</span> <span class="hljs-string">'derived'</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> seenSuper <span class="hljs-keyword">and</span> haveThisParam
 | 
						||
      param = thisAssignments[<span class="hljs-number">0</span>].variable
 | 
						||
      param.error <span class="hljs-string">"Can't use @params in derived class constructors without calling super"</span>
 | 
						||
 | 
						||
    seenSuper</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-225">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-225">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Find all super calls in the given context node
 | 
						||
Returns <code>true</code> if <code>iterator</code> is called</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  eachSuperCall: <span class="hljs-function"><span class="hljs-params">(context, iterator)</span> -></span>
 | 
						||
    seenSuper = <span class="hljs-literal">no</span>
 | 
						||
 | 
						||
    context.traverseChildren <span class="hljs-literal">true</span>, <span class="hljs-function"><span class="hljs-params">(child)</span> =></span>
 | 
						||
      <span class="hljs-keyword">if</span> child <span class="hljs-keyword">instanceof</span> SuperCall
 | 
						||
        seenSuper = <span class="hljs-literal">yes</span>
 | 
						||
        iterator child
 | 
						||
      <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> child <span class="hljs-keyword">instanceof</span> ThisLiteral <span class="hljs-keyword">and</span> @ctor <span class="hljs-keyword">is</span> <span class="hljs-string">'derived'</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> seenSuper
 | 
						||
        child.error <span class="hljs-string">"Can't reference 'this' before calling super in derived class constructors"</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-226">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-226">¶</a>
 | 
						||
              </div>
 | 
						||
              <p><code>super</code> has the same target in bound (arrow) functions, so check them too</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      child <span class="hljs-keyword">not</span> <span class="hljs-keyword">instanceof</span> SuperCall <span class="hljs-keyword">and</span> (child <span class="hljs-keyword">not</span> <span class="hljs-keyword">instanceof</span> Code <span class="hljs-keyword">or</span> child.bound)
 | 
						||
 | 
						||
    seenSuper</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-227">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-227">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="param">Param</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-228">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-228">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>A parameter in a function definition. Beyond a typical JavaScript parameter,
 | 
						||
these parameters can also attach themselves to the context of the function,
 | 
						||
as well as be a splat, gathering up a group of parameters into an array.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Param = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Param</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@name, @value, @splat)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
    message = isUnassignable @name.unwrapAll().value
 | 
						||
    @name.error message <span class="hljs-keyword">if</span> message
 | 
						||
    <span class="hljs-keyword">if</span> @name <span class="hljs-keyword">instanceof</span> Obj <span class="hljs-keyword">and</span> @name.generated
 | 
						||
      token = @name.objects[<span class="hljs-number">0</span>].operatorToken
 | 
						||
      token.error <span class="hljs-string">"unexpected <span class="hljs-subst">#{token.value}</span>"</span>
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'name'</span>, <span class="hljs-string">'value'</span>]
 | 
						||
 | 
						||
  compileToFragments: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    @name.compileToFragments o, LEVEL_LIST
 | 
						||
 | 
						||
  compileToFragmentsWithoutComments: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    @name.compileToFragmentsWithoutComments o, LEVEL_LIST
 | 
						||
 | 
						||
  asReference: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    <span class="hljs-keyword">return</span> @reference <span class="hljs-keyword">if</span> @reference
 | 
						||
    node = @name
 | 
						||
    <span class="hljs-keyword">if</span> node.<span class="hljs-keyword">this</span>
 | 
						||
      name = node.properties[<span class="hljs-number">0</span>].name.value
 | 
						||
      name = <span class="hljs-string">"_<span class="hljs-subst">#{name}</span>"</span> <span class="hljs-keyword">if</span> name <span class="hljs-keyword">in</span> JS_FORBIDDEN
 | 
						||
      node = <span class="hljs-keyword">new</span> IdentifierLiteral o.scope.freeVariable name
 | 
						||
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> node.shouldCache()
 | 
						||
      node = <span class="hljs-keyword">new</span> IdentifierLiteral o.scope.freeVariable <span class="hljs-string">'arg'</span>
 | 
						||
    node = <span class="hljs-keyword">new</span> Value node
 | 
						||
    node.updateLocationDataIfMissing @locationData
 | 
						||
    @reference = node
 | 
						||
 | 
						||
  shouldCache: <span class="hljs-function">-></span>
 | 
						||
    @name.shouldCache()</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-229">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-229">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Iterates the name or names of a <code>Param</code>.
 | 
						||
In a sense, a destructured parameter represents multiple JS parameters. This
 | 
						||
method allows to iterate them all.
 | 
						||
The <code>iterator</code> function will be called as <code>iterator(name, node)</code> where
 | 
						||
<code>name</code> is the name of the parameter and <code>node</code> is the AST node corresponding
 | 
						||
to that name.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  eachName: <span class="hljs-function"><span class="hljs-params">(iterator, name = @name)</span> -></span>
 | 
						||
<span class="hljs-function">    <span class="hljs-title">atParam</span> = <span class="hljs-params">(obj)</span> =></span> iterator <span class="hljs-string">"@<span class="hljs-subst">#{obj.properties[<span class="hljs-number">0</span>].name.value}</span>"</span>, obj, @</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-230">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-230">¶</a>
 | 
						||
              </div>
 | 
						||
              <ul>
 | 
						||
<li>simple literals <code>foo</code></li>
 | 
						||
</ul>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">return</span> iterator name.value, name, @ <span class="hljs-keyword">if</span> name <span class="hljs-keyword">instanceof</span> Literal</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-231">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-231">¶</a>
 | 
						||
              </div>
 | 
						||
              <ul>
 | 
						||
<li>at-params <code>@foo</code></li>
 | 
						||
</ul>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">return</span> atParam name <span class="hljs-keyword">if</span> name <span class="hljs-keyword">instanceof</span> Value
 | 
						||
    <span class="hljs-keyword">for</span> obj <span class="hljs-keyword">in</span> name.objects ? []</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-232">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-232">¶</a>
 | 
						||
              </div>
 | 
						||
              <ul>
 | 
						||
<li>destructured parameter with default value</li>
 | 
						||
</ul>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      <span class="hljs-keyword">if</span> obj <span class="hljs-keyword">instanceof</span> Assign <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> obj.context?
 | 
						||
        obj = obj.variable</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-233">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-233">¶</a>
 | 
						||
              </div>
 | 
						||
              <ul>
 | 
						||
<li>assignments within destructured parameters <code>{foo:bar}</code></li>
 | 
						||
</ul>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      <span class="hljs-keyword">if</span> obj <span class="hljs-keyword">instanceof</span> Assign</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-234">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-234">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>… possibly with a default value</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        <span class="hljs-keyword">if</span> obj.value <span class="hljs-keyword">instanceof</span> Assign
 | 
						||
          obj = obj.value.variable
 | 
						||
        <span class="hljs-keyword">else</span>
 | 
						||
          obj = obj.value
 | 
						||
        @eachName iterator, obj.unwrap()</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-235">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-235">¶</a>
 | 
						||
              </div>
 | 
						||
              <ul>
 | 
						||
<li>splats within destructured parameters <code>[xs...]</code></li>
 | 
						||
</ul>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> obj <span class="hljs-keyword">instanceof</span> Splat
 | 
						||
        node = obj.name.unwrap()
 | 
						||
        iterator node.value, node, @
 | 
						||
      <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> obj <span class="hljs-keyword">instanceof</span> Value</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-236">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-236">¶</a>
 | 
						||
              </div>
 | 
						||
              <ul>
 | 
						||
<li>destructured parameters within destructured parameters <code>[{a}]</code></li>
 | 
						||
</ul>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        <span class="hljs-keyword">if</span> obj.isArray() <span class="hljs-keyword">or</span> obj.isObject()
 | 
						||
          @eachName iterator, obj.base</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-237">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-237">¶</a>
 | 
						||
              </div>
 | 
						||
              <ul>
 | 
						||
<li>at-params within destructured parameters <code>{@foo}</code></li>
 | 
						||
</ul>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> obj.<span class="hljs-keyword">this</span>
 | 
						||
          atParam obj</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-238">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-238">¶</a>
 | 
						||
              </div>
 | 
						||
              <ul>
 | 
						||
<li>simple destructured parameters {foo}</li>
 | 
						||
</ul>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        <span class="hljs-keyword">else</span> iterator obj.base.value, obj.base, @
 | 
						||
      <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> obj <span class="hljs-keyword">not</span> <span class="hljs-keyword">instanceof</span> Expansion
 | 
						||
        obj.error <span class="hljs-string">"illegal parameter <span class="hljs-subst">#{obj.compile()}</span>"</span>
 | 
						||
    <span class="hljs-keyword">return</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-239">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-239">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Rename a param by replacing the given AST node for a name with a new node.
 | 
						||
This needs to ensure that the the source for object destructuring does not change.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  renameParam: <span class="hljs-function"><span class="hljs-params">(node, newNode)</span> -></span>
 | 
						||
<span class="hljs-function">    <span class="hljs-title">isNode</span>      = <span class="hljs-params">(candidate)</span> -></span> candidate <span class="hljs-keyword">is</span> node
 | 
						||
<span class="hljs-function">    <span class="hljs-title">replacement</span> = <span class="hljs-params">(node, parent)</span> =></span>
 | 
						||
      <span class="hljs-keyword">if</span> parent <span class="hljs-keyword">instanceof</span> Obj
 | 
						||
        key = node
 | 
						||
        key = node.properties[<span class="hljs-number">0</span>].name <span class="hljs-keyword">if</span> node.<span class="hljs-keyword">this</span>
 | 
						||
        <span class="hljs-keyword">new</span> Assign <span class="hljs-keyword">new</span> Value(key), newNode, <span class="hljs-string">'object'</span>
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        newNode
 | 
						||
 | 
						||
    @replaceInContext isNode, replacement</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-240">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-240">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="splat">Splat</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-241">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-241">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>A splat, either as a parameter to a function, an argument to a call,
 | 
						||
or as part of a destructuring assignment.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Splat = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Splat</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(name)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
    @name = <span class="hljs-keyword">if</span> name.compile <span class="hljs-keyword">then</span> name <span class="hljs-keyword">else</span> <span class="hljs-keyword">new</span> Literal name
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'name'</span>]
 | 
						||
 | 
						||
  isAssignable: <span class="hljs-function">-></span>
 | 
						||
    @name.isAssignable() <span class="hljs-keyword">and</span> (<span class="hljs-keyword">not</span> @name.isAtomic <span class="hljs-keyword">or</span> @name.isAtomic())
 | 
						||
 | 
						||
  assigns: <span class="hljs-function"><span class="hljs-params">(name)</span> -></span>
 | 
						||
    @name.assigns name
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    [@makeCode(<span class="hljs-string">'...'</span>), @name.compileToFragments(o, LEVEL_OP)...]
 | 
						||
 | 
						||
  unwrap: <span class="hljs-function">-></span> @name</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-242">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-242">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="expansion">Expansion</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-243">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-243">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Used to skip values inside an array destructuring (pattern matching) or
 | 
						||
parameter list.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Expansion = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Expansion</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
 | 
						||
  shouldCache: NO
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    @error <span class="hljs-string">'Expansion must be used inside a destructuring assignment or parameter list'</span>
 | 
						||
 | 
						||
  asReference: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    <span class="hljs-keyword">this</span>
 | 
						||
 | 
						||
  eachName: <span class="hljs-function"><span class="hljs-params">(iterator)</span> -></span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-244">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-244">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="while">While</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-245">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-245">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>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.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.While = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">While</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(condition, options)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
    @condition = <span class="hljs-keyword">if</span> options?.invert <span class="hljs-keyword">then</span> condition.invert() <span class="hljs-keyword">else</span> condition
 | 
						||
    @guard     = options?.guard
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'condition'</span>, <span class="hljs-string">'guard'</span>, <span class="hljs-string">'body'</span>]
 | 
						||
 | 
						||
  isStatement: YES
 | 
						||
 | 
						||
  makeReturn: <span class="hljs-function"><span class="hljs-params">(res)</span> -></span>
 | 
						||
    <span class="hljs-keyword">if</span> res
 | 
						||
      <span class="hljs-keyword">super</span> res
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      @returns = <span class="hljs-keyword">not</span> @jumps()
 | 
						||
      <span class="hljs-keyword">this</span>
 | 
						||
 | 
						||
  addBody: <span class="hljs-function"><span class="hljs-params">(@body)</span> -></span>
 | 
						||
    <span class="hljs-keyword">this</span>
 | 
						||
 | 
						||
  jumps: <span class="hljs-function">-></span>
 | 
						||
    {expressions} = @body
 | 
						||
    <span class="hljs-keyword">return</span> <span class="hljs-literal">no</span> <span class="hljs-keyword">unless</span> expressions.length
 | 
						||
    <span class="hljs-keyword">for</span> node <span class="hljs-keyword">in</span> expressions
 | 
						||
      <span class="hljs-keyword">return</span> jumpNode <span class="hljs-keyword">if</span> jumpNode = node.jumps loop: <span class="hljs-literal">yes</span>
 | 
						||
    <span class="hljs-literal">no</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-246">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-246">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>The main difference from a JavaScript <em>while</em> is that the CoffeeScript
 | 
						||
<em>while</em> can be used as a part of a larger expression – while loops may
 | 
						||
return an array containing the computed result of each iteration.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    o.indent += TAB
 | 
						||
    set      = <span class="hljs-string">''</span>
 | 
						||
    {body}   = <span class="hljs-keyword">this</span>
 | 
						||
    <span class="hljs-keyword">if</span> body.isEmpty()
 | 
						||
      body = @makeCode <span class="hljs-string">''</span>
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      <span class="hljs-keyword">if</span> @returns
 | 
						||
        body.makeReturn rvar = o.scope.freeVariable <span class="hljs-string">'results'</span>
 | 
						||
        set  = <span class="hljs-string">"<span class="hljs-subst">#{@tab}</span><span class="hljs-subst">#{rvar}</span> = [];\n"</span>
 | 
						||
      <span class="hljs-keyword">if</span> @guard
 | 
						||
        <span class="hljs-keyword">if</span> body.expressions.length > <span class="hljs-number">1</span>
 | 
						||
          body.expressions.unshift <span class="hljs-keyword">new</span> If (<span class="hljs-keyword">new</span> Parens @guard).invert(), <span class="hljs-keyword">new</span> StatementLiteral <span class="hljs-string">"continue"</span>
 | 
						||
        <span class="hljs-keyword">else</span>
 | 
						||
          body = Block.wrap [<span class="hljs-keyword">new</span> If @guard, body] <span class="hljs-keyword">if</span> @guard
 | 
						||
      body = [].concat @makeCode(<span class="hljs-string">"\n"</span>), (body.compileToFragments o, LEVEL_TOP), @makeCode(<span class="hljs-string">"\n<span class="hljs-subst">#{@tab}</span>"</span>)
 | 
						||
    answer = [].concat @makeCode(set + @tab + <span class="hljs-string">"while ("</span>), @condition.compileToFragments(o, LEVEL_PAREN),
 | 
						||
      @makeCode(<span class="hljs-string">") {"</span>), body, @makeCode(<span class="hljs-string">"}"</span>)
 | 
						||
    <span class="hljs-keyword">if</span> @returns
 | 
						||
      answer.push @makeCode <span class="hljs-string">"\n<span class="hljs-subst">#{@tab}</span>return <span class="hljs-subst">#{rvar}</span>;"</span>
 | 
						||
    answer</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-247">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-247">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="op">Op</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-248">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-248">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Simple Arithmetic and logical operations. Performs some conversion from
 | 
						||
CoffeeScript operations into their JavaScript equivalents.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Op = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Op</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(op, first, second, flip)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> In first, second <span class="hljs-keyword">if</span> op <span class="hljs-keyword">is</span> <span class="hljs-string">'in'</span>
 | 
						||
    <span class="hljs-keyword">if</span> op <span class="hljs-keyword">is</span> <span class="hljs-string">'do'</span>
 | 
						||
      <span class="hljs-keyword">return</span> Op::generateDo first
 | 
						||
    <span class="hljs-keyword">if</span> op <span class="hljs-keyword">is</span> <span class="hljs-string">'new'</span>
 | 
						||
      <span class="hljs-keyword">if</span> (firstCall = first.unwrap()) <span class="hljs-keyword">instanceof</span> Call <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> firstCall.<span class="hljs-keyword">do</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> firstCall.isNew
 | 
						||
        <span class="hljs-keyword">return</span> firstCall.newInstance()
 | 
						||
      first = <span class="hljs-keyword">new</span> Parens first   <span class="hljs-keyword">if</span> first <span class="hljs-keyword">instanceof</span> Code <span class="hljs-keyword">and</span> first.bound <span class="hljs-keyword">or</span> first.<span class="hljs-keyword">do</span>
 | 
						||
 | 
						||
    @operator = CONVERSIONS[op] <span class="hljs-keyword">or</span> op
 | 
						||
    @first    = first
 | 
						||
    @second   = second
 | 
						||
    @flip     = !!flip
 | 
						||
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-249">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-249">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>The map of conversions from CoffeeScript to JavaScript symbols.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  CONVERSIONS =
 | 
						||
    <span class="hljs-string">'=='</span>:        <span class="hljs-string">'==='</span>
 | 
						||
    <span class="hljs-string">'!='</span>:        <span class="hljs-string">'!=='</span>
 | 
						||
    <span class="hljs-string">'of'</span>:        <span class="hljs-string">'in'</span>
 | 
						||
    <span class="hljs-string">'yieldfrom'</span>: <span class="hljs-string">'yield*'</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-250">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-250">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>The map of invertible operators.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  INVERSIONS =
 | 
						||
    <span class="hljs-string">'!=='</span>: <span class="hljs-string">'==='</span>
 | 
						||
    <span class="hljs-string">'==='</span>: <span class="hljs-string">'!=='</span>
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'first'</span>, <span class="hljs-string">'second'</span>]
 | 
						||
 | 
						||
  isNumber: <span class="hljs-function">-></span>
 | 
						||
    @isUnary() <span class="hljs-keyword">and</span> @operator <span class="hljs-keyword">in</span> [<span class="hljs-string">'+'</span>, <span class="hljs-string">'-'</span>] <span class="hljs-keyword">and</span>
 | 
						||
      @first <span class="hljs-keyword">instanceof</span> Value <span class="hljs-keyword">and</span> @first.isNumber()
 | 
						||
 | 
						||
  isAwait: <span class="hljs-function">-></span>
 | 
						||
    @operator <span class="hljs-keyword">is</span> <span class="hljs-string">'await'</span>
 | 
						||
 | 
						||
  isYield: <span class="hljs-function">-></span>
 | 
						||
    @operator <span class="hljs-keyword">in</span> [<span class="hljs-string">'yield'</span>, <span class="hljs-string">'yield*'</span>]
 | 
						||
 | 
						||
  isUnary: <span class="hljs-function">-></span>
 | 
						||
    <span class="hljs-keyword">not</span> @second
 | 
						||
 | 
						||
  shouldCache: <span class="hljs-function">-></span>
 | 
						||
    <span class="hljs-keyword">not</span> @isNumber()</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-251">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-251">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Am I capable of
 | 
						||
<a href="https://docs.python.org/3/reference/expressions.html#not-in">Python-style comparison chaining</a>?</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  isChainable: <span class="hljs-function">-></span>
 | 
						||
    @operator <span class="hljs-keyword">in</span> [<span class="hljs-string">'<'</span>, <span class="hljs-string">'>'</span>, <span class="hljs-string">'>='</span>, <span class="hljs-string">'<='</span>, <span class="hljs-string">'==='</span>, <span class="hljs-string">'!=='</span>]
 | 
						||
 | 
						||
  invert: <span class="hljs-function">-></span>
 | 
						||
    <span class="hljs-keyword">if</span> @isChainable() <span class="hljs-keyword">and</span> @first.isChainable()
 | 
						||
      allInvertable = <span class="hljs-literal">yes</span>
 | 
						||
      curr = <span class="hljs-keyword">this</span>
 | 
						||
      <span class="hljs-keyword">while</span> curr <span class="hljs-keyword">and</span> curr.operator
 | 
						||
        allInvertable <span class="hljs-keyword">and</span>= (curr.operator <span class="hljs-keyword">of</span> INVERSIONS)
 | 
						||
        curr = curr.first
 | 
						||
      <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Parens(<span class="hljs-keyword">this</span>).invert() <span class="hljs-keyword">unless</span> allInvertable
 | 
						||
      curr = <span class="hljs-keyword">this</span>
 | 
						||
      <span class="hljs-keyword">while</span> curr <span class="hljs-keyword">and</span> curr.operator
 | 
						||
        curr.invert = !curr.invert
 | 
						||
        curr.operator = INVERSIONS[curr.operator]
 | 
						||
        curr = curr.first
 | 
						||
      <span class="hljs-keyword">this</span>
 | 
						||
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> op = INVERSIONS[@operator]
 | 
						||
      @operator = op
 | 
						||
      <span class="hljs-keyword">if</span> @first.unwrap() <span class="hljs-keyword">instanceof</span> Op
 | 
						||
        @first.invert()
 | 
						||
      <span class="hljs-keyword">this</span>
 | 
						||
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> @second
 | 
						||
      <span class="hljs-keyword">new</span> Parens(<span class="hljs-keyword">this</span>).invert()
 | 
						||
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> @operator <span class="hljs-keyword">is</span> <span class="hljs-string">'!'</span> <span class="hljs-keyword">and</span> (fst = @first.unwrap()) <span class="hljs-keyword">instanceof</span> Op <span class="hljs-keyword">and</span>
 | 
						||
                                  fst.operator <span class="hljs-keyword">in</span> [<span class="hljs-string">'!'</span>, <span class="hljs-string">'in'</span>, <span class="hljs-string">'instanceof'</span>]
 | 
						||
      fst
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      <span class="hljs-keyword">new</span> Op <span class="hljs-string">'!'</span>, <span class="hljs-keyword">this</span>
 | 
						||
 | 
						||
  unfoldSoak: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    @operator <span class="hljs-keyword">in</span> [<span class="hljs-string">'++'</span>, <span class="hljs-string">'--'</span>, <span class="hljs-string">'delete'</span>] <span class="hljs-keyword">and</span> unfoldSoak o, <span class="hljs-keyword">this</span>, <span class="hljs-string">'first'</span>
 | 
						||
 | 
						||
  generateDo: <span class="hljs-function"><span class="hljs-params">(exp)</span> -></span>
 | 
						||
    passedParams = []
 | 
						||
    func = <span class="hljs-keyword">if</span> exp <span class="hljs-keyword">instanceof</span> Assign <span class="hljs-keyword">and</span> (ref = exp.value.unwrap()) <span class="hljs-keyword">instanceof</span> Code
 | 
						||
      ref
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      exp
 | 
						||
    <span class="hljs-keyword">for</span> param <span class="hljs-keyword">in</span> func.params <span class="hljs-keyword">or</span> []
 | 
						||
      <span class="hljs-keyword">if</span> param.value
 | 
						||
        passedParams.push param.value
 | 
						||
        <span class="hljs-keyword">delete</span> param.value
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        passedParams.push param
 | 
						||
    call = <span class="hljs-keyword">new</span> Call exp, passedParams
 | 
						||
    call.<span class="hljs-keyword">do</span> = <span class="hljs-literal">yes</span>
 | 
						||
    call
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    isChain = @isChainable() <span class="hljs-keyword">and</span> @first.isChainable()</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-252">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-252">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>In chains, there’s no need to wrap bare obj literals in parens,
 | 
						||
as the chained expression is wrapped.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    @first.front = @front <span class="hljs-keyword">unless</span> isChain
 | 
						||
    <span class="hljs-keyword">if</span> @operator <span class="hljs-keyword">is</span> <span class="hljs-string">'delete'</span> <span class="hljs-keyword">and</span> o.scope.check(@first.unwrapAll().value)
 | 
						||
      @error <span class="hljs-string">'delete operand may not be argument or var'</span>
 | 
						||
    <span class="hljs-keyword">if</span> @operator <span class="hljs-keyword">in</span> [<span class="hljs-string">'--'</span>, <span class="hljs-string">'++'</span>]
 | 
						||
      message = isUnassignable @first.unwrapAll().value
 | 
						||
      @first.error message <span class="hljs-keyword">if</span> message
 | 
						||
    <span class="hljs-keyword">return</span> @compileContinuation o <span class="hljs-keyword">if</span> @isYield() <span class="hljs-keyword">or</span> @isAwait()
 | 
						||
    <span class="hljs-keyword">return</span> @compileUnary        o <span class="hljs-keyword">if</span> @isUnary()
 | 
						||
    <span class="hljs-keyword">return</span> @compileChain        o <span class="hljs-keyword">if</span> isChain
 | 
						||
    <span class="hljs-keyword">switch</span> @operator
 | 
						||
      <span class="hljs-keyword">when</span> <span class="hljs-string">'?'</span>  <span class="hljs-keyword">then</span> @compileExistence o, @second.isDefaultValue
 | 
						||
      <span class="hljs-keyword">when</span> <span class="hljs-string">'**'</span> <span class="hljs-keyword">then</span> @compilePower o
 | 
						||
      <span class="hljs-keyword">when</span> <span class="hljs-string">'//'</span> <span class="hljs-keyword">then</span> @compileFloorDivision o
 | 
						||
      <span class="hljs-keyword">when</span> <span class="hljs-string">'%%'</span> <span class="hljs-keyword">then</span> @compileModulo o
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        lhs = @first.compileToFragments o, LEVEL_OP
 | 
						||
        rhs = @second.compileToFragments o, LEVEL_OP
 | 
						||
        answer = [].concat lhs, @makeCode(<span class="hljs-string">" <span class="hljs-subst">#{@operator}</span> "</span>), rhs
 | 
						||
        <span class="hljs-keyword">if</span> o.level <= LEVEL_OP <span class="hljs-keyword">then</span> answer <span class="hljs-keyword">else</span> @wrapInParentheses answer</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-253">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-253">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Mimic Python’s chained comparisons when multiple comparison operators are
 | 
						||
used sequentially. For example:</p>
 | 
						||
<pre><code>bin/coffee -e <span class="hljs-string">'console.log 50 < 65 > 10'</span>
 | 
						||
<span class="hljs-literal">true</span>
 | 
						||
</code></pre>
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileChain: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    [@first.second, shared] = @first.second.cache o
 | 
						||
    fst = @first.compileToFragments o, LEVEL_OP
 | 
						||
    fragments = fst.concat @makeCode(<span class="hljs-string">" <span class="hljs-subst">#{<span class="hljs-keyword">if</span> @invert <span class="hljs-keyword">then</span> <span class="hljs-string">'&&'</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'||'</span>}</span> "</span>),
 | 
						||
      (shared.compileToFragments o), @makeCode(<span class="hljs-string">" <span class="hljs-subst">#{@operator}</span> "</span>), (@second.compileToFragments o, LEVEL_OP)
 | 
						||
    @wrapInParentheses fragments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-254">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-254">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Keep reference to the left expression, unless this an existential assignment</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileExistence: <span class="hljs-function"><span class="hljs-params">(o, checkOnlyUndefined)</span> -></span>
 | 
						||
    <span class="hljs-keyword">if</span> @first.shouldCache()
 | 
						||
      ref = <span class="hljs-keyword">new</span> IdentifierLiteral o.scope.freeVariable <span class="hljs-string">'ref'</span>
 | 
						||
      fst = <span class="hljs-keyword">new</span> Parens <span class="hljs-keyword">new</span> Assign ref, @first
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      fst = @first
 | 
						||
      ref = fst
 | 
						||
    <span class="hljs-keyword">new</span> If(<span class="hljs-keyword">new</span> Existence(fst, checkOnlyUndefined), ref, type: <span class="hljs-string">'if'</span>).addElse(@second).compileToFragments o</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-255">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-255">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Compile a unary <strong>Op</strong>.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileUnary: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    parts = []
 | 
						||
    op = @operator
 | 
						||
    parts.push [@makeCode op]
 | 
						||
    <span class="hljs-keyword">if</span> op <span class="hljs-keyword">is</span> <span class="hljs-string">'!'</span> <span class="hljs-keyword">and</span> @first <span class="hljs-keyword">instanceof</span> Existence
 | 
						||
      @first.negated = <span class="hljs-keyword">not</span> @first.negated
 | 
						||
      <span class="hljs-keyword">return</span> @first.compileToFragments o
 | 
						||
    <span class="hljs-keyword">if</span> o.level >= LEVEL_ACCESS
 | 
						||
      <span class="hljs-keyword">return</span> (<span class="hljs-keyword">new</span> Parens <span class="hljs-keyword">this</span>).compileToFragments o
 | 
						||
    plusMinus = op <span class="hljs-keyword">in</span> [<span class="hljs-string">'+'</span>, <span class="hljs-string">'-'</span>]
 | 
						||
    parts.push [@makeCode(<span class="hljs-string">' '</span>)] <span class="hljs-keyword">if</span> op <span class="hljs-keyword">in</span> [<span class="hljs-string">'new'</span>, <span class="hljs-string">'typeof'</span>, <span class="hljs-string">'delete'</span>] <span class="hljs-keyword">or</span>
 | 
						||
                      plusMinus <span class="hljs-keyword">and</span> @first <span class="hljs-keyword">instanceof</span> Op <span class="hljs-keyword">and</span> @first.operator <span class="hljs-keyword">is</span> op
 | 
						||
    <span class="hljs-keyword">if</span> (plusMinus <span class="hljs-keyword">and</span> @first <span class="hljs-keyword">instanceof</span> Op) <span class="hljs-keyword">or</span> (op <span class="hljs-keyword">is</span> <span class="hljs-string">'new'</span> <span class="hljs-keyword">and</span> @first.isStatement o)
 | 
						||
      @first = <span class="hljs-keyword">new</span> Parens @first
 | 
						||
    parts.push @first.compileToFragments o, LEVEL_OP
 | 
						||
    parts.reverse() <span class="hljs-keyword">if</span> @flip
 | 
						||
    @joinFragmentArrays parts, <span class="hljs-string">''</span>
 | 
						||
 | 
						||
  compileContinuation: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    parts = []
 | 
						||
    op = @operator
 | 
						||
    <span class="hljs-keyword">unless</span> o.scope.parent?
 | 
						||
      @error <span class="hljs-string">"<span class="hljs-subst">#{@operator}</span> can only occur inside functions"</span>
 | 
						||
    <span class="hljs-keyword">if</span> o.scope.method?.bound <span class="hljs-keyword">and</span> o.scope.method.isGenerator
 | 
						||
      @error <span class="hljs-string">'yield cannot occur inside bound (fat arrow) functions'</span>
 | 
						||
    <span class="hljs-keyword">if</span> <span class="hljs-string">'expression'</span> <span class="hljs-keyword">in</span> Object.keys(@first) <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> (@first <span class="hljs-keyword">instanceof</span> Throw)
 | 
						||
      parts.push @first.expression.compileToFragments o, LEVEL_OP <span class="hljs-keyword">if</span> @first.expression?
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      parts.push [@makeCode <span class="hljs-string">"("</span>] <span class="hljs-keyword">if</span> o.level >= LEVEL_PAREN
 | 
						||
      parts.push [@makeCode op]
 | 
						||
      parts.push [@makeCode <span class="hljs-string">" "</span>] <span class="hljs-keyword">if</span> @first.base?.value <span class="hljs-keyword">isnt</span> <span class="hljs-string">''</span>
 | 
						||
      parts.push @first.compileToFragments o, LEVEL_OP
 | 
						||
      parts.push [@makeCode <span class="hljs-string">")"</span>] <span class="hljs-keyword">if</span> o.level >= LEVEL_PAREN
 | 
						||
    @joinFragmentArrays parts, <span class="hljs-string">''</span>
 | 
						||
 | 
						||
  compilePower: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-256">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-256">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Make a Math.pow call</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    pow = <span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> IdentifierLiteral(<span class="hljs-string">'Math'</span>), [<span class="hljs-keyword">new</span> Access <span class="hljs-keyword">new</span> PropertyName <span class="hljs-string">'pow'</span>]
 | 
						||
    <span class="hljs-keyword">new</span> Call(pow, [@first, @second]).compileToFragments o
 | 
						||
 | 
						||
  compileFloorDivision: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    floor = <span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> IdentifierLiteral(<span class="hljs-string">'Math'</span>), [<span class="hljs-keyword">new</span> Access <span class="hljs-keyword">new</span> PropertyName <span class="hljs-string">'floor'</span>]
 | 
						||
    second = <span class="hljs-keyword">if</span> @second.shouldCache() <span class="hljs-keyword">then</span> <span class="hljs-keyword">new</span> Parens @second <span class="hljs-keyword">else</span> @second
 | 
						||
    div = <span class="hljs-keyword">new</span> Op <span class="hljs-string">'/'</span>, @first, second
 | 
						||
    <span class="hljs-keyword">new</span> Call(floor, [div]).compileToFragments o
 | 
						||
 | 
						||
  compileModulo: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    mod = <span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Literal utility <span class="hljs-string">'modulo'</span>, o
 | 
						||
    <span class="hljs-keyword">new</span> Call(mod, [@first, @second]).compileToFragments o
 | 
						||
 | 
						||
  toString: <span class="hljs-function"><span class="hljs-params">(idt)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span> idt, @constructor.name + <span class="hljs-string">' '</span> + @operator</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-257">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-257">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="in">In</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.In = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">In</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@object, @array)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'object'</span>, <span class="hljs-string">'array'</span>]
 | 
						||
 | 
						||
  invert: NEGATE
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    <span class="hljs-keyword">if</span> @array <span class="hljs-keyword">instanceof</span> Value <span class="hljs-keyword">and</span> @array.isArray() <span class="hljs-keyword">and</span> @array.base.objects.length
 | 
						||
      <span class="hljs-keyword">for</span> obj <span class="hljs-keyword">in</span> @array.base.objects <span class="hljs-keyword">when</span> obj <span class="hljs-keyword">instanceof</span> Splat
 | 
						||
        hasSplat = <span class="hljs-literal">yes</span>
 | 
						||
        <span class="hljs-keyword">break</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-258">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-258">¶</a>
 | 
						||
              </div>
 | 
						||
              <p><code>compileOrTest</code> only if we have an array literal with no splats</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      <span class="hljs-keyword">return</span> @compileOrTest o <span class="hljs-keyword">unless</span> hasSplat
 | 
						||
    @compileLoopTest o
 | 
						||
 | 
						||
  compileOrTest: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    [sub, ref] = @object.cache o, LEVEL_OP
 | 
						||
    [cmp, cnj] = <span class="hljs-keyword">if</span> @negated <span class="hljs-keyword">then</span> [<span class="hljs-string">' !== '</span>, <span class="hljs-string">' && '</span>] <span class="hljs-keyword">else</span> [<span class="hljs-string">' === '</span>, <span class="hljs-string">' || '</span>]
 | 
						||
    tests = []
 | 
						||
    <span class="hljs-keyword">for</span> item, i <span class="hljs-keyword">in</span> @array.base.objects
 | 
						||
      <span class="hljs-keyword">if</span> i <span class="hljs-keyword">then</span> tests.push @makeCode cnj
 | 
						||
      tests = tests.concat (<span class="hljs-keyword">if</span> i <span class="hljs-keyword">then</span> ref <span class="hljs-keyword">else</span> sub), @makeCode(cmp), item.compileToFragments(o, LEVEL_ACCESS)
 | 
						||
    <span class="hljs-keyword">if</span> o.level < LEVEL_OP <span class="hljs-keyword">then</span> tests <span class="hljs-keyword">else</span> @wrapInParentheses tests
 | 
						||
 | 
						||
  compileLoopTest: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    [sub, ref] = @object.cache o, LEVEL_LIST
 | 
						||
    fragments = [].concat @makeCode(utility(<span class="hljs-string">'indexOf'</span>, o) + <span class="hljs-string">".call("</span>), @array.compileToFragments(o, LEVEL_LIST),
 | 
						||
      @makeCode(<span class="hljs-string">", "</span>), ref, @makeCode(<span class="hljs-string">") "</span> + <span class="hljs-keyword">if</span> @negated <span class="hljs-keyword">then</span> <span class="hljs-string">'< 0'</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'>= 0'</span>)
 | 
						||
    <span class="hljs-keyword">return</span> fragments <span class="hljs-keyword">if</span> fragmentsToText(sub) <span class="hljs-keyword">is</span> fragmentsToText(ref)
 | 
						||
    fragments = sub.concat @makeCode(<span class="hljs-string">', '</span>), fragments
 | 
						||
    <span class="hljs-keyword">if</span> o.level < LEVEL_LIST <span class="hljs-keyword">then</span> fragments <span class="hljs-keyword">else</span> @wrapInParentheses fragments
 | 
						||
 | 
						||
  toString: <span class="hljs-function"><span class="hljs-params">(idt)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span> idt, @constructor.name + <span class="hljs-keyword">if</span> @negated <span class="hljs-keyword">then</span> <span class="hljs-string">'!'</span> <span class="hljs-keyword">else</span> <span class="hljs-string">''</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-259">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-259">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="try">Try</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-260">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-260">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>A classic <em>try/catch/finally</em> block.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Try = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Try</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@attempt, @errorVariable, @recovery, @ensure)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'attempt'</span>, <span class="hljs-string">'recovery'</span>, <span class="hljs-string">'ensure'</span>]
 | 
						||
 | 
						||
  isStatement: YES
 | 
						||
 | 
						||
  jumps: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span> @attempt.jumps(o) <span class="hljs-keyword">or</span> @recovery?.jumps(o)
 | 
						||
 | 
						||
  makeReturn: <span class="hljs-function"><span class="hljs-params">(res)</span> -></span>
 | 
						||
    @attempt  = @attempt .makeReturn res <span class="hljs-keyword">if</span> @attempt
 | 
						||
    @recovery = @recovery.makeReturn res <span class="hljs-keyword">if</span> @recovery
 | 
						||
    <span class="hljs-keyword">this</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-261">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-261">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Compilation is more or less as you would expect – the <em>finally</em> clause
 | 
						||
is optional, the <em>catch</em> is not.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    o.indent  += TAB
 | 
						||
    tryPart   = @attempt.compileToFragments o, LEVEL_TOP
 | 
						||
 | 
						||
    catchPart = <span class="hljs-keyword">if</span> @recovery
 | 
						||
      generatedErrorVariableName = o.scope.freeVariable <span class="hljs-string">'error'</span>, reserve: <span class="hljs-literal">no</span>
 | 
						||
      placeholder = <span class="hljs-keyword">new</span> IdentifierLiteral generatedErrorVariableName
 | 
						||
      <span class="hljs-keyword">if</span> @errorVariable
 | 
						||
        message = isUnassignable @errorVariable.unwrapAll().value
 | 
						||
        @errorVariable.error message <span class="hljs-keyword">if</span> message
 | 
						||
        @recovery.unshift <span class="hljs-keyword">new</span> Assign @errorVariable, placeholder
 | 
						||
      [].concat @makeCode(<span class="hljs-string">" catch ("</span>), placeholder.compileToFragments(o), @makeCode(<span class="hljs-string">") {\n"</span>),
 | 
						||
        @recovery.compileToFragments(o, LEVEL_TOP), @makeCode(<span class="hljs-string">"\n<span class="hljs-subst">#{@tab}</span>}"</span>)
 | 
						||
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">unless</span> @ensure <span class="hljs-keyword">or</span> @recovery
 | 
						||
      generatedErrorVariableName = o.scope.freeVariable <span class="hljs-string">'error'</span>, reserve: <span class="hljs-literal">no</span>
 | 
						||
      [@makeCode(<span class="hljs-string">" catch (<span class="hljs-subst">#{generatedErrorVariableName}</span>) {}"</span>)]
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      []
 | 
						||
 | 
						||
    ensurePart = <span class="hljs-keyword">if</span> @ensure <span class="hljs-keyword">then</span> ([].concat @makeCode(<span class="hljs-string">" finally {\n"</span>), @ensure.compileToFragments(o, LEVEL_TOP),
 | 
						||
      @makeCode(<span class="hljs-string">"\n<span class="hljs-subst">#{@tab}</span>}"</span>)) <span class="hljs-keyword">else</span> []
 | 
						||
 | 
						||
    [].concat @makeCode(<span class="hljs-string">"<span class="hljs-subst">#{@tab}</span>try {\n"</span>),
 | 
						||
      tryPart,
 | 
						||
      @makeCode(<span class="hljs-string">"\n<span class="hljs-subst">#{@tab}</span>}"</span>), catchPart, ensurePart</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-262">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-262">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="throw">Throw</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-263">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-263">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Simple node to throw an exception.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Throw = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Throw</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@expression)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'expression'</span>]
 | 
						||
 | 
						||
  isStatement: YES
 | 
						||
  jumps:       NO</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-264">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-264">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>A <strong>Throw</strong> is already a return, of sorts…</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  makeReturn: THIS
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    fragments = @expression.compileToFragments o, LEVEL_LIST
 | 
						||
    unshiftAfterComments fragments, @makeCode <span class="hljs-string">'throw '</span>
 | 
						||
    fragments.unshift @makeCode @tab
 | 
						||
    fragments.push @makeCode <span class="hljs-string">';'</span>
 | 
						||
    fragments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-265">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-265">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="existence">Existence</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-266">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-266">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Checks a variable for existence – not <code>null</code> and not <code>undefined</code>. This is
 | 
						||
similar to <code>.nil?</code> in Ruby, and avoids having to consult a JavaScript truth
 | 
						||
table. Optionally only check if a variable is not <code>undefined</code>.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Existence = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Existence</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@expression, onlyNotUndefined = <span class="hljs-literal">no</span>)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
    @comparisonTarget = <span class="hljs-keyword">if</span> onlyNotUndefined <span class="hljs-keyword">then</span> <span class="hljs-string">'undefined'</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'null'</span>
 | 
						||
    salvagedComments = []
 | 
						||
    @expression.eachChild (child) ->
 | 
						||
      <span class="hljs-keyword">if</span> child.comments
 | 
						||
        <span class="hljs-keyword">for</span> comment <span class="hljs-keyword">in</span> child.comments
 | 
						||
          salvagedComments.push comment <span class="hljs-keyword">unless</span> comment <span class="hljs-keyword">in</span> salvagedComments
 | 
						||
        <span class="hljs-keyword">delete</span> child.comments
 | 
						||
      <span class="hljs-keyword">if</span> child.name?.comments
 | 
						||
        <span class="hljs-keyword">for</span> comment <span class="hljs-keyword">in</span> child.name.comments
 | 
						||
          salvagedComments.push comment <span class="hljs-keyword">unless</span> comment <span class="hljs-keyword">in</span> salvagedComments
 | 
						||
        <span class="hljs-keyword">delete</span> child.name.comments
 | 
						||
    attachCommentsToNode salvagedComments, @
 | 
						||
    moveComments @expression, @
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'expression'</span>]
 | 
						||
 | 
						||
  invert: NEGATE
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    @expression.front = @front
 | 
						||
    code = @expression.compile o, LEVEL_OP
 | 
						||
    <span class="hljs-keyword">if</span> @expression.unwrap() <span class="hljs-keyword">instanceof</span> IdentifierLiteral <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> o.scope.check code
 | 
						||
      [cmp, cnj] = <span class="hljs-keyword">if</span> @negated <span class="hljs-keyword">then</span> [<span class="hljs-string">'==='</span>, <span class="hljs-string">'||'</span>] <span class="hljs-keyword">else</span> [<span class="hljs-string">'!=='</span>, <span class="hljs-string">'&&'</span>]
 | 
						||
      code = <span class="hljs-string">"typeof <span class="hljs-subst">#{code}</span> <span class="hljs-subst">#{cmp}</span> \"undefined\""</span> + <span class="hljs-keyword">if</span> @comparisonTarget <span class="hljs-keyword">isnt</span> <span class="hljs-string">'undefined'</span> <span class="hljs-keyword">then</span> <span class="hljs-string">" <span class="hljs-subst">#{cnj}</span> <span class="hljs-subst">#{code}</span> <span class="hljs-subst">#{cmp}</span> <span class="hljs-subst">#{@comparisonTarget}</span>"</span> <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>
 | 
						||
    <span class="hljs-keyword">else</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-267">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-267">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>We explicity want to use loose equality (<code>==</code>) when comparing against <code>null</code>,
 | 
						||
so that an existence check roughly corresponds to a check for truthiness.
 | 
						||
Do <em>not</em> change this to <code>===</code> for <code>null</code>, as this will break mountains of
 | 
						||
existing code. When comparing only against <code>undefined</code>, however, we want to
 | 
						||
use <code>===</code> because this use case is for parity with ES2015+ default values,
 | 
						||
which only get assigned when the variable is <code>undefined</code> (but not <code>null</code>).</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>      cmp = <span class="hljs-keyword">if</span> @comparisonTarget <span class="hljs-keyword">is</span> <span class="hljs-string">'null'</span>
 | 
						||
        <span class="hljs-keyword">if</span> @negated <span class="hljs-keyword">then</span> <span class="hljs-string">'=='</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'!='</span>
 | 
						||
      <span class="hljs-keyword">else</span> <span class="hljs-comment"># `undefined`</span>
 | 
						||
        <span class="hljs-keyword">if</span> @negated <span class="hljs-keyword">then</span> <span class="hljs-string">'==='</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'!=='</span>
 | 
						||
      code = <span class="hljs-string">"<span class="hljs-subst">#{code}</span> <span class="hljs-subst">#{cmp}</span> <span class="hljs-subst">#{@comparisonTarget}</span>"</span>
 | 
						||
    [@makeCode(<span class="hljs-keyword">if</span> o.level <= LEVEL_COND <span class="hljs-keyword">then</span> code <span class="hljs-keyword">else</span> <span class="hljs-string">"(<span class="hljs-subst">#{code}</span>)"</span>)]</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-268">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-268">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="parens">Parens</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-269">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-269">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>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.</p>
 | 
						||
<p>Parentheses are a good way to force any statement to become an expression.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Parens = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Parens</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@body)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'body'</span>]
 | 
						||
 | 
						||
  unwrap: <span class="hljs-function">-></span> @body
 | 
						||
 | 
						||
  shouldCache: <span class="hljs-function">-></span> @body.shouldCache()
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    expr = @body.unwrap()
 | 
						||
    <span class="hljs-keyword">if</span> expr <span class="hljs-keyword">instanceof</span> Value <span class="hljs-keyword">and</span> expr.isAtomic() <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @csxAttribute
 | 
						||
      expr.front = @front
 | 
						||
      <span class="hljs-keyword">return</span> expr.compileToFragments o
 | 
						||
    fragments = expr.compileToFragments o, LEVEL_PAREN
 | 
						||
    bare = o.level < LEVEL_OP <span class="hljs-keyword">and</span> (expr <span class="hljs-keyword">instanceof</span> Op <span class="hljs-keyword">or</span> expr.unwrap() <span class="hljs-keyword">instanceof</span> Call <span class="hljs-keyword">or</span>
 | 
						||
      (expr <span class="hljs-keyword">instanceof</span> For <span class="hljs-keyword">and</span> expr.returns)) <span class="hljs-keyword">and</span> (o.level < LEVEL_COND <span class="hljs-keyword">or</span>
 | 
						||
        fragments.length <= <span class="hljs-number">3</span>)
 | 
						||
    <span class="hljs-keyword">return</span> @wrapInBraces fragments <span class="hljs-keyword">if</span> @csxAttribute
 | 
						||
    <span class="hljs-keyword">if</span> bare <span class="hljs-keyword">then</span> fragments <span class="hljs-keyword">else</span> @wrapInParentheses fragments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-270">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-270">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="stringwithinterpolations">StringWithInterpolations</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>
 | 
						||
exports.StringWithInterpolations = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StringWithInterpolations</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@body)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'body'</span>]</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-271">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-271">¶</a>
 | 
						||
              </div>
 | 
						||
              <p><code>unwrap</code> returns <code>this</code> to stop ancestor nodes reaching in to grab @body,
 | 
						||
and using @body.compileNode. <code>StringWithInterpolations.compileNode</code> is
 | 
						||
<em>the</em> custom logic to output interpolated strings as code.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  unwrap: <span class="hljs-function">-></span> <span class="hljs-keyword">this</span>
 | 
						||
 | 
						||
  shouldCache: <span class="hljs-function">-></span> @body.shouldCache()
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    <span class="hljs-keyword">if</span> @csxAttribute
 | 
						||
      wrapped = <span class="hljs-keyword">new</span> Parens <span class="hljs-keyword">new</span> StringWithInterpolations @body
 | 
						||
      wrapped.csxAttribute = <span class="hljs-literal">yes</span>
 | 
						||
      <span class="hljs-keyword">return</span> wrapped.compileNode o</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-272">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-272">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Assumes that <code>expr</code> is <code>Value</code> » <code>StringLiteral</code> or <code>Op</code></p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    expr = @body.unwrap()
 | 
						||
 | 
						||
    elements = []
 | 
						||
    salvagedComments = []
 | 
						||
    expr.traverseChildren <span class="hljs-literal">no</span>, <span class="hljs-function"><span class="hljs-params">(node)</span> -></span>
 | 
						||
      <span class="hljs-keyword">if</span> node <span class="hljs-keyword">instanceof</span> StringLiteral
 | 
						||
        <span class="hljs-keyword">if</span> node.comments
 | 
						||
          salvagedComments.push node.comments...
 | 
						||
          <span class="hljs-keyword">delete</span> node.comments
 | 
						||
        elements.push node
 | 
						||
        <span class="hljs-keyword">return</span> <span class="hljs-literal">yes</span>
 | 
						||
      <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> node <span class="hljs-keyword">instanceof</span> Parens
 | 
						||
        <span class="hljs-keyword">if</span> salvagedComments.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span>
 | 
						||
          <span class="hljs-keyword">for</span> comment <span class="hljs-keyword">in</span> salvagedComments
 | 
						||
            comment.unshift = <span class="hljs-literal">yes</span>
 | 
						||
            comment.newLine = <span class="hljs-literal">yes</span>
 | 
						||
          attachCommentsToNode salvagedComments, node
 | 
						||
        elements.push node
 | 
						||
        <span class="hljs-keyword">return</span> <span class="hljs-literal">no</span>
 | 
						||
      <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> node.comments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-273">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-273">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>This node is getting discarded, but salvage its comments.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>        <span class="hljs-keyword">if</span> elements.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span> <span class="hljs-keyword">and</span> elements[elements.length - <span class="hljs-number">1</span>] <span class="hljs-keyword">not</span> <span class="hljs-keyword">instanceof</span> StringLiteral
 | 
						||
          <span class="hljs-keyword">for</span> comment <span class="hljs-keyword">in</span> node.comments
 | 
						||
            comment.unshift = <span class="hljs-literal">no</span>
 | 
						||
            comment.newLine = <span class="hljs-literal">yes</span>
 | 
						||
          attachCommentsToNode node.comments, elements[elements.length - <span class="hljs-number">1</span>]
 | 
						||
        <span class="hljs-keyword">else</span>
 | 
						||
          salvagedComments.push node.comments...
 | 
						||
        <span class="hljs-keyword">delete</span> node.comments
 | 
						||
      <span class="hljs-keyword">return</span> <span class="hljs-literal">yes</span>
 | 
						||
 | 
						||
    fragments = []
 | 
						||
    fragments.push @makeCode <span class="hljs-string">'`'</span> <span class="hljs-keyword">unless</span> @csx
 | 
						||
    <span class="hljs-keyword">for</span> element <span class="hljs-keyword">in</span> elements
 | 
						||
      <span class="hljs-keyword">if</span> element <span class="hljs-keyword">instanceof</span> StringLiteral
 | 
						||
        element.value = element.unquote <span class="hljs-literal">yes</span>, @csx
 | 
						||
        <span class="hljs-keyword">unless</span> @csx</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-274">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-274">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Backticks and <code>${</code> inside template literals must be escaped.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>          element.value = element.value.replace <span class="hljs-regexp">/(\\*)(`|\$\{)/g</span>, <span class="hljs-function"><span class="hljs-params">(match, backslashes, toBeEscaped)</span> -></span>
 | 
						||
            <span class="hljs-keyword">if</span> backslashes.length % <span class="hljs-number">2</span> <span class="hljs-keyword">is</span> <span class="hljs-number">0</span>
 | 
						||
              <span class="hljs-string">"<span class="hljs-subst">#{backslashes}</span>\\<span class="hljs-subst">#{toBeEscaped}</span>"</span>
 | 
						||
            <span class="hljs-keyword">else</span>
 | 
						||
              match
 | 
						||
        fragments.push element.compileToFragments(o)...
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        fragments.push @makeCode <span class="hljs-string">'$'</span> <span class="hljs-keyword">unless</span> @csx
 | 
						||
        code = element.compileToFragments(o, LEVEL_PAREN)
 | 
						||
        <span class="hljs-keyword">unless</span> @isNestedTag element
 | 
						||
          code = @wrapInBraces code</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-275">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-275">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Flag the <code>{</code> and <code>}</code> fragments as having been generated by this
 | 
						||
<code>StringWithInterpolations</code> node, so that <code>compileComments</code> knows
 | 
						||
to treat them as bounds. Don’t trust <code>fragment.type</code>, which can
 | 
						||
report minified variable names when this compiler is minified.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>          code[<span class="hljs-number">0</span>].isStringWithInterpolations = <span class="hljs-literal">yes</span>
 | 
						||
          code[code.length - <span class="hljs-number">1</span>].isStringWithInterpolations = <span class="hljs-literal">yes</span>
 | 
						||
        fragments.push code...
 | 
						||
    fragments.push @makeCode <span class="hljs-string">'`'</span> <span class="hljs-keyword">unless</span> @csx
 | 
						||
    fragments
 | 
						||
 | 
						||
  isNestedTag: <span class="hljs-function"><span class="hljs-params">(element)</span> -></span>
 | 
						||
    exprs = element.body?.expressions
 | 
						||
    call = exprs?[<span class="hljs-number">0</span>].unwrap()
 | 
						||
    @csx <span class="hljs-keyword">and</span> exprs <span class="hljs-keyword">and</span> exprs.length <span class="hljs-keyword">is</span> <span class="hljs-number">1</span> <span class="hljs-keyword">and</span> call <span class="hljs-keyword">instanceof</span> Call <span class="hljs-keyword">and</span> call.csx</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-276">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-276">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="for">For</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-277">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-277">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>CoffeeScript’s replacement for the <em>for</em> loop is our array and object
 | 
						||
comprehensions, that compile into <em>for</em> loops here. They also act as an
 | 
						||
expression, able to return the result of each filtered iteration.</p>
 | 
						||
<p>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.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.For = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">For</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">While</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(body, source)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
    {@source, @guard, @step, @name, @index} = source
 | 
						||
    @body    = Block.wrap [body]
 | 
						||
    @own     = source.own?
 | 
						||
    @object  = source.object?
 | 
						||
    @from    = source.<span class="hljs-keyword">from</span>?
 | 
						||
    @index.error <span class="hljs-string">'cannot use index with for-from'</span> <span class="hljs-keyword">if</span> @from <span class="hljs-keyword">and</span> @index
 | 
						||
    source.ownTag.error <span class="hljs-string">"cannot use own with for-<span class="hljs-subst">#{<span class="hljs-keyword">if</span> @from <span class="hljs-keyword">then</span> <span class="hljs-string">'from'</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'in'</span>}</span>"</span> <span class="hljs-keyword">if</span> @own <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @object
 | 
						||
    [@name, @index] = [@index, @name] <span class="hljs-keyword">if</span> @object
 | 
						||
    @index.error <span class="hljs-string">'index cannot be a pattern matching expression'</span> <span class="hljs-keyword">if</span> @index?.isArray?() <span class="hljs-keyword">or</span> @index?.isObject?()
 | 
						||
    @range   = @source <span class="hljs-keyword">instanceof</span> Value <span class="hljs-keyword">and</span> @source.base <span class="hljs-keyword">instanceof</span> Range <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @source.properties.length <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @from
 | 
						||
    @pattern = @name <span class="hljs-keyword">instanceof</span> Value
 | 
						||
    @index.error <span class="hljs-string">'indexes do not apply to range loops'</span> <span class="hljs-keyword">if</span> @range <span class="hljs-keyword">and</span> @index
 | 
						||
    @name.error <span class="hljs-string">'cannot pattern match over range loops'</span> <span class="hljs-keyword">if</span> @range <span class="hljs-keyword">and</span> @pattern
 | 
						||
    @returns = <span class="hljs-literal">no</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-278">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-278">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Move up any comments in the “<code>for</code> line”, i.e. the line of code with <code>for</code>,
 | 
						||
from any child nodes of that line up to the <code>for</code> node itself so that these
 | 
						||
comments get output, and get output above the <code>for</code> loop.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">for</span> attribute <span class="hljs-keyword">in</span> [<span class="hljs-string">'source'</span>, <span class="hljs-string">'guard'</span>, <span class="hljs-string">'step'</span>, <span class="hljs-string">'name'</span>, <span class="hljs-string">'index'</span>] <span class="hljs-keyword">when</span> @[attribute]
 | 
						||
      @[attribute].traverseChildren <span class="hljs-literal">yes</span>, <span class="hljs-function"><span class="hljs-params">(node)</span> =></span>
 | 
						||
        <span class="hljs-keyword">if</span> node.comments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-279">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-279">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>These comments are buried pretty deeply, so if they happen to be
 | 
						||
trailing comments the line they trail will be unrecognizable when
 | 
						||
we’re done compiling this <code>for</code> loop; so just shift them up to
 | 
						||
output above the <code>for</code> line.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>          comment.newLine = comment.unshift = <span class="hljs-literal">yes</span> <span class="hljs-keyword">for</span> comment <span class="hljs-keyword">in</span> node.comments
 | 
						||
          moveComments node, @[attribute]
 | 
						||
      moveComments @[attribute], @
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'body'</span>, <span class="hljs-string">'source'</span>, <span class="hljs-string">'guard'</span>, <span class="hljs-string">'step'</span>]</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-280">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-280">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>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
 | 
						||
some cannot.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    body        = Block.wrap [@body]
 | 
						||
    [..., last] = body.expressions
 | 
						||
    @returns    = <span class="hljs-literal">no</span> <span class="hljs-keyword">if</span> last?.jumps() <span class="hljs-keyword">instanceof</span> Return
 | 
						||
    source      = <span class="hljs-keyword">if</span> @range <span class="hljs-keyword">then</span> @source.base <span class="hljs-keyword">else</span> @source
 | 
						||
    scope       = o.scope
 | 
						||
    name        = @name  <span class="hljs-keyword">and</span> (@name.compile o, LEVEL_LIST) <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> @pattern
 | 
						||
    index       = @index <span class="hljs-keyword">and</span> (@index.compile o, LEVEL_LIST)
 | 
						||
    scope.find(name)  <span class="hljs-keyword">if</span> name <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @pattern
 | 
						||
    scope.find(index) <span class="hljs-keyword">if</span> index <span class="hljs-keyword">and</span> @index <span class="hljs-keyword">not</span> <span class="hljs-keyword">instanceof</span> Value
 | 
						||
    rvar        = scope.freeVariable <span class="hljs-string">'results'</span> <span class="hljs-keyword">if</span> @returns
 | 
						||
    <span class="hljs-keyword">if</span> @from
 | 
						||
      ivar = scope.freeVariable <span class="hljs-string">'x'</span>, single: <span class="hljs-literal">true</span> <span class="hljs-keyword">if</span> @pattern
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      ivar = (@object <span class="hljs-keyword">and</span> index) <span class="hljs-keyword">or</span> scope.freeVariable <span class="hljs-string">'i'</span>, single: <span class="hljs-literal">true</span>
 | 
						||
    kvar        = ((@range <span class="hljs-keyword">or</span> @from) <span class="hljs-keyword">and</span> name) <span class="hljs-keyword">or</span> index <span class="hljs-keyword">or</span> ivar
 | 
						||
    kvarAssign  = <span class="hljs-keyword">if</span> kvar <span class="hljs-keyword">isnt</span> ivar <span class="hljs-keyword">then</span> <span class="hljs-string">"<span class="hljs-subst">#{kvar}</span> = "</span> <span class="hljs-keyword">else</span> <span class="hljs-string">""</span>
 | 
						||
    <span class="hljs-keyword">if</span> @step <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @range
 | 
						||
      [step, stepVar] = @cacheToCodeFragments @step.cache o, LEVEL_LIST, shouldCacheOrIsAssignable
 | 
						||
      stepNum   = Number stepVar <span class="hljs-keyword">if</span> @step.isNumber()
 | 
						||
    name        = ivar <span class="hljs-keyword">if</span> @pattern
 | 
						||
    varPart     = <span class="hljs-string">''</span>
 | 
						||
    guardPart   = <span class="hljs-string">''</span>
 | 
						||
    defPart     = <span class="hljs-string">''</span>
 | 
						||
    idt1        = @tab + TAB
 | 
						||
    <span class="hljs-keyword">if</span> @range
 | 
						||
      forPartFragments = source.compileToFragments merge o,
 | 
						||
        {index: ivar, name, @step, shouldCache: shouldCacheOrIsAssignable}
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      svar    = @source.compile o, LEVEL_LIST
 | 
						||
      <span class="hljs-keyword">if</span> (name <span class="hljs-keyword">or</span> @own) <span class="hljs-keyword">and</span> @source.unwrap() <span class="hljs-keyword">not</span> <span class="hljs-keyword">instanceof</span> IdentifierLiteral
 | 
						||
        defPart    += <span class="hljs-string">"<span class="hljs-subst">#{@tab}</span><span class="hljs-subst">#{ref = scope.freeVariable <span class="hljs-string">'ref'</span>}</span> = <span class="hljs-subst">#{svar}</span>;\n"</span>
 | 
						||
        svar       = ref
 | 
						||
      <span class="hljs-keyword">if</span> name <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @pattern <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @from
 | 
						||
        namePart   = <span class="hljs-string">"<span class="hljs-subst">#{name}</span> = <span class="hljs-subst">#{svar}</span>[<span class="hljs-subst">#{kvar}</span>]"</span>
 | 
						||
      <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> @object <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @from
 | 
						||
        defPart += <span class="hljs-string">"<span class="hljs-subst">#{@tab}</span><span class="hljs-subst">#{step}</span>;\n"</span> <span class="hljs-keyword">if</span> step <span class="hljs-keyword">isnt</span> stepVar
 | 
						||
        down = stepNum < <span class="hljs-number">0</span>
 | 
						||
        lvar = scope.freeVariable <span class="hljs-string">'len'</span> <span class="hljs-keyword">unless</span> @step <span class="hljs-keyword">and</span> stepNum? <span class="hljs-keyword">and</span> down
 | 
						||
        declare = <span class="hljs-string">"<span class="hljs-subst">#{kvarAssign}</span><span class="hljs-subst">#{ivar}</span> = 0, <span class="hljs-subst">#{lvar}</span> = <span class="hljs-subst">#{svar}</span>.length"</span>
 | 
						||
        declareDown = <span class="hljs-string">"<span class="hljs-subst">#{kvarAssign}</span><span class="hljs-subst">#{ivar}</span> = <span class="hljs-subst">#{svar}</span>.length - 1"</span>
 | 
						||
        compare = <span class="hljs-string">"<span class="hljs-subst">#{ivar}</span> < <span class="hljs-subst">#{lvar}</span>"</span>
 | 
						||
        compareDown = <span class="hljs-string">"<span class="hljs-subst">#{ivar}</span> >= 0"</span>
 | 
						||
        <span class="hljs-keyword">if</span> @step
 | 
						||
          <span class="hljs-keyword">if</span> stepNum?
 | 
						||
            <span class="hljs-keyword">if</span> down
 | 
						||
              compare = compareDown
 | 
						||
              declare = declareDown
 | 
						||
          <span class="hljs-keyword">else</span>
 | 
						||
            compare = <span class="hljs-string">"<span class="hljs-subst">#{stepVar}</span> > 0 ? <span class="hljs-subst">#{compare}</span> : <span class="hljs-subst">#{compareDown}</span>"</span>
 | 
						||
            declare = <span class="hljs-string">"(<span class="hljs-subst">#{stepVar}</span> > 0 ? (<span class="hljs-subst">#{declare}</span>) : <span class="hljs-subst">#{declareDown}</span>)"</span>
 | 
						||
          increment = <span class="hljs-string">"<span class="hljs-subst">#{ivar}</span> += <span class="hljs-subst">#{stepVar}</span>"</span>
 | 
						||
        <span class="hljs-keyword">else</span>
 | 
						||
          increment = <span class="hljs-string">"<span class="hljs-subst">#{<span class="hljs-keyword">if</span> kvar <span class="hljs-keyword">isnt</span> ivar <span class="hljs-keyword">then</span> <span class="hljs-string">"++<span class="hljs-subst">#{ivar}</span>"</span> <span class="hljs-keyword">else</span> <span class="hljs-string">"<span class="hljs-subst">#{ivar}</span>++"</span>}</span>"</span>
 | 
						||
        forPartFragments = [@makeCode(<span class="hljs-string">"<span class="hljs-subst">#{declare}</span>; <span class="hljs-subst">#{compare}</span>; <span class="hljs-subst">#{kvarAssign}</span><span class="hljs-subst">#{increment}</span>"</span>)]
 | 
						||
    <span class="hljs-keyword">if</span> @returns
 | 
						||
      resultPart   = <span class="hljs-string">"<span class="hljs-subst">#{@tab}</span><span class="hljs-subst">#{rvar}</span> = [];\n"</span>
 | 
						||
      returnResult = <span class="hljs-string">"\n<span class="hljs-subst">#{@tab}</span>return <span class="hljs-subst">#{rvar}</span>;"</span>
 | 
						||
      body.makeReturn rvar
 | 
						||
    <span class="hljs-keyword">if</span> @guard
 | 
						||
      <span class="hljs-keyword">if</span> body.expressions.length > <span class="hljs-number">1</span>
 | 
						||
        body.expressions.unshift <span class="hljs-keyword">new</span> If (<span class="hljs-keyword">new</span> Parens @guard).invert(), <span class="hljs-keyword">new</span> StatementLiteral <span class="hljs-string">"continue"</span>
 | 
						||
      <span class="hljs-keyword">else</span>
 | 
						||
        body = Block.wrap [<span class="hljs-keyword">new</span> If @guard, body] <span class="hljs-keyword">if</span> @guard
 | 
						||
    <span class="hljs-keyword">if</span> @pattern
 | 
						||
      body.expressions.unshift <span class="hljs-keyword">new</span> Assign @name, <span class="hljs-keyword">if</span> @from <span class="hljs-keyword">then</span> <span class="hljs-keyword">new</span> IdentifierLiteral kvar <span class="hljs-keyword">else</span> <span class="hljs-keyword">new</span> Literal <span class="hljs-string">"<span class="hljs-subst">#{svar}</span>[<span class="hljs-subst">#{kvar}</span>]"</span>
 | 
						||
    defPartFragments = [].concat @makeCode(defPart), @pluckDirectCall(o, body)
 | 
						||
    varPart = <span class="hljs-string">"\n<span class="hljs-subst">#{idt1}</span><span class="hljs-subst">#{namePart}</span>;"</span> <span class="hljs-keyword">if</span> namePart
 | 
						||
    <span class="hljs-keyword">if</span> @object
 | 
						||
      forPartFragments = [@makeCode(<span class="hljs-string">"<span class="hljs-subst">#{kvar}</span> in <span class="hljs-subst">#{svar}</span>"</span>)]
 | 
						||
      guardPart = <span class="hljs-string">"\n<span class="hljs-subst">#{idt1}</span>if (!<span class="hljs-subst">#{utility <span class="hljs-string">'hasProp'</span>, o}</span>.call(<span class="hljs-subst">#{svar}</span>, <span class="hljs-subst">#{kvar}</span>)) continue;"</span> <span class="hljs-keyword">if</span> @own
 | 
						||
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> @from
 | 
						||
      forPartFragments = [@makeCode(<span class="hljs-string">"<span class="hljs-subst">#{kvar}</span> of <span class="hljs-subst">#{svar}</span>"</span>)]
 | 
						||
    bodyFragments = body.compileToFragments merge(o, indent: idt1), LEVEL_TOP
 | 
						||
    <span class="hljs-keyword">if</span> bodyFragments <span class="hljs-keyword">and</span> bodyFragments.length > <span class="hljs-number">0</span>
 | 
						||
      bodyFragments = [].concat @makeCode(<span class="hljs-string">'\n'</span>), bodyFragments, @makeCode(<span class="hljs-string">'\n'</span>)
 | 
						||
 | 
						||
    fragments = []
 | 
						||
    <span class="hljs-keyword">if</span> defPartFragments? <span class="hljs-keyword">and</span> fragmentsToText(defPartFragments) <span class="hljs-keyword">isnt</span> <span class="hljs-string">''</span>
 | 
						||
      fragments = fragments.concat defPartFragments
 | 
						||
    fragments.push @makeCode(resultPart) <span class="hljs-keyword">if</span> resultPart
 | 
						||
    fragments = fragments.concat @makeCode(@tab), @makeCode( <span class="hljs-string">'for ('</span>),
 | 
						||
      forPartFragments, @makeCode(<span class="hljs-string">") {<span class="hljs-subst">#{guardPart}</span><span class="hljs-subst">#{varPart}</span>"</span>), bodyFragments,
 | 
						||
      @makeCode(@tab), @makeCode(<span class="hljs-string">'}'</span>)
 | 
						||
    fragments.push @makeCode(returnResult) <span class="hljs-keyword">if</span> returnResult
 | 
						||
    fragments
 | 
						||
 | 
						||
  pluckDirectCall: <span class="hljs-function"><span class="hljs-params">(o, body)</span> -></span>
 | 
						||
    defs = []
 | 
						||
    <span class="hljs-keyword">for</span> expr, idx <span class="hljs-keyword">in</span> body.expressions
 | 
						||
      expr = expr.unwrapAll()
 | 
						||
      <span class="hljs-keyword">continue</span> <span class="hljs-keyword">unless</span> expr <span class="hljs-keyword">instanceof</span> Call
 | 
						||
      val = expr.variable?.unwrapAll()
 | 
						||
      <span class="hljs-keyword">continue</span> <span class="hljs-keyword">unless</span> (val <span class="hljs-keyword">instanceof</span> Code) <span class="hljs-keyword">or</span>
 | 
						||
                      (val <span class="hljs-keyword">instanceof</span> Value <span class="hljs-keyword">and</span>
 | 
						||
                      val.base?.unwrapAll() <span class="hljs-keyword">instanceof</span> Code <span class="hljs-keyword">and</span>
 | 
						||
                      val.properties.length <span class="hljs-keyword">is</span> <span class="hljs-number">1</span> <span class="hljs-keyword">and</span>
 | 
						||
                      val.properties[<span class="hljs-number">0</span>].name?.value <span class="hljs-keyword">in</span> [<span class="hljs-string">'call'</span>, <span class="hljs-string">'apply'</span>])
 | 
						||
      fn    = val.base?.unwrapAll() <span class="hljs-keyword">or</span> val
 | 
						||
      ref   = <span class="hljs-keyword">new</span> IdentifierLiteral o.scope.freeVariable <span class="hljs-string">'fn'</span>
 | 
						||
      base  = <span class="hljs-keyword">new</span> Value ref
 | 
						||
      <span class="hljs-keyword">if</span> val.base
 | 
						||
        [val.base, base] = [base, val]
 | 
						||
      body.expressions[idx] = <span class="hljs-keyword">new</span> Call base, expr.args
 | 
						||
      defs = defs.concat @makeCode(@tab), (<span class="hljs-keyword">new</span> Assign(ref, fn).compileToFragments(o, LEVEL_TOP)), @makeCode(<span class="hljs-string">';\n'</span>)
 | 
						||
    defs</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-281">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-281">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="switch">Switch</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-282">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-282">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>A JavaScript <em>switch</em> statement. Converts into a returnable expression on-demand.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.Switch = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Switch</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(@subject, @cases, @otherwise)</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'subject'</span>, <span class="hljs-string">'cases'</span>, <span class="hljs-string">'otherwise'</span>]
 | 
						||
 | 
						||
  isStatement: YES
 | 
						||
 | 
						||
  jumps: <span class="hljs-function"><span class="hljs-params">(o = {block: <span class="hljs-literal">yes</span>})</span> -></span>
 | 
						||
    <span class="hljs-keyword">for</span> [conds, block] <span class="hljs-keyword">in</span> @cases
 | 
						||
      <span class="hljs-keyword">return</span> jumpNode <span class="hljs-keyword">if</span> jumpNode = block.jumps o
 | 
						||
    @otherwise?.jumps o
 | 
						||
 | 
						||
  makeReturn: <span class="hljs-function"><span class="hljs-params">(res)</span> -></span>
 | 
						||
    pair[<span class="hljs-number">1</span>].makeReturn res <span class="hljs-keyword">for</span> pair <span class="hljs-keyword">in</span> @cases
 | 
						||
    @otherwise <span class="hljs-keyword">or</span>= <span class="hljs-keyword">new</span> Block [<span class="hljs-keyword">new</span> Literal <span class="hljs-string">'void 0'</span>] <span class="hljs-keyword">if</span> res
 | 
						||
    @otherwise?.makeReturn res
 | 
						||
    <span class="hljs-keyword">this</span>
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    idt1 = o.indent + TAB
 | 
						||
    idt2 = o.indent = idt1 + TAB
 | 
						||
    fragments = [].concat @makeCode(@tab + <span class="hljs-string">"switch ("</span>),
 | 
						||
      (<span class="hljs-keyword">if</span> @subject <span class="hljs-keyword">then</span> @subject.compileToFragments(o, LEVEL_PAREN) <span class="hljs-keyword">else</span> @makeCode <span class="hljs-string">"false"</span>),
 | 
						||
      @makeCode(<span class="hljs-string">") {\n"</span>)
 | 
						||
    <span class="hljs-keyword">for</span> [conditions, block], i <span class="hljs-keyword">in</span> @cases
 | 
						||
      <span class="hljs-keyword">for</span> cond <span class="hljs-keyword">in</span> flatten [conditions]
 | 
						||
        cond  = cond.invert() <span class="hljs-keyword">unless</span> @subject
 | 
						||
        fragments = fragments.concat @makeCode(idt1 + <span class="hljs-string">"case "</span>), cond.compileToFragments(o, LEVEL_PAREN), @makeCode(<span class="hljs-string">":\n"</span>)
 | 
						||
      fragments = fragments.concat body, @makeCode(<span class="hljs-string">'\n'</span>) <span class="hljs-keyword">if</span> (body = block.compileToFragments o, LEVEL_TOP).length > <span class="hljs-number">0</span>
 | 
						||
      <span class="hljs-keyword">break</span> <span class="hljs-keyword">if</span> i <span class="hljs-keyword">is</span> @cases.length - <span class="hljs-number">1</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> @otherwise
 | 
						||
      expr = @lastNode block.expressions
 | 
						||
      <span class="hljs-keyword">continue</span> <span class="hljs-keyword">if</span> expr <span class="hljs-keyword">instanceof</span> Return <span class="hljs-keyword">or</span> expr <span class="hljs-keyword">instanceof</span> Throw <span class="hljs-keyword">or</span> (expr <span class="hljs-keyword">instanceof</span> Literal <span class="hljs-keyword">and</span> expr.jumps() <span class="hljs-keyword">and</span> expr.value <span class="hljs-keyword">isnt</span> <span class="hljs-string">'debugger'</span>)
 | 
						||
      fragments.push cond.makeCode(idt2 + <span class="hljs-string">'break;\n'</span>)
 | 
						||
    <span class="hljs-keyword">if</span> @otherwise <span class="hljs-keyword">and</span> @otherwise.expressions.length
 | 
						||
      fragments.push @makeCode(idt1 + <span class="hljs-string">"default:\n"</span>), (@otherwise.compileToFragments o, LEVEL_TOP)..., @makeCode(<span class="hljs-string">"\n"</span>)
 | 
						||
    fragments.push @makeCode @tab + <span class="hljs-string">'}'</span>
 | 
						||
    fragments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-283">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-283">¶</a>
 | 
						||
              </div>
 | 
						||
              <h3 id="if">If</h3>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-284">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-284">¶</a>
 | 
						||
              </div>
 | 
						||
              <p><em>If/else</em> statements. Acts as an expression by pushing down requested returns
 | 
						||
to the last line of each clause.</p>
 | 
						||
<p>Single-expression <strong>Ifs</strong> are compiled into conditional operators if possible,
 | 
						||
because ternaries are already proper expressions, and don’t need conversion.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>exports.If = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">If</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
 | 
						||
  constructor: <span class="hljs-function"><span class="hljs-params">(condition, @body, options = {})</span> -></span>
 | 
						||
    <span class="hljs-keyword">super</span>()
 | 
						||
    @condition = <span class="hljs-keyword">if</span> options.type <span class="hljs-keyword">is</span> <span class="hljs-string">'unless'</span> <span class="hljs-keyword">then</span> condition.invert() <span class="hljs-keyword">else</span> condition
 | 
						||
    @elseBody  = <span class="hljs-literal">null</span>
 | 
						||
    @isChain   = <span class="hljs-literal">false</span>
 | 
						||
    {@soak}    = options
 | 
						||
    moveComments @condition, @ <span class="hljs-keyword">if</span> @condition.comments
 | 
						||
 | 
						||
  children: [<span class="hljs-string">'condition'</span>, <span class="hljs-string">'body'</span>, <span class="hljs-string">'elseBody'</span>]
 | 
						||
 | 
						||
  bodyNode:     <span class="hljs-function">-></span> @body?.unwrap()
 | 
						||
  elseBodyNode: <span class="hljs-function">-></span> @elseBody?.unwrap()</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-285">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-285">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Rewrite a chain of <strong>Ifs</strong> to add a default case as the final <em>else</em>.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  addElse: <span class="hljs-function"><span class="hljs-params">(elseBody)</span> -></span>
 | 
						||
    <span class="hljs-keyword">if</span> @isChain
 | 
						||
      @elseBodyNode().addElse elseBody
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      @isChain  = elseBody <span class="hljs-keyword">instanceof</span> If
 | 
						||
      @elseBody = @ensureBlock elseBody
 | 
						||
      @elseBody.updateLocationDataIfMissing elseBody.locationData
 | 
						||
    <span class="hljs-keyword">this</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-286">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-286">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>The <strong>If</strong> only compiles into a statement if either of its bodies needs
 | 
						||
to be a statement. Otherwise a conditional operator is safe.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  isStatement: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    o?.level <span class="hljs-keyword">is</span> LEVEL_TOP <span class="hljs-keyword">or</span>
 | 
						||
      @bodyNode().isStatement(o) <span class="hljs-keyword">or</span> @elseBodyNode()?.isStatement(o)
 | 
						||
 | 
						||
  jumps: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span> @body.jumps(o) <span class="hljs-keyword">or</span> @elseBody?.jumps(o)
 | 
						||
 | 
						||
  compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    <span class="hljs-keyword">if</span> @isStatement o <span class="hljs-keyword">then</span> @compileStatement o <span class="hljs-keyword">else</span> @compileExpression o
 | 
						||
 | 
						||
  makeReturn: <span class="hljs-function"><span class="hljs-params">(res)</span> -></span>
 | 
						||
    @elseBody  <span class="hljs-keyword">or</span>= <span class="hljs-keyword">new</span> Block [<span class="hljs-keyword">new</span> Literal <span class="hljs-string">'void 0'</span>] <span class="hljs-keyword">if</span> res
 | 
						||
    @body     <span class="hljs-keyword">and</span>= <span class="hljs-keyword">new</span> Block [@body.makeReturn res]
 | 
						||
    @elseBody <span class="hljs-keyword">and</span>= <span class="hljs-keyword">new</span> Block [@elseBody.makeReturn res]
 | 
						||
    <span class="hljs-keyword">this</span>
 | 
						||
 | 
						||
  ensureBlock: <span class="hljs-function"><span class="hljs-params">(node)</span> -></span>
 | 
						||
    <span class="hljs-keyword">if</span> node <span class="hljs-keyword">instanceof</span> Block <span class="hljs-keyword">then</span> node <span class="hljs-keyword">else</span> <span class="hljs-keyword">new</span> Block [node]</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-287">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-287">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Compile the <code>If</code> as a regular <em>if-else</em> statement. Flattened chains
 | 
						||
force inner <em>else</em> bodies into statement form.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileStatement: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    child    = del o, <span class="hljs-string">'chainChild'</span>
 | 
						||
    exeq     = del o, <span class="hljs-string">'isExistentialEquals'</span>
 | 
						||
 | 
						||
    <span class="hljs-keyword">if</span> exeq
 | 
						||
      <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> If(@condition.invert(), @elseBodyNode(), type: <span class="hljs-string">'if'</span>).compileToFragments o
 | 
						||
 | 
						||
    indent   = o.indent + TAB
 | 
						||
    cond     = @condition.compileToFragments o, LEVEL_PAREN
 | 
						||
    body     = @ensureBlock(@body).compileToFragments merge o, {indent}
 | 
						||
    ifPart   = [].concat @makeCode(<span class="hljs-string">"if ("</span>), cond, @makeCode(<span class="hljs-string">") {\n"</span>), body, @makeCode(<span class="hljs-string">"\n<span class="hljs-subst">#{@tab}</span>}"</span>)
 | 
						||
    ifPart.unshift @makeCode @tab <span class="hljs-keyword">unless</span> child
 | 
						||
    <span class="hljs-keyword">return</span> ifPart <span class="hljs-keyword">unless</span> @elseBody
 | 
						||
    answer = ifPart.concat @makeCode(<span class="hljs-string">' else '</span>)
 | 
						||
    <span class="hljs-keyword">if</span> @isChain
 | 
						||
      o.chainChild = <span class="hljs-literal">yes</span>
 | 
						||
      answer = answer.concat @elseBody.unwrap().compileToFragments o, LEVEL_TOP
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      answer = answer.concat @makeCode(<span class="hljs-string">"{\n"</span>), @elseBody.compileToFragments(merge(o, {indent}), LEVEL_TOP), @makeCode(<span class="hljs-string">"\n<span class="hljs-subst">#{@tab}</span>}"</span>)
 | 
						||
    answer</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-288">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-288">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Compile the <code>If</code> as a conditional operator.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  compileExpression: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
 | 
						||
    cond = @condition.compileToFragments o, LEVEL_COND
 | 
						||
    body = @bodyNode().compileToFragments o, LEVEL_LIST
 | 
						||
    alt  = <span class="hljs-keyword">if</span> @elseBodyNode() <span class="hljs-keyword">then</span> @elseBodyNode().compileToFragments(o, LEVEL_LIST) <span class="hljs-keyword">else</span> [@makeCode(<span class="hljs-string">'void 0'</span>)]
 | 
						||
    fragments = cond.concat @makeCode(<span class="hljs-string">" ? "</span>), body, @makeCode(<span class="hljs-string">" : "</span>), alt
 | 
						||
    <span class="hljs-keyword">if</span> o.level >= LEVEL_COND <span class="hljs-keyword">then</span> @wrapInParentheses fragments <span class="hljs-keyword">else</span> fragments
 | 
						||
 | 
						||
  unfoldSoak: <span class="hljs-function">-></span>
 | 
						||
    @soak <span class="hljs-keyword">and</span> <span class="hljs-keyword">this</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-289">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-289">¶</a>
 | 
						||
              </div>
 | 
						||
              <h2 id="constants">Constants</h2>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-290">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-290">¶</a>
 | 
						||
              </div>
 | 
						||
              
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>
 | 
						||
UTILITIES =
 | 
						||
  modulo: <span class="hljs-function">-></span> <span class="hljs-string">'function(a, b) { return (+a % (b = +b) + b) % b; }'</span>
 | 
						||
  objectWithoutKeys: <span class="hljs-function">-></span> <span class="hljs-string">"
 | 
						||
      function(o, ks) {
 | 
						||
        var res = {};
 | 
						||
        for (var k in o) ([].indexOf.call(ks, k) < 0 && {}.hasOwnProperty.call(o, k)) && (res[k] = o[k]);
 | 
						||
        return res;
 | 
						||
      }
 | 
						||
    "</span>
 | 
						||
  boundMethodCheck: <span class="hljs-function">-></span> <span class="hljs-string">"
 | 
						||
    function(instance, Constructor) {
 | 
						||
      if (!(instance instanceof Constructor)) {
 | 
						||
        throw new Error('Bound instance method accessed before binding');
 | 
						||
      }
 | 
						||
    }
 | 
						||
  "</span>
 | 
						||
  _extends: <span class="hljs-function">-></span> <span class="hljs-string">"
 | 
						||
    Object.assign || function (target) {
 | 
						||
      for (var i = 1; i < arguments.length; i++) {
 | 
						||
        var source = arguments[i];
 | 
						||
        for (var key in source) {
 | 
						||
          if (Object.prototype.hasOwnProperty.call(source, key)) {
 | 
						||
            target[key] = source[key];
 | 
						||
          }
 | 
						||
        }
 | 
						||
      }
 | 
						||
      return target;
 | 
						||
    }
 | 
						||
  "</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-291">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-291">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Shortcuts to speed up the lookup time for native functions.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>  hasProp: <span class="hljs-function">-></span> <span class="hljs-string">'{}.hasOwnProperty'</span>
 | 
						||
  indexOf: <span class="hljs-function">-></span> <span class="hljs-string">'[].indexOf'</span>
 | 
						||
  slice  : <span class="hljs-function">-></span> <span class="hljs-string">'[].slice'</span>
 | 
						||
  splice : <span class="hljs-function">-></span> <span class="hljs-string">'[].splice'</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-292">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-292">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Levels indicate a node’s position in the AST. Useful for knowing if
 | 
						||
parens are necessary or superfluous.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>LEVEL_TOP    = <span class="hljs-number">1</span>  <span class="hljs-comment"># ...;</span>
 | 
						||
LEVEL_PAREN  = <span class="hljs-number">2</span>  <span class="hljs-comment"># (...)</span>
 | 
						||
LEVEL_LIST   = <span class="hljs-number">3</span>  <span class="hljs-comment"># [...]</span>
 | 
						||
LEVEL_COND   = <span class="hljs-number">4</span>  <span class="hljs-comment"># ... ? x : y</span>
 | 
						||
LEVEL_OP     = <span class="hljs-number">5</span>  <span class="hljs-comment"># !...</span>
 | 
						||
LEVEL_ACCESS = <span class="hljs-number">6</span>  <span class="hljs-comment"># ...[0]</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-293">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-293">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Tabs are two spaces for pretty printing.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre>TAB = <span class="hljs-string">'  '</span>
 | 
						||
 | 
						||
SIMPLENUM = <span class="hljs-regexp">/^[+-]?\d+$/</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-294">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-294">¶</a>
 | 
						||
              </div>
 | 
						||
              <h2 id="helper-functions">Helper Functions</h2>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-295">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-295">¶</a>
 | 
						||
              </div>
 | 
						||
              
 | 
						||
            </div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-296">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-296">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Helper for ensuring that utility functions are assigned at the top level.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">utility</span> = <span class="hljs-params">(name, o)</span> -></span>
 | 
						||
  {root} = o.scope
 | 
						||
  <span class="hljs-keyword">if</span> name <span class="hljs-keyword">of</span> root.utilities
 | 
						||
    root.utilities[name]
 | 
						||
  <span class="hljs-keyword">else</span>
 | 
						||
    ref = root.freeVariable name
 | 
						||
    root.assign ref, UTILITIES[name] o
 | 
						||
    root.utilities[name] = ref
 | 
						||
<span class="hljs-function">
 | 
						||
<span class="hljs-title">multident</span> = <span class="hljs-params">(code, tab, includingFirstLine = <span class="hljs-literal">yes</span>)</span> -></span>
 | 
						||
  endsWithNewLine = code[code.length - <span class="hljs-number">1</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'\n'</span>
 | 
						||
  code = (<span class="hljs-keyword">if</span> includingFirstLine <span class="hljs-keyword">then</span> tab <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>) + code.replace <span class="hljs-regexp">/\n/g</span>, <span class="hljs-string">"$&<span class="hljs-subst">#{tab}</span>"</span>
 | 
						||
  code = code.replace <span class="hljs-regexp">/\s+$/</span>, <span class="hljs-string">''</span>
 | 
						||
  code = code + <span class="hljs-string">'\n'</span> <span class="hljs-keyword">if</span> endsWithNewLine
 | 
						||
  code</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-297">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-297">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Wherever in CoffeeScript 1 we might’ve inserted a <code>makeCode "#{@tab}"</code> to
 | 
						||
indent a line of code, now we must account for the possibility of comments
 | 
						||
preceding that line of code. If there are such comments, indent each line of
 | 
						||
such comments, and <em>then</em> indent the first following line of code.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">indentInitial</span> = <span class="hljs-params">(fragments, node)</span> -></span>
 | 
						||
  <span class="hljs-keyword">for</span> fragment, fragmentIndex <span class="hljs-keyword">in</span> fragments
 | 
						||
    <span class="hljs-keyword">if</span> fragment.isHereComment
 | 
						||
      fragment.code = multident fragment.code, node.tab
 | 
						||
    <span class="hljs-keyword">else</span>
 | 
						||
      fragments.splice fragmentIndex, <span class="hljs-number">0</span>, node.makeCode <span class="hljs-string">"<span class="hljs-subst">#{node.tab}</span>"</span>
 | 
						||
      <span class="hljs-keyword">break</span>
 | 
						||
  fragments
 | 
						||
<span class="hljs-function">
 | 
						||
<span class="hljs-title">hasLineComments</span> = <span class="hljs-params">(node)</span> -></span>
 | 
						||
  <span class="hljs-keyword">return</span> <span class="hljs-literal">no</span> <span class="hljs-keyword">unless</span> node.comments
 | 
						||
  <span class="hljs-keyword">for</span> comment <span class="hljs-keyword">in</span> node.comments
 | 
						||
    <span class="hljs-keyword">return</span> <span class="hljs-literal">yes</span> <span class="hljs-keyword">if</span> comment.here <span class="hljs-keyword">is</span> <span class="hljs-literal">no</span>
 | 
						||
  <span class="hljs-keyword">return</span> <span class="hljs-literal">no</span></pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-298">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-298">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Move the <code>comments</code> property from one object to another, deleting it from
 | 
						||
the first object.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">moveComments</span> = <span class="hljs-params">(<span class="hljs-keyword">from</span>, to)</span> -></span>
 | 
						||
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> <span class="hljs-keyword">from</span>?.comments
 | 
						||
  attachCommentsToNode <span class="hljs-keyword">from</span>.comments, to
 | 
						||
  <span class="hljs-keyword">delete</span> <span class="hljs-keyword">from</span>.comments</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-299">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-299">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Sometimes when compiling a node, we want to insert a fragment at the start
 | 
						||
of an array of fragments; but if the start has one or more comment fragments,
 | 
						||
we want to insert this fragment after those but before any non-comments.</p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">unshiftAfterComments</span> = <span class="hljs-params">(fragments, fragmentToInsert)</span> -></span>
 | 
						||
  inserted = <span class="hljs-literal">no</span>
 | 
						||
  <span class="hljs-keyword">for</span> fragment, fragmentIndex <span class="hljs-keyword">in</span> fragments <span class="hljs-keyword">when</span> <span class="hljs-keyword">not</span> fragment.isComment
 | 
						||
    fragments.splice fragmentIndex, <span class="hljs-number">0</span>, fragmentToInsert
 | 
						||
    inserted = <span class="hljs-literal">yes</span>
 | 
						||
    <span class="hljs-keyword">break</span>
 | 
						||
  fragments.push fragmentToInsert <span class="hljs-keyword">unless</span> inserted
 | 
						||
  fragments
 | 
						||
<span class="hljs-function">
 | 
						||
<span class="hljs-title">isLiteralArguments</span> = <span class="hljs-params">(node)</span> -></span>
 | 
						||
  node <span class="hljs-keyword">instanceof</span> IdentifierLiteral <span class="hljs-keyword">and</span> node.value <span class="hljs-keyword">is</span> <span class="hljs-string">'arguments'</span>
 | 
						||
<span class="hljs-function">
 | 
						||
<span class="hljs-title">isLiteralThis</span> = <span class="hljs-params">(node)</span> -></span>
 | 
						||
  node <span class="hljs-keyword">instanceof</span> ThisLiteral <span class="hljs-keyword">or</span> (node <span class="hljs-keyword">instanceof</span> Code <span class="hljs-keyword">and</span> node.bound)
 | 
						||
<span class="hljs-function">
 | 
						||
<span class="hljs-title">shouldCacheOrIsAssignable</span> = <span class="hljs-params">(node)</span> -></span> node.shouldCache() <span class="hljs-keyword">or</span> node.isAssignable?()</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
        
 | 
						||
        <li id="section-300">
 | 
						||
            <div class="annotation">
 | 
						||
              
 | 
						||
              <div class="pilwrap ">
 | 
						||
                <a class="pilcrow" href="#section-300">¶</a>
 | 
						||
              </div>
 | 
						||
              <p>Unfold a node’s child if soak, then tuck the node under created <code>If</code></p>
 | 
						||
 | 
						||
            </div>
 | 
						||
            
 | 
						||
            <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">unfoldSoak</span> = <span class="hljs-params">(o, parent, name)</span> -></span>
 | 
						||
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> ifn = parent[name].unfoldSoak o
 | 
						||
  parent[name] = ifn.body
 | 
						||
  ifn.body = <span class="hljs-keyword">new</span> Value parent
 | 
						||
  ifn</pre></div></div>
 | 
						||
            
 | 
						||
        </li>
 | 
						||
        
 | 
						||
    </ul>
 | 
						||
  </div>
 | 
						||
</body>
 | 
						||
</html>
 |