/documentation/docs/scope.html
http://github.com/jashkenas/coffee-script · HTML · 392 lines · 265 code · 127 blank · 0 comment · 0 complexity · db2b0b333c46bf2db8b59d105095c30f MD5 · raw file
- <!DOCTYPE html>
- <html>
- <head>
- <title>scope.litcoffee</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="coffee-script.html">
- coffee-script.coffee
- </a>
-
-
- <a class="source" href="command.html">
- command.coffee
- </a>
-
-
- <a class="source" href="grammar.html">
- grammar.coffee
- </a>
-
-
- <a class="source" href="helpers.html">
- helpers.coffee
- </a>
-
-
- <a class="source" href="index.html">
- index.coffee
- </a>
-
-
- <a class="source" href="lexer.html">
- lexer.coffee
- </a>
-
-
- <a class="source" href="nodes.html">
- nodes.coffee
- </a>
-
-
- <a class="source" href="optparse.html">
- optparse.coffee
- </a>
-
-
- <a class="source" href="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>scope.litcoffee</h1>
- </div>
- </li>
-
-
-
- <li id="section-1">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-1">¶</a>
- </div>
- <p>The <strong>Scope</strong> class regulates lexical scoping within CoffeeScript. As you
- generate code, you create a tree of scopes in the same shape as the nested
- function bodies. Each scope knows about the variables declared within it,
- and has a reference to its parent enclosing scope. In this way, we know which
- variables are new and need to be declared with <code>var</code>, and which are shared
- with external scopes.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.Scope = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Scope</span></span></pre></div></div>
-
- </li>
-
-
- <li id="section-2">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-2">¶</a>
- </div>
- <p>Initialize a scope with its parent, for lookups up the chain,
- as well as a reference to the <strong>Block</strong> node it belongs to, which is
- where it should declare its variables, a reference to the function that
- it belongs to, and a list of variables referenced in the source code
- and therefore should be avoided when generating variables.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">constructor</span>: <span class="hljs-function"><span class="hljs-params">(<span class="hljs-property">@parent</span>, <span class="hljs-property">@expressions</span>, <span class="hljs-property">@method</span>, <span class="hljs-property">@referencedVars</span>)</span> -></span>
- <span class="hljs-property">@variables</span> = [{<span class="hljs-attribute">name</span>: <span class="hljs-string">'arguments'</span>, <span class="hljs-attribute">type</span>: <span class="hljs-string">'arguments'</span>}]
- <span class="hljs-property">@positions</span> = {}
- <span class="hljs-property">@utilities</span> = {} <span class="hljs-keyword">unless</span> <span class="hljs-property">@parent</span></pre></div></div>
-
- </li>
-
-
- <li id="section-3">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-3">¶</a>
- </div>
- <p>The <code>@root</code> is the top-level <strong>Scope</strong> object for a given file.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre> <span class="hljs-property">@root</span> = <span class="hljs-property">@parent</span>?.root ? <span class="hljs-keyword">this</span></pre></div></div>
-
- </li>
-
-
- <li id="section-4">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-4">¶</a>
- </div>
- <p>Adds a new variable or overrides an existing one.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">add</span>: <span class="hljs-function"><span class="hljs-params">(name, type, immediate)</span> -></span>
- <span class="hljs-keyword">return</span> <span class="hljs-property">@parent</span>.add name, type, immediate <span class="hljs-keyword">if</span> <span class="hljs-property">@shared</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> immediate
- <span class="hljs-keyword">if</span> <span class="hljs-attribute">Object</span>::hasOwnProperty.call <span class="hljs-property">@positions</span>, name
- <span class="hljs-property">@variables</span>[<span class="hljs-property">@positions</span>[name]].type = type
- <span class="hljs-keyword">else</span>
- <span class="hljs-property">@positions</span>[name] = <span class="hljs-property">@variables</span>.push({name, type}) - <span class="hljs-number">1</span></pre></div></div>
-
- </li>
-
-
- <li id="section-5">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-5">¶</a>
- </div>
- <p>When <code>super</code> is called, we need to find the name of the current method weâre
- in, so that we know how to invoke the same method of the parent class. This
- can get complicated if super is being called from an inner function.
- <code>namedMethod</code> will walk up the scope tree until it either finds the first
- function object that has a name filled in, or bottoms out.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">namedMethod</span>:<span class="hljs-function"> -></span>
- <span class="hljs-keyword">return</span> <span class="hljs-property">@method</span> <span class="hljs-keyword">if</span> <span class="hljs-property">@method</span>?.name <span class="hljs-keyword">or</span> !<span class="hljs-property">@parent</span>
- <span class="hljs-property">@parent</span>.namedMethod()</pre></div></div>
-
- </li>
-
-
- <li id="section-6">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-6">¶</a>
- </div>
- <p>Look up a variable name in lexical scope, and declare it if it does not
- already exist.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">find</span>: <span class="hljs-function"><span class="hljs-params">(name)</span> -></span>
- <span class="hljs-keyword">return</span> <span class="hljs-literal">yes</span> <span class="hljs-keyword">if</span> <span class="hljs-property">@check</span> name
- <span class="hljs-property">@add</span> name, <span class="hljs-string">'var'</span>
- <span class="hljs-literal">no</span></pre></div></div>
-
- </li>
-
-
- <li id="section-7">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-7">¶</a>
- </div>
- <p>Reserve a variable name as originating from a function parameter for this
- scope. No <code>var</code> required for internal references.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">parameter</span>: <span class="hljs-function"><span class="hljs-params">(name)</span> -></span>
- <span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> <span class="hljs-property">@shared</span> <span class="hljs-keyword">and</span> <span class="hljs-property">@parent</span>.check name, <span class="hljs-literal">yes</span>
- <span class="hljs-property">@add</span> name, <span class="hljs-string">'param'</span></pre></div></div>
-
- </li>
-
-
- <li id="section-8">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-8">¶</a>
- </div>
- <p>Just check to see if a variable has already been declared, without reserving,
- walks up to the root scope.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">check</span>: <span class="hljs-function"><span class="hljs-params">(name)</span> -></span>
- !!(<span class="hljs-property">@type</span>(name) <span class="hljs-keyword">or</span> <span class="hljs-property">@parent</span>?.check(name))</pre></div></div>
-
- </li>
-
-
- <li id="section-9">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-9">¶</a>
- </div>
- <p>Generate a temporary variable name at the given index.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">temporary</span>: <span class="hljs-function"><span class="hljs-params">(name, index, single=<span class="hljs-literal">false</span>)</span> -></span>
- <span class="hljs-keyword">if</span> single
- (index + parseInt name, <span class="hljs-number">36</span>).toString(<span class="hljs-number">36</span>).replace <span class="hljs-regexp">/\d/g</span>, <span class="hljs-string">'a'</span>
- <span class="hljs-keyword">else</span>
- name + (index <span class="hljs-keyword">or</span> <span class="hljs-string">''</span>)</pre></div></div>
-
- </li>
-
-
- <li id="section-10">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-10">¶</a>
- </div>
- <p>Gets the type of a variable.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">type</span>: <span class="hljs-function"><span class="hljs-params">(name)</span> -></span>
- <span class="hljs-keyword">return</span> v.type <span class="hljs-keyword">for</span> v <span class="hljs-keyword">in</span> <span class="hljs-property">@variables</span> <span class="hljs-keyword">when</span> v.name <span class="hljs-keyword">is</span> name
- <span class="hljs-literal">null</span></pre></div></div>
-
- </li>
-
-
- <li id="section-11">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-11">¶</a>
- </div>
- <p>If we need to store an intermediate result, find an available name for a
- compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so onâŚ</p>
- </div>
-
- <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">freeVariable</span>: <span class="hljs-function"><span class="hljs-params">(name, options={})</span> -></span>
- index = <span class="hljs-number">0</span>
- <span class="hljs-keyword">loop</span>
- temp = <span class="hljs-property">@temporary</span> name, index, options.single
- <span class="hljs-keyword">break</span> <span class="hljs-keyword">unless</span> <span class="hljs-property">@check</span>(temp) <span class="hljs-keyword">or</span> temp <span class="hljs-keyword">in</span> <span class="hljs-property">@root</span>.referencedVars
- index++
- <span class="hljs-property">@add</span> temp, <span class="hljs-string">'var'</span>, <span class="hljs-literal">yes</span> <span class="hljs-keyword">if</span> options.reserve ? <span class="hljs-literal">true</span>
- temp</pre></div></div>
-
- </li>
-
-
- <li id="section-12">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-12">¶</a>
- </div>
- <p>Ensure that an assignment is made at the top of this scope
- (or at the top-level scope, if requested).</p>
- </div>
-
- <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">assign</span>: <span class="hljs-function"><span class="hljs-params">(name, value)</span> -></span>
- <span class="hljs-property">@add</span> name, {value, <span class="hljs-attribute">assigned</span>: <span class="hljs-literal">yes</span>}, <span class="hljs-literal">yes</span>
- <span class="hljs-property">@hasAssignments</span> = <span class="hljs-literal">yes</span></pre></div></div>
-
- </li>
-
-
- <li id="section-13">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-13">¶</a>
- </div>
- <p>Does this scope have any declared variables?</p>
- </div>
-
- <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">hasDeclarations</span>:<span class="hljs-function"> -></span>
- !!<span class="hljs-property">@declaredVariables</span>().length</pre></div></div>
-
- </li>
-
-
- <li id="section-14">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-14">¶</a>
- </div>
- <p>Return the list of variables first declared in this scope.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">declaredVariables</span>:<span class="hljs-function"> -></span>
- (v.name <span class="hljs-keyword">for</span> v <span class="hljs-keyword">in</span> <span class="hljs-property">@variables</span> <span class="hljs-keyword">when</span> v.type <span class="hljs-keyword">is</span> <span class="hljs-string">'var'</span>).sort()</pre></div></div>
-
- </li>
-
-
- <li id="section-15">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-15">¶</a>
- </div>
- <p>Return the list of assignments that are supposed to be made at the top
- of this scope.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">assignedVariables</span>:<span class="hljs-function"> -></span>
- <span class="hljs-string">"<span class="hljs-subst">#{v.name}</span> = <span class="hljs-subst">#{v.type.value}</span>"</span> <span class="hljs-keyword">for</span> v <span class="hljs-keyword">in</span> <span class="hljs-property">@variables</span> <span class="hljs-keyword">when</span> v.type.assigned</pre></div></div>
-
- </li>
-
- </ul>
- </div>
- </body>
- </html>