/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

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>scope.litcoffee</title>
  5. <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  6. <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
  7. <link rel="stylesheet" media="all" href="docco.css" />
  8. </head>
  9. <body>
  10. <div id="container">
  11. <div id="background"></div>
  12. <ul id="jump_to">
  13. <li>
  14. <a class="large" href="javascript:void(0);">Jump To &hellip;</a>
  15. <a class="small" href="javascript:void(0);">+</a>
  16. <div id="jump_wrapper">
  17. <div id="jump_page_wrapper">
  18. <div id="jump_page">
  19. <a class="source" href="browser.html">
  20. browser.coffee
  21. </a>
  22. <a class="source" href="cake.html">
  23. cake.coffee
  24. </a>
  25. <a class="source" href="coffee-script.html">
  26. coffee-script.coffee
  27. </a>
  28. <a class="source" href="command.html">
  29. command.coffee
  30. </a>
  31. <a class="source" href="grammar.html">
  32. grammar.coffee
  33. </a>
  34. <a class="source" href="helpers.html">
  35. helpers.coffee
  36. </a>
  37. <a class="source" href="index.html">
  38. index.coffee
  39. </a>
  40. <a class="source" href="lexer.html">
  41. lexer.coffee
  42. </a>
  43. <a class="source" href="nodes.html">
  44. nodes.coffee
  45. </a>
  46. <a class="source" href="optparse.html">
  47. optparse.coffee
  48. </a>
  49. <a class="source" href="register.html">
  50. register.coffee
  51. </a>
  52. <a class="source" href="repl.html">
  53. repl.coffee
  54. </a>
  55. <a class="source" href="rewriter.html">
  56. rewriter.coffee
  57. </a>
  58. <a class="source" href="scope.html">
  59. scope.litcoffee
  60. </a>
  61. <a class="source" href="sourcemap.html">
  62. sourcemap.litcoffee
  63. </a>
  64. </div>
  65. </div>
  66. </li>
  67. </ul>
  68. <ul class="sections">
  69. <li id="title">
  70. <div class="annotation">
  71. <h1>scope.litcoffee</h1>
  72. </div>
  73. </li>
  74. <li id="section-1">
  75. <div class="annotation">
  76. <div class="pilwrap ">
  77. <a class="pilcrow" href="#section-1">&#182;</a>
  78. </div>
  79. <p>The <strong>Scope</strong> class regulates lexical scoping within CoffeeScript. As you
  80. generate code, you create a tree of scopes in the same shape as the nested
  81. function bodies. Each scope knows about the variables declared within it,
  82. and has a reference to its parent enclosing scope. In this way, we know which
  83. variables are new and need to be declared with <code>var</code>, and which are shared
  84. with external scopes.</p>
  85. </div>
  86. <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>
  87. </li>
  88. <li id="section-2">
  89. <div class="annotation">
  90. <div class="pilwrap ">
  91. <a class="pilcrow" href="#section-2">&#182;</a>
  92. </div>
  93. <p>Initialize a scope with its parent, for lookups up the chain,
  94. as well as a reference to the <strong>Block</strong> node it belongs to, which is
  95. where it should declare its variables, a reference to the function that
  96. it belongs to, and a list of variables referenced in the source code
  97. and therefore should be avoided when generating variables.</p>
  98. </div>
  99. <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> -&gt;</span>
  100. <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>}]
  101. <span class="hljs-property">@positions</span> = {}
  102. <span class="hljs-property">@utilities</span> = {} <span class="hljs-keyword">unless</span> <span class="hljs-property">@parent</span></pre></div></div>
  103. </li>
  104. <li id="section-3">
  105. <div class="annotation">
  106. <div class="pilwrap ">
  107. <a class="pilcrow" href="#section-3">&#182;</a>
  108. </div>
  109. <p>The <code>@root</code> is the top-level <strong>Scope</strong> object for a given file.</p>
  110. </div>
  111. <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>
  112. </li>
  113. <li id="section-4">
  114. <div class="annotation">
  115. <div class="pilwrap ">
  116. <a class="pilcrow" href="#section-4">&#182;</a>
  117. </div>
  118. <p>Adds a new variable or overrides an existing one.</p>
  119. </div>
  120. <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> -&gt;</span>
  121. <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
  122. <span class="hljs-keyword">if</span> <span class="hljs-attribute">Object</span>::hasOwnProperty.call <span class="hljs-property">@positions</span>, name
  123. <span class="hljs-property">@variables</span>[<span class="hljs-property">@positions</span>[name]].type = type
  124. <span class="hljs-keyword">else</span>
  125. <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>
  126. </li>
  127. <li id="section-5">
  128. <div class="annotation">
  129. <div class="pilwrap ">
  130. <a class="pilcrow" href="#section-5">&#182;</a>
  131. </div>
  132. <p>When <code>super</code> is called, we need to find the name of the current method we’re
  133. in, so that we know how to invoke the same method of the parent class. This
  134. can get complicated if super is being called from an inner function.
  135. <code>namedMethod</code> will walk up the scope tree until it either finds the first
  136. function object that has a name filled in, or bottoms out.</p>
  137. </div>
  138. <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">namedMethod</span>:<span class="hljs-function"> -&gt;</span>
  139. <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>
  140. <span class="hljs-property">@parent</span>.namedMethod()</pre></div></div>
  141. </li>
  142. <li id="section-6">
  143. <div class="annotation">
  144. <div class="pilwrap ">
  145. <a class="pilcrow" href="#section-6">&#182;</a>
  146. </div>
  147. <p>Look up a variable name in lexical scope, and declare it if it does not
  148. already exist.</p>
  149. </div>
  150. <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">find</span>: <span class="hljs-function"><span class="hljs-params">(name)</span> -&gt;</span>
  151. <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
  152. <span class="hljs-property">@add</span> name, <span class="hljs-string">'var'</span>
  153. <span class="hljs-literal">no</span></pre></div></div>
  154. </li>
  155. <li id="section-7">
  156. <div class="annotation">
  157. <div class="pilwrap ">
  158. <a class="pilcrow" href="#section-7">&#182;</a>
  159. </div>
  160. <p>Reserve a variable name as originating from a function parameter for this
  161. scope. No <code>var</code> required for internal references.</p>
  162. </div>
  163. <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">parameter</span>: <span class="hljs-function"><span class="hljs-params">(name)</span> -&gt;</span>
  164. <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>
  165. <span class="hljs-property">@add</span> name, <span class="hljs-string">'param'</span></pre></div></div>
  166. </li>
  167. <li id="section-8">
  168. <div class="annotation">
  169. <div class="pilwrap ">
  170. <a class="pilcrow" href="#section-8">&#182;</a>
  171. </div>
  172. <p>Just check to see if a variable has already been declared, without reserving,
  173. walks up to the root scope.</p>
  174. </div>
  175. <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">check</span>: <span class="hljs-function"><span class="hljs-params">(name)</span> -&gt;</span>
  176. !!(<span class="hljs-property">@type</span>(name) <span class="hljs-keyword">or</span> <span class="hljs-property">@parent</span>?.check(name))</pre></div></div>
  177. </li>
  178. <li id="section-9">
  179. <div class="annotation">
  180. <div class="pilwrap ">
  181. <a class="pilcrow" href="#section-9">&#182;</a>
  182. </div>
  183. <p>Generate a temporary variable name at the given index.</p>
  184. </div>
  185. <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> -&gt;</span>
  186. <span class="hljs-keyword">if</span> single
  187. (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>
  188. <span class="hljs-keyword">else</span>
  189. name + (index <span class="hljs-keyword">or</span> <span class="hljs-string">''</span>)</pre></div></div>
  190. </li>
  191. <li id="section-10">
  192. <div class="annotation">
  193. <div class="pilwrap ">
  194. <a class="pilcrow" href="#section-10">&#182;</a>
  195. </div>
  196. <p>Gets the type of a variable.</p>
  197. </div>
  198. <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">type</span>: <span class="hljs-function"><span class="hljs-params">(name)</span> -&gt;</span>
  199. <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
  200. <span class="hljs-literal">null</span></pre></div></div>
  201. </li>
  202. <li id="section-11">
  203. <div class="annotation">
  204. <div class="pilwrap ">
  205. <a class="pilcrow" href="#section-11">&#182;</a>
  206. </div>
  207. <p>If we need to store an intermediate result, find an available name for a
  208. compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on…</p>
  209. </div>
  210. <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">freeVariable</span>: <span class="hljs-function"><span class="hljs-params">(name, options={})</span> -&gt;</span>
  211. index = <span class="hljs-number">0</span>
  212. <span class="hljs-keyword">loop</span>
  213. temp = <span class="hljs-property">@temporary</span> name, index, options.single
  214. <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
  215. index++
  216. <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>
  217. temp</pre></div></div>
  218. </li>
  219. <li id="section-12">
  220. <div class="annotation">
  221. <div class="pilwrap ">
  222. <a class="pilcrow" href="#section-12">&#182;</a>
  223. </div>
  224. <p>Ensure that an assignment is made at the top of this scope
  225. (or at the top-level scope, if requested).</p>
  226. </div>
  227. <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">assign</span>: <span class="hljs-function"><span class="hljs-params">(name, value)</span> -&gt;</span>
  228. <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>
  229. <span class="hljs-property">@hasAssignments</span> = <span class="hljs-literal">yes</span></pre></div></div>
  230. </li>
  231. <li id="section-13">
  232. <div class="annotation">
  233. <div class="pilwrap ">
  234. <a class="pilcrow" href="#section-13">&#182;</a>
  235. </div>
  236. <p>Does this scope have any declared variables?</p>
  237. </div>
  238. <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">hasDeclarations</span>:<span class="hljs-function"> -&gt;</span>
  239. !!<span class="hljs-property">@declaredVariables</span>().length</pre></div></div>
  240. </li>
  241. <li id="section-14">
  242. <div class="annotation">
  243. <div class="pilwrap ">
  244. <a class="pilcrow" href="#section-14">&#182;</a>
  245. </div>
  246. <p>Return the list of variables first declared in this scope.</p>
  247. </div>
  248. <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">declaredVariables</span>:<span class="hljs-function"> -&gt;</span>
  249. (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>
  250. </li>
  251. <li id="section-15">
  252. <div class="annotation">
  253. <div class="pilwrap ">
  254. <a class="pilcrow" href="#section-15">&#182;</a>
  255. </div>
  256. <p>Return the list of assignments that are supposed to be made at the top
  257. of this scope.</p>
  258. </div>
  259. <div class="content"><div class='highlight'><pre> <span class="hljs-attribute">assignedVariables</span>:<span class="hljs-function"> -&gt;</span>
  260. <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>
  261. </li>
  262. </ul>
  263. </div>
  264. </body>
  265. </html>