mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-01-14 09:17:55 -05:00
4221 lines
365 KiB
HTML
4221 lines
365 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">
|
|
|
|
|
|
<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="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.coffee
|
|
</a>
|
|
|
|
</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><span class="nb">Error</span><span class="p">.</span><span class="nv">stackTraceLimit = </span><span class="kc">Infinity</span>
|
|
|
|
<span class="p">{</span><span class="nx">Scope</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">'./scope'</span>
|
|
<span class="p">{</span><span class="nx">RESERVED</span><span class="p">,</span> <span class="nx">STRICT_PROSCRIBED</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">'./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><span class="p">{</span><span class="nx">compact</span><span class="p">,</span> <span class="nx">flatten</span><span class="p">,</span> <span class="nx">extend</span><span class="p">,</span> <span class="nx">merge</span><span class="p">,</span> <span class="nx">del</span><span class="p">,</span> <span class="nx">starts</span><span class="p">,</span> <span class="nx">ends</span><span class="p">,</span> <span class="nx">last</span><span class="p">,</span> <span class="nx">some</span><span class="p">,</span>
|
|
<span class="nx">addLocationDataFn</span><span class="p">,</span> <span class="nx">locationDataToString</span><span class="p">,</span> <span class="nx">throwSyntaxError</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">'./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><span class="nv">exports.extend = </span><span class="nx">extend</span>
|
|
<span class="nv">exports.addLocationDataFn = </span><span class="nx">addLocationDataFn</span></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="nv">YES = </span><span class="nf">-></span> <span class="kc">yes</span>
|
|
<span class="nv">NO = </span><span class="nf">-></span> <span class="kc">no</span>
|
|
<span class="nv">THIS = </span><span class="nf">-></span> <span class="k">this</span>
|
|
<span class="nv">NEGATE = </span><span class="nf">-></span> <span class="vi">@negated = </span><span class="o">not</span> <span class="nx">@negated</span><span class="p">;</span> <span class="k">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>CodeFragment</h3>
|
|
<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><span class="nv">exports.CodeFragment = </span><span class="k">class</span> <span class="nx">CodeFragment</span>
|
|
<span class="nv">constructor: </span><span class="nf">(parent, code) -></span>
|
|
<span class="vi">@code = </span><span class="s">"</span><span class="si">#{</span><span class="nx">code</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="vi">@locationData = </span><span class="nx">parent</span><span class="o">?</span><span class="p">.</span><span class="nx">locationData</span>
|
|
<span class="vi">@type = </span><span class="nx">parent</span><span class="o">?</span><span class="p">.</span><span class="nx">constructor</span><span class="o">?</span><span class="p">.</span><span class="nx">name</span> <span class="o">or</span> <span class="s">'unknown'</span>
|
|
|
|
<span class="nv">toString: </span><span class="p">()</span> <span class="nf">-></span>
|
|
<span class="s">"</span><span class="si">#{</span><span class="nx">@code</span><span class="si">}#{</span><span class="p">[</span><span class="k">if</span> <span class="nx">@locationData</span> <span class="k">then</span> <span class="s">": "</span> <span class="o">+</span> <span class="nx">locationDataToString</span><span class="p">(</span><span class="nx">@locationData</span><span class="p">)]</span><span class="si">}</span><span class="s">"</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-6">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-6">¶</a>
|
|
</div>
|
|
|
|
<p>Convert an array of CodeFragments into a string.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre><span class="nv">fragmentsToText = </span><span class="nf">(fragments) -></span>
|
|
<span class="p">(</span><span class="nx">fragment</span><span class="p">.</span><span class="nx">code</span> <span class="k">for</span> <span class="nx">fragment</span> <span class="k">in</span> <span class="nx">fragments</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s">''</span><span class="p">)</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-7">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-7">¶</a>
|
|
</div>
|
|
|
|
<h3>Base</h3>
|
|
<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><span class="nv">exports.Base = </span><span class="k">class</span> <span class="nx">Base</span>
|
|
|
|
<span class="nv">compile: </span><span class="nf">(o, lvl) -></span>
|
|
<span class="nx">fragmentsToText</span> <span class="nx">@compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">lvl</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-8">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-8">¶</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> <span class="nv">compileToFragments: </span><span class="nf">(o, lvl) -></span>
|
|
<span class="nv">o = </span><span class="nx">extend</span> <span class="p">{},</span> <span class="nx">o</span>
|
|
<span class="nv">o.level = </span><span class="nx">lvl</span> <span class="k">if</span> <span class="nx">lvl</span>
|
|
<span class="nv">node = </span><span class="nx">@unfoldSoak</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">or</span> <span class="k">this</span>
|
|
<span class="nv">node.tab = </span><span class="nx">o</span><span class="p">.</span><span class="nx">indent</span>
|
|
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">is</span> <span class="nx">LEVEL_TOP</span> <span class="o">or</span> <span class="o">not</span> <span class="nx">node</span><span class="p">.</span><span class="nx">isStatement</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">compileNode</span> <span class="nx">o</span>
|
|
<span class="k">else</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">compileClosure</span> <span class="nx">o</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-9">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-9">¶</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> <span class="nv">compileClosure: </span><span class="nf">(o) -></span>
|
|
<span class="k">if</span> <span class="nv">jumpNode = </span><span class="nx">@jumps</span><span class="p">()</span>
|
|
<span class="nx">jumpNode</span><span class="p">.</span><span class="nx">error</span> <span class="s">'cannot use a pure statement in an expression'</span>
|
|
<span class="nv">o.sharedScope = </span><span class="kc">yes</span>
|
|
<span class="nx">Closure</span><span class="p">.</span><span class="nx">wrap</span><span class="p">(</span><span class="k">this</span><span class="p">).</span><span class="nx">compileNode</span> <span class="nx">o</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-10">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-10">¶</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> <span class="nv">cache: </span><span class="nf">(o, level, reused) -></span>
|
|
<span class="k">unless</span> <span class="nx">@isComplex</span><span class="p">()</span>
|
|
<span class="nv">ref = </span><span class="k">if</span> <span class="nx">level</span> <span class="k">then</span> <span class="nx">@compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">level</span> <span class="k">else</span> <span class="k">this</span>
|
|
<span class="p">[</span><span class="nx">ref</span><span class="p">,</span> <span class="nx">ref</span><span class="p">]</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">ref = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">reused</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s">'ref'</span>
|
|
<span class="nv">sub = </span><span class="k">new</span> <span class="nx">Assign</span> <span class="nx">ref</span><span class="p">,</span> <span class="k">this</span>
|
|
<span class="k">if</span> <span class="nx">level</span> <span class="k">then</span> <span class="p">[</span><span class="nx">sub</span><span class="p">.</span><span class="nx">compileToFragments</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">level</span><span class="p">),</span> <span class="p">[</span><span class="nx">@makeCode</span><span class="p">(</span><span class="nx">ref</span><span class="p">.</span><span class="nx">value</span><span class="p">)]]</span> <span class="k">else</span> <span class="p">[</span><span class="nx">sub</span><span class="p">,</span> <span class="nx">ref</span><span class="p">]</span>
|
|
|
|
<span class="nv">cacheToCodeFragments: </span><span class="nf">(cacheValues) -></span>
|
|
<span class="p">[</span><span class="nx">fragmentsToText</span><span class="p">(</span><span class="nx">cacheValues</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span> <span class="nx">fragmentsToText</span><span class="p">(</span><span class="nx">cacheValues</span><span class="p">[</span><span class="mi">1</span><span class="p">])]</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-11">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-11">¶</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> <span class="nv">makeReturn: </span><span class="nf">(res) -></span>
|
|
<span class="nv">me = </span><span class="nx">@unwrapAll</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="nx">res</span>
|
|
<span class="k">new</span> <span class="nx">Call</span> <span class="k">new</span> <span class="nx">Literal</span><span class="p">(</span><span class="s">"</span><span class="si">#{</span><span class="nx">res</span><span class="si">}</span><span class="s">.push"</span><span class="p">),</span> <span class="p">[</span><span class="nx">me</span><span class="p">]</span>
|
|
<span class="k">else</span>
|
|
<span class="k">new</span> <span class="nx">Return</span> <span class="nx">me</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-12">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-12">¶</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> <span class="nv">contains: </span><span class="nf">(pred) -></span>
|
|
<span class="nv">node = </span><span class="kc">undefined</span>
|
|
<span class="nx">@traverseChildren</span> <span class="kc">no</span><span class="p">,</span> <span class="nf">(n) -></span>
|
|
<span class="k">if</span> <span class="nx">pred</span> <span class="nx">n</span>
|
|
<span class="nv">node = </span><span class="nx">n</span>
|
|
<span class="k">return</span> <span class="kc">no</span>
|
|
<span class="nx">node</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-13">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-13">¶</a>
|
|
</div>
|
|
|
|
<p>Pull out the last non-comment node of a node list.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">lastNonComment: </span><span class="nf">(list) -></span>
|
|
<span class="nv">i = </span><span class="nx">list</span><span class="p">.</span><span class="nx">length</span>
|
|
<span class="k">return</span> <span class="nx">list</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="k">while</span> <span class="nx">i</span><span class="o">--</span> <span class="k">when</span> <span class="nx">list</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">not</span> <span class="k">instanceof</span> <span class="nx">Comment</span>
|
|
<span class="kc">null</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-14">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-14">¶</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> <span class="nv">toString: </span><span class="nf">(idt = '', name = @constructor.name) -></span>
|
|
<span class="nv">tree = </span><span class="s">'\n'</span> <span class="o">+</span> <span class="nx">idt</span> <span class="o">+</span> <span class="nx">name</span>
|
|
<span class="nx">tree</span> <span class="o">+=</span> <span class="s">'?'</span> <span class="k">if</span> <span class="nx">@soak</span>
|
|
<span class="nx">@eachChild</span> <span class="nf">(node) -></span> <span class="nx">tree</span> <span class="o">+=</span> <span class="nx">node</span><span class="p">.</span><span class="nx">toString</span> <span class="nx">idt</span> <span class="o">+</span> <span class="nx">TAB</span>
|
|
<span class="nx">tree</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-15">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-15">¶</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> <span class="nv">eachChild: </span><span class="nf">(func) -></span>
|
|
<span class="k">return</span> <span class="k">this</span> <span class="k">unless</span> <span class="nx">@children</span>
|
|
<span class="k">for</span> <span class="nx">attr</span> <span class="k">in</span> <span class="nx">@children</span> <span class="k">when</span> <span class="nx">@</span><span class="p">[</span><span class="nx">attr</span><span class="p">]</span>
|
|
<span class="k">for</span> <span class="nx">child</span> <span class="k">in</span> <span class="nx">flatten</span> <span class="p">[</span><span class="nx">@</span><span class="p">[</span><span class="nx">attr</span><span class="p">]]</span>
|
|
<span class="k">return</span> <span class="k">this</span> <span class="k">if</span> <span class="nx">func</span><span class="p">(</span><span class="nx">child</span><span class="p">)</span> <span class="o">is</span> <span class="kc">false</span>
|
|
<span class="k">this</span>
|
|
|
|
<span class="nv">traverseChildren: </span><span class="nf">(crossScope, func) -></span>
|
|
<span class="nx">@eachChild</span> <span class="nf">(child) -></span>
|
|
<span class="k">return</span> <span class="kc">false</span> <span class="k">if</span> <span class="nx">func</span><span class="p">(</span><span class="nx">child</span><span class="p">)</span> <span class="o">is</span> <span class="kc">false</span>
|
|
<span class="nx">child</span><span class="p">.</span><span class="nx">traverseChildren</span> <span class="nx">crossScope</span><span class="p">,</span> <span class="nx">func</span>
|
|
|
|
<span class="nv">invert: </span><span class="nf">-></span>
|
|
<span class="k">new</span> <span class="nx">Op</span> <span class="s">'!'</span><span class="p">,</span> <span class="k">this</span>
|
|
|
|
<span class="nv">unwrapAll: </span><span class="nf">-></span>
|
|
<span class="nv">node = </span><span class="k">this</span>
|
|
<span class="k">continue</span> <span class="k">until</span> <span class="nx">node</span> <span class="o">is</span> <span class="nv">node = </span><span class="nx">node</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span>
|
|
<span class="nx">node</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-16">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-16">¶</a>
|
|
</div>
|
|
|
|
<p>Default implementations of the common node properties and methods. Nodes
|
|
will override these with custom logic, if needed.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">children: </span><span class="p">[]</span>
|
|
|
|
<span class="nv">isStatement : </span><span class="nx">NO</span>
|
|
<span class="nv">jumps : </span><span class="nx">NO</span>
|
|
<span class="nv">isComplex : </span><span class="nx">YES</span>
|
|
<span class="nv">isChainable : </span><span class="nx">NO</span>
|
|
<span class="nv">isAssignable : </span><span class="nx">NO</span>
|
|
|
|
<span class="nv">unwrap : </span><span class="nx">THIS</span>
|
|
<span class="nv">unfoldSoak : </span><span class="nx">NO</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-17">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-17">¶</a>
|
|
</div>
|
|
|
|
<p>Is this node used to assign a certain variable?
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">assigns: </span><span class="nx">NO</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-18">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-18">¶</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> <span class="nv">updateLocationDataIfMissing: </span><span class="nf">(locationData) -></span>
|
|
<span class="nx">@locationData</span> <span class="o">or=</span> <span class="nx">locationData</span>
|
|
|
|
<span class="nx">@eachChild</span> <span class="nf">(child) -></span>
|
|
<span class="nx">child</span><span class="p">.</span><span class="nx">updateLocationDataIfMissing</span> <span class="nx">locationData</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-19">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-19">¶</a>
|
|
</div>
|
|
|
|
<p>Throw a SyntaxError associated with this node's location.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">error: </span><span class="nf">(message) -></span>
|
|
<span class="nx">throwSyntaxError</span> <span class="nx">message</span><span class="p">,</span> <span class="nx">@locationData</span>
|
|
|
|
<span class="nv">makeCode: </span><span class="nf">(code) -></span>
|
|
<span class="k">new</span> <span class="nx">CodeFragment</span> <span class="k">this</span><span class="p">,</span> <span class="nx">code</span>
|
|
|
|
<span class="nv">wrapInBraces: </span><span class="nf">(fragments) -></span>
|
|
<span class="p">[].</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">'('</span><span class="p">),</span> <span class="nx">fragments</span><span class="p">,</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">')'</span><span class="p">)</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-20">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-20">¶</a>
|
|
</div>
|
|
|
|
<p><code>fragmentsList</code> is an array of arrays of fragments. Each array in fragmentsList will be
|
|
concatonated 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> <span class="nv">joinFragmentArrays: </span><span class="nf">(fragmentsList, joinStr) -></span>
|
|
<span class="nv">answer = </span><span class="p">[]</span>
|
|
<span class="k">for</span> <span class="nx">fragments</span><span class="p">,</span><span class="nx">i</span> <span class="k">in</span> <span class="nx">fragmentsList</span>
|
|
<span class="k">if</span> <span class="nx">i</span> <span class="k">then</span> <span class="nx">answer</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="nx">joinStr</span>
|
|
<span class="nv">answer = </span><span class="nx">answer</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">fragments</span>
|
|
<span class="nx">answer</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-21">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-21">¶</a>
|
|
</div>
|
|
|
|
<h3>Block</h3>
|
|
<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><span class="nv">exports.Block = </span><span class="k">class</span> <span class="nx">Block</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(nodes) -></span>
|
|
<span class="vi">@expressions = </span><span class="nx">compact</span> <span class="nx">flatten</span> <span class="nx">nodes</span> <span class="o">or</span> <span class="p">[]</span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'expressions'</span><span class="p">]</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-22">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-22">¶</a>
|
|
</div>
|
|
|
|
<p>Tack an expression on to the end of this expression list.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">push: </span><span class="nf">(node) -></span>
|
|
<span class="nx">@expressions</span><span class="p">.</span><span class="nx">push</span> <span class="nx">node</span>
|
|
<span class="k">this</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-23">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-23">¶</a>
|
|
</div>
|
|
|
|
<p>Remove and return the last expression of this expression list.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">pop: </span><span class="nf">-></span>
|
|
<span class="nx">@expressions</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-24">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-24">¶</a>
|
|
</div>
|
|
|
|
<p>Add an expression at the beginning of this expression list.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">unshift: </span><span class="nf">(node) -></span>
|
|
<span class="nx">@expressions</span><span class="p">.</span><span class="nx">unshift</span> <span class="nx">node</span>
|
|
<span class="k">this</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-25">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-25">¶</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> <span class="nv">unwrap: </span><span class="nf">-></span>
|
|
<span class="k">if</span> <span class="nx">@expressions</span><span class="p">.</span><span class="nx">length</span> <span class="o">is</span> <span class="mi">1</span> <span class="k">then</span> <span class="nx">@expressions</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">else</span> <span class="k">this</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-26">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-26">¶</a>
|
|
</div>
|
|
|
|
<p>Is this an empty block of code?
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">isEmpty: </span><span class="nf">-></span>
|
|
<span class="o">not</span> <span class="nx">@expressions</span><span class="p">.</span><span class="nx">length</span>
|
|
|
|
<span class="nv">isStatement: </span><span class="nf">(o) -></span>
|
|
<span class="k">for</span> <span class="nx">exp</span> <span class="k">in</span> <span class="nx">@expressions</span> <span class="k">when</span> <span class="nx">exp</span><span class="p">.</span><span class="nx">isStatement</span> <span class="nx">o</span>
|
|
<span class="k">return</span> <span class="kc">yes</span>
|
|
<span class="kc">no</span>
|
|
|
|
<span class="nv">jumps: </span><span class="nf">(o) -></span>
|
|
<span class="k">for</span> <span class="nx">exp</span> <span class="k">in</span> <span class="nx">@expressions</span>
|
|
<span class="k">return</span> <span class="nx">exp</span> <span class="k">if</span> <span class="nx">exp</span><span class="p">.</span><span class="nx">jumps</span> <span class="nx">o</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-27">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-27">¶</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> <span class="nv">makeReturn: </span><span class="nf">(res) -></span>
|
|
<span class="nv">len = </span><span class="nx">@expressions</span><span class="p">.</span><span class="nx">length</span>
|
|
<span class="k">while</span> <span class="nx">len</span><span class="o">--</span>
|
|
<span class="nv">expr = </span><span class="nx">@expressions</span><span class="p">[</span><span class="nx">len</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="nx">expr</span> <span class="o">not</span> <span class="k">instanceof</span> <span class="nx">Comment</span>
|
|
<span class="nx">@expressions</span><span class="p">[</span><span class="nx">len</span><span class="p">]</span> <span class="o">=</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">makeReturn</span> <span class="nx">res</span>
|
|
<span class="nx">@expressions</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">len</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="k">if</span> <span class="nx">expr</span> <span class="k">instanceof</span> <span class="nx">Return</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">expression</span>
|
|
<span class="k">break</span>
|
|
<span class="k">this</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-28">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-28">¶</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> <span class="nv">compileToFragments: </span><span class="nf">(o = {}, level) -></span>
|
|
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span> <span class="k">then</span> <span class="k">super</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">level</span> <span class="k">else</span> <span class="nx">@compileRoot</span> <span class="nx">o</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-29">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-29">¶</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> <span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="vi">@tab = </span><span class="nx">o</span><span class="p">.</span><span class="nx">indent</span>
|
|
<span class="nv">top = </span><span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">is</span> <span class="nx">LEVEL_TOP</span>
|
|
<span class="nv">compiledNodes = </span><span class="p">[]</span>
|
|
|
|
<span class="k">for</span> <span class="nx">node</span><span class="p">,</span> <span class="nx">index</span> <span class="k">in</span> <span class="nx">@expressions</span>
|
|
|
|
<span class="nv">node = </span><span class="nx">node</span><span class="p">.</span><span class="nx">unwrapAll</span><span class="p">()</span>
|
|
<span class="nv">node = </span><span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">unfoldSoak</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">or</span> <span class="nx">node</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Block</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-30">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-30">¶</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> <span class="nx">compiledNodes</span><span class="p">.</span><span class="nx">push</span> <span class="nx">node</span><span class="p">.</span><span class="nx">compileNode</span> <span class="nx">o</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="nx">top</span>
|
|
<span class="nv">node.front = </span><span class="kc">true</span>
|
|
<span class="nv">fragments = </span><span class="nx">node</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span>
|
|
<span class="k">unless</span> <span class="nx">node</span><span class="p">.</span><span class="nx">isStatement</span> <span class="nx">o</span>
|
|
<span class="nx">fragments</span><span class="p">.</span><span class="nx">unshift</span> <span class="nx">@makeCode</span> <span class="s">"</span><span class="si">#{</span><span class="nx">@tab</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="nx">fragments</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="s">";"</span>
|
|
<span class="nx">compiledNodes</span><span class="p">.</span><span class="nx">push</span> <span class="nx">fragments</span>
|
|
<span class="k">else</span>
|
|
<span class="nx">compiledNodes</span><span class="p">.</span><span class="nx">push</span> <span class="nx">node</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
|
|
<span class="k">if</span> <span class="nx">top</span>
|
|
<span class="k">if</span> <span class="nx">@spaced</span>
|
|
<span class="k">return</span> <span class="p">[].</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"\n"</span><span class="p">),</span> <span class="nx">@joinFragmentArrays</span><span class="p">(</span><span class="nx">compiledNodes</span><span class="p">,</span> <span class="s">'\n\n'</span><span class="p">),</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"\n"</span><span class="p">)</span>
|
|
<span class="k">else</span>
|
|
<span class="k">return</span> <span class="nx">@joinFragmentArrays</span><span class="p">(</span><span class="nx">compiledNodes</span><span class="p">,</span> <span class="s">'\n'</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nx">compiledNodes</span><span class="p">.</span><span class="nx">length</span>
|
|
<span class="nv">answer = </span><span class="nx">@joinFragmentArrays</span><span class="p">(</span><span class="nx">compiledNodes</span><span class="p">,</span> <span class="s">', '</span><span class="p">)</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">answer = </span><span class="p">[</span><span class="nx">@makeCode</span> <span class="s">"void 0"</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="nx">compiledNodes</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">1</span> <span class="o">and</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">>=</span> <span class="nx">LEVEL_LIST</span> <span class="k">then</span> <span class="nx">@wrapInBraces</span> <span class="nx">answer</span> <span class="k">else</span> <span class="nx">answer</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-31">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-31">¶</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> <span class="nv">compileRoot: </span><span class="nf">(o) -></span>
|
|
<span class="nv">o.indent = </span><span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">bare</span> <span class="k">then</span> <span class="s">''</span> <span class="k">else</span> <span class="nx">TAB</span>
|
|
<span class="nv">o.scope = </span><span class="k">new</span> <span class="nx">Scope</span> <span class="kc">null</span><span class="p">,</span> <span class="k">this</span><span class="p">,</span> <span class="kc">null</span>
|
|
<span class="nv">o.level = </span><span class="nx">LEVEL_TOP</span>
|
|
<span class="vi">@spaced = </span><span class="kc">yes</span>
|
|
<span class="nv">prelude = </span><span class="p">[]</span>
|
|
<span class="k">unless</span> <span class="nx">o</span><span class="p">.</span><span class="nx">bare</span>
|
|
<span class="nv">preludeExps = </span><span class="k">for</span> <span class="nx">exp</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">@expressions</span>
|
|
<span class="k">break</span> <span class="k">unless</span> <span class="nx">exp</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span> <span class="k">instanceof</span> <span class="nx">Comment</span>
|
|
<span class="nx">exp</span>
|
|
<span class="nv">rest = </span><span class="nx">@expressions</span><span class="p">[</span><span class="nx">preludeExps</span><span class="p">.</span><span class="nx">length</span><span class="p">...]</span>
|
|
<span class="vi">@expressions = </span><span class="nx">preludeExps</span>
|
|
<span class="k">if</span> <span class="nx">preludeExps</span><span class="p">.</span><span class="nx">length</span>
|
|
<span class="nv">prelude = </span><span class="nx">@compileNode</span> <span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nv">indent: </span><span class="s">''</span><span class="p">)</span>
|
|
<span class="nx">prelude</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="s">"\n"</span>
|
|
<span class="vi">@expressions = </span><span class="nx">rest</span>
|
|
<span class="nv">fragments = </span><span class="nx">@compileWithDeclarations</span> <span class="nx">o</span>
|
|
<span class="k">return</span> <span class="nx">fragments</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">bare</span>
|
|
<span class="p">[].</span><span class="nx">concat</span> <span class="nx">prelude</span><span class="p">,</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"(function() {\n"</span><span class="p">),</span> <span class="nx">fragments</span><span class="p">,</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"\n}).call(this);\n"</span><span class="p">)</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-32">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-32">¶</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> <span class="nv">compileWithDeclarations: </span><span class="nf">(o) -></span>
|
|
<span class="nv">fragments = </span><span class="p">[]</span>
|
|
<span class="nv">post = </span><span class="p">[]</span>
|
|
<span class="k">for</span> <span class="nx">exp</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">@expressions</span>
|
|
<span class="nv">exp = </span><span class="nx">exp</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span>
|
|
<span class="k">break</span> <span class="k">unless</span> <span class="nx">exp</span> <span class="k">instanceof</span> <span class="nx">Comment</span> <span class="o">or</span> <span class="nx">exp</span> <span class="k">instanceof</span> <span class="nx">Literal</span>
|
|
<span class="nv">o = </span><span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nv">level: </span><span class="nx">LEVEL_TOP</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nx">i</span>
|
|
<span class="nv">rest = </span><span class="nx">@expressions</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">9</span><span class="nx">e9</span>
|
|
<span class="p">[</span><span class="nx">spaced</span><span class="p">,</span> <span class="nx">@spaced</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">@spaced</span><span class="p">,</span> <span class="kc">no</span><span class="p">]</span>
|
|
<span class="p">[</span><span class="nx">fragments</span><span class="p">,</span> <span class="nx">@spaced</span><span class="p">]</span> <span class="o">=</span> <span class="p">[(</span><span class="nx">@compileNode</span> <span class="nx">o</span><span class="p">),</span> <span class="nx">spaced</span><span class="p">]</span>
|
|
<span class="vi">@expressions = </span><span class="nx">rest</span>
|
|
<span class="nv">post = </span><span class="nx">@compileNode</span> <span class="nx">o</span>
|
|
<span class="p">{</span><span class="nx">scope</span><span class="p">}</span> <span class="o">=</span> <span class="nx">o</span>
|
|
<span class="k">if</span> <span class="nx">scope</span><span class="p">.</span><span class="nx">expressions</span> <span class="o">is</span> <span class="k">this</span>
|
|
<span class="nv">declars = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">hasDeclarations</span><span class="p">()</span>
|
|
<span class="nv">assigns = </span><span class="nx">scope</span><span class="p">.</span><span class="nx">hasAssignments</span>
|
|
<span class="k">if</span> <span class="nx">declars</span> <span class="o">or</span> <span class="nx">assigns</span>
|
|
<span class="nx">fragments</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="s">'\n'</span> <span class="k">if</span> <span class="nx">i</span>
|
|
<span class="nx">fragments</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="s">"</span><span class="si">#{</span><span class="nx">@tab</span><span class="si">}</span><span class="s">var "</span>
|
|
<span class="k">if</span> <span class="nx">declars</span>
|
|
<span class="nx">fragments</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="nx">scope</span><span class="p">.</span><span class="nx">declaredVariables</span><span class="p">().</span><span class="nx">join</span> <span class="s">', '</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nx">assigns</span>
|
|
<span class="nx">fragments</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="s">",\n</span><span class="si">#{</span><span class="nx">@tab</span> <span class="o">+</span> <span class="nx">TAB</span><span class="si">}</span><span class="s">"</span> <span class="k">if</span> <span class="nx">declars</span>
|
|
<span class="nx">fragments</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="p">(</span><span class="nx">scope</span><span class="p">.</span><span class="nx">assignedVariables</span><span class="p">().</span><span class="nx">join</span> <span class="s">",\n</span><span class="si">#{</span><span class="nx">@tab</span> <span class="o">+</span> <span class="nx">TAB</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
|
|
<span class="nx">fragments</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="s">';\n'</span>
|
|
<span class="nx">fragments</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">post</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-33">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-33">¶</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> <span class="vi">@wrap: </span><span class="nf">(nodes) -></span>
|
|
<span class="k">return</span> <span class="nx">nodes</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="nx">nodes</span><span class="p">.</span><span class="nx">length</span> <span class="o">is</span> <span class="mi">1</span> <span class="o">and</span> <span class="nx">nodes</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">instanceof</span> <span class="nx">Block</span>
|
|
<span class="k">new</span> <span class="nx">Block</span> <span class="nx">nodes</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-34">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-34">¶</a>
|
|
</div>
|
|
|
|
<h3>Literal</h3>
|
|
<p>Literals are 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><span class="nv">exports.Literal = </span><span class="k">class</span> <span class="nx">Literal</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(@value) -></span>
|
|
|
|
<span class="nv">makeReturn: </span><span class="nf">-></span>
|
|
<span class="k">if</span> <span class="nx">@isStatement</span><span class="p">()</span> <span class="k">then</span> <span class="k">this</span> <span class="k">else</span> <span class="k">super</span>
|
|
|
|
<span class="nv">isAssignable: </span><span class="nf">-></span>
|
|
<span class="nx">IDENTIFIER</span><span class="p">.</span><span class="nx">test</span> <span class="nx">@value</span>
|
|
|
|
<span class="nv">isStatement: </span><span class="nf">-></span>
|
|
<span class="nx">@value</span> <span class="k">in</span> <span class="p">[</span><span class="s">'break'</span><span class="p">,</span> <span class="s">'continue'</span><span class="p">,</span> <span class="s">'debugger'</span><span class="p">]</span>
|
|
|
|
<span class="nv">isComplex: </span><span class="nx">NO</span>
|
|
|
|
<span class="nv">assigns: </span><span class="nf">(name) -></span>
|
|
<span class="nx">name</span> <span class="o">is</span> <span class="nx">@value</span>
|
|
|
|
<span class="nv">jumps: </span><span class="nf">(o) -></span>
|
|
<span class="k">return</span> <span class="k">this</span> <span class="k">if</span> <span class="nx">@value</span> <span class="o">is</span> <span class="s">'break'</span> <span class="o">and</span> <span class="o">not</span> <span class="p">(</span><span class="nx">o</span><span class="o">?</span><span class="p">.</span><span class="nx">loop</span> <span class="o">or</span> <span class="nx">o</span><span class="o">?</span><span class="p">.</span><span class="nx">block</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="k">this</span> <span class="k">if</span> <span class="nx">@value</span> <span class="o">is</span> <span class="s">'continue'</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">o</span><span class="o">?</span><span class="p">.</span><span class="nx">loop</span>
|
|
|
|
<span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="nv">code = </span><span class="k">if</span> <span class="nx">@value</span> <span class="o">is</span> <span class="s">'this'</span>
|
|
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">method</span><span class="o">?</span><span class="p">.</span><span class="nx">bound</span> <span class="k">then</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">method</span><span class="p">.</span><span class="nx">context</span> <span class="k">else</span> <span class="nx">@value</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="nx">@value</span><span class="p">.</span><span class="nx">reserved</span>
|
|
<span class="s">"\"</span><span class="si">#{</span><span class="nx">@value</span><span class="si">}</span><span class="s">\""</span>
|
|
<span class="k">else</span>
|
|
<span class="nx">@value</span>
|
|
<span class="nv">answer = </span><span class="k">if</span> <span class="nx">@isStatement</span><span class="p">()</span> <span class="k">then</span> <span class="s">"</span><span class="si">#{</span><span class="nx">@tab</span><span class="si">}#{</span><span class="nx">code</span><span class="si">}</span><span class="s">;"</span> <span class="k">else</span> <span class="nx">code</span>
|
|
<span class="p">[</span><span class="nx">@makeCode</span> <span class="nx">answer</span><span class="p">]</span>
|
|
|
|
<span class="nv">toString: </span><span class="nf">-></span>
|
|
<span class="s">' "'</span> <span class="o">+</span> <span class="nx">@value</span> <span class="o">+</span> <span class="s">'"'</span>
|
|
|
|
<span class="k">class</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">Undefined</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">isAssignable: </span><span class="nx">NO</span>
|
|
<span class="nv">isComplex: </span><span class="nx">NO</span>
|
|
<span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="p">[</span><span class="nx">@makeCode</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">>=</span> <span class="nx">LEVEL_ACCESS</span> <span class="k">then</span> <span class="s">'(void 0)'</span> <span class="k">else</span> <span class="s">'void 0'</span><span class="p">]</span>
|
|
|
|
<span class="k">class</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">Null</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">isAssignable: </span><span class="nx">NO</span>
|
|
<span class="nv">isComplex: </span><span class="nx">NO</span>
|
|
<span class="nv">compileNode: </span><span class="nf">-></span> <span class="p">[</span><span class="nx">@makeCode</span> <span class="s">"null"</span><span class="p">]</span>
|
|
|
|
<span class="k">class</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">Bool</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">isAssignable: </span><span class="nx">NO</span>
|
|
<span class="nv">isComplex: </span><span class="nx">NO</span>
|
|
<span class="nv">compileNode: </span><span class="nf">-></span> <span class="p">[</span><span class="nx">@makeCode</span> <span class="nx">@val</span><span class="p">]</span>
|
|
<span class="nv">constructor: </span><span class="nf">(@val) -></span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-35">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-35">¶</a>
|
|
</div>
|
|
|
|
<h3>Return</h3>
|
|
<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><span class="nv">exports.Return = </span><span class="k">class</span> <span class="nx">Return</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(expr) -></span>
|
|
<span class="vi">@expression = </span><span class="nx">expr</span> <span class="k">if</span> <span class="nx">expr</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">().</span><span class="nx">isUndefined</span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'expression'</span><span class="p">]</span>
|
|
|
|
<span class="nv">isStatement: </span> <span class="nx">YES</span>
|
|
<span class="nv">makeReturn: </span> <span class="nx">THIS</span>
|
|
<span class="nv">jumps: </span> <span class="nx">THIS</span>
|
|
|
|
<span class="nv">compileToFragments: </span><span class="nf">(o, level) -></span>
|
|
<span class="nv">expr = </span><span class="nx">@expression</span><span class="o">?</span><span class="p">.</span><span class="nx">makeReturn</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="nx">expr</span> <span class="o">and</span> <span class="nx">expr</span> <span class="o">not</span> <span class="k">instanceof</span> <span class="nx">Return</span> <span class="k">then</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">level</span> <span class="k">else</span> <span class="k">super</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">level</span>
|
|
|
|
<span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="nv">answer = </span><span class="p">[]</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-36">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-36">¶</a>
|
|
</div>
|
|
|
|
<p>TODO: If we call expression.compile() here twice, we'll sometimes get back different results!
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nx">answer</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="nx">@tab</span> <span class="o">+</span> <span class="s">"return</span><span class="si">#{</span><span class="p">[</span><span class="s">" "</span> <span class="k">if</span> <span class="nx">@expression</span><span class="p">]</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nx">@expression</span>
|
|
<span class="nv">answer = </span><span class="nx">answer</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">@expression</span><span class="p">.</span><span class="nx">compileToFragments</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_PAREN</span><span class="p">)</span>
|
|
<span class="nx">answer</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="s">";"</span>
|
|
<span class="k">return</span> <span class="nx">answer</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-37">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-37">¶</a>
|
|
</div>
|
|
|
|
<h3>Value</h3>
|
|
<p>A value, variable or literal or parenthesized, indexed or dotted into,
|
|
or vanilla.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre><span class="nv">exports.Value = </span><span class="k">class</span> <span class="nx">Value</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(base, props, tag) -></span>
|
|
<span class="k">return</span> <span class="nx">base</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">props</span> <span class="o">and</span> <span class="nx">base</span> <span class="k">instanceof</span> <span class="nx">Value</span>
|
|
<span class="vi">@base = </span><span class="nx">base</span>
|
|
<span class="vi">@properties = </span><span class="nx">props</span> <span class="o">or</span> <span class="p">[]</span>
|
|
<span class="nx">@</span><span class="p">[</span><span class="nx">tag</span><span class="p">]</span> <span class="o">=</span> <span class="kc">true</span> <span class="k">if</span> <span class="nx">tag</span>
|
|
<span class="k">return</span> <span class="k">this</span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'base'</span><span class="p">,</span> <span class="s">'properties'</span><span class="p">]</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-38">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-38">¶</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> <span class="nv">add: </span><span class="nf">(props) -></span>
|
|
<span class="vi">@properties = </span><span class="nx">@properties</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">props</span>
|
|
<span class="k">this</span>
|
|
|
|
<span class="nv">hasProperties: </span><span class="nf">-></span>
|
|
<span class="o">!!</span><span class="nx">@properties</span><span class="p">.</span><span class="nx">length</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-39">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-39">¶</a>
|
|
</div>
|
|
|
|
<p>Some boolean checks for the benefit of other nodes.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">isArray : </span><span class="nf">-></span> <span class="o">not</span> <span class="nx">@properties</span><span class="p">.</span><span class="nx">length</span> <span class="o">and</span> <span class="nx">@base</span> <span class="k">instanceof</span> <span class="nx">Arr</span>
|
|
<span class="nv">isComplex : </span><span class="nf">-></span> <span class="nx">@hasProperties</span><span class="p">()</span> <span class="o">or</span> <span class="nx">@base</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span>
|
|
<span class="nv">isAssignable : </span><span class="nf">-></span> <span class="nx">@hasProperties</span><span class="p">()</span> <span class="o">or</span> <span class="nx">@base</span><span class="p">.</span><span class="nx">isAssignable</span><span class="p">()</span>
|
|
<span class="nv">isSimpleNumber : </span><span class="nf">-></span> <span class="nx">@base</span> <span class="k">instanceof</span> <span class="nx">Literal</span> <span class="o">and</span> <span class="nx">SIMPLENUM</span><span class="p">.</span><span class="nx">test</span> <span class="nx">@base</span><span class="p">.</span><span class="nx">value</span>
|
|
<span class="nv">isString : </span><span class="nf">-></span> <span class="nx">@base</span> <span class="k">instanceof</span> <span class="nx">Literal</span> <span class="o">and</span> <span class="nx">IS_STRING</span><span class="p">.</span><span class="nx">test</span> <span class="nx">@base</span><span class="p">.</span><span class="nx">value</span>
|
|
<span class="nv">isAtomic : </span><span class="nf">-></span>
|
|
<span class="k">for</span> <span class="nx">node</span> <span class="k">in</span> <span class="nx">@properties</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">@base</span>
|
|
<span class="k">return</span> <span class="kc">no</span> <span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">soak</span> <span class="o">or</span> <span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Call</span>
|
|
<span class="kc">yes</span>
|
|
|
|
<span class="nv">isStatement : </span><span class="nf">(o) -></span> <span class="o">not</span> <span class="nx">@properties</span><span class="p">.</span><span class="nx">length</span> <span class="o">and</span> <span class="nx">@base</span><span class="p">.</span><span class="nx">isStatement</span> <span class="nx">o</span>
|
|
<span class="nv">assigns : </span><span class="nf">(name) -></span> <span class="o">not</span> <span class="nx">@properties</span><span class="p">.</span><span class="nx">length</span> <span class="o">and</span> <span class="nx">@base</span><span class="p">.</span><span class="nx">assigns</span> <span class="nx">name</span>
|
|
<span class="nv">jumps : </span><span class="nf">(o) -></span> <span class="o">not</span> <span class="nx">@properties</span><span class="p">.</span><span class="nx">length</span> <span class="o">and</span> <span class="nx">@base</span><span class="p">.</span><span class="nx">jumps</span> <span class="nx">o</span>
|
|
|
|
<span class="nv">isObject: </span><span class="nf">(onlyGenerated) -></span>
|
|
<span class="k">return</span> <span class="kc">no</span> <span class="k">if</span> <span class="nx">@properties</span><span class="p">.</span><span class="nx">length</span>
|
|
<span class="p">(</span><span class="nx">@base</span> <span class="k">instanceof</span> <span class="nx">Obj</span><span class="p">)</span> <span class="o">and</span> <span class="p">(</span><span class="o">not</span> <span class="nx">onlyGenerated</span> <span class="o">or</span> <span class="nx">@base</span><span class="p">.</span><span class="nx">generated</span><span class="p">)</span>
|
|
|
|
<span class="nv">isSplice: </span><span class="nf">-></span>
|
|
<span class="nx">last</span><span class="p">(</span><span class="nx">@properties</span><span class="p">)</span> <span class="k">instanceof</span> <span class="nx">Slice</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-40">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-40">¶</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> <span class="nv">unwrap: </span><span class="nf">-></span>
|
|
<span class="k">if</span> <span class="nx">@properties</span><span class="p">.</span><span class="nx">length</span> <span class="k">then</span> <span class="k">this</span> <span class="k">else</span> <span class="nx">@base</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-41">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-41">¶</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> <span class="nv">cacheReference: </span><span class="nf">(o) -></span>
|
|
<span class="nv">name = </span><span class="nx">last</span> <span class="nx">@properties</span>
|
|
<span class="k">if</span> <span class="nx">@properties</span><span class="p">.</span><span class="nx">length</span> <span class="o"><</span> <span class="mi">2</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@base</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">name</span><span class="o">?</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span>
|
|
<span class="k">return</span> <span class="p">[</span><span class="k">this</span><span class="p">,</span> <span class="k">this</span><span class="p">]</span> <span class="c1"># `a` `a.b`</span>
|
|
<span class="nv">base = </span><span class="k">new</span> <span class="nx">Value</span> <span class="nx">@base</span><span class="p">,</span> <span class="nx">@properties</span><span class="p">[...</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="nx">base</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span> <span class="c1"># `a().b`</span>
|
|
<span class="nv">bref = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s">'base'</span>
|
|
<span class="nv">base = </span><span class="k">new</span> <span class="nx">Value</span> <span class="k">new</span> <span class="nx">Parens</span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">bref</span><span class="p">,</span> <span class="nx">base</span>
|
|
<span class="k">return</span> <span class="p">[</span><span class="nx">base</span><span class="p">,</span> <span class="nx">bref</span><span class="p">]</span> <span class="k">unless</span> <span class="nx">name</span> <span class="c1"># `a()`</span>
|
|
<span class="k">if</span> <span class="nx">name</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span> <span class="c1"># `a[b()]`</span>
|
|
<span class="nv">nref = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s">'name'</span>
|
|
<span class="nv">name = </span><span class="k">new</span> <span class="nx">Index</span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">nref</span><span class="p">,</span> <span class="nx">name</span><span class="p">.</span><span class="nx">index</span>
|
|
<span class="nv">nref = </span><span class="k">new</span> <span class="nx">Index</span> <span class="nx">nref</span>
|
|
<span class="p">[</span><span class="nx">base</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">name</span><span class="p">),</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="nx">bref</span> <span class="o">or</span> <span class="nx">base</span><span class="p">.</span><span class="nx">base</span><span class="p">,</span> <span class="p">[</span><span class="nx">nref</span> <span class="o">or</span> <span class="nx">name</span><span class="p">])]</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-42">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-42">¶</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> <span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="vi">@base.front = </span><span class="nx">@front</span>
|
|
<span class="nv">props = </span><span class="nx">@properties</span>
|
|
<span class="nv">fragments = </span><span class="nx">@base</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="p">(</span><span class="k">if</span> <span class="nx">props</span><span class="p">.</span><span class="nx">length</span> <span class="k">then</span> <span class="nx">LEVEL_ACCESS</span> <span class="k">else</span> <span class="kc">null</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">@base</span> <span class="k">instanceof</span> <span class="nx">Parens</span> <span class="o">or</span> <span class="nx">props</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="o">and</span> <span class="nx">SIMPLENUM</span><span class="p">.</span><span class="nx">test</span> <span class="nx">fragmentsToText</span> <span class="nx">fragments</span>
|
|
<span class="nx">fragments</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="s">'.'</span>
|
|
<span class="k">for</span> <span class="nx">prop</span> <span class="k">in</span> <span class="nx">props</span>
|
|
<span class="nx">fragments</span><span class="p">.</span><span class="nx">push</span> <span class="p">(</span><span class="nx">prop</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">)...</span>
|
|
<span class="nx">fragments</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-43">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-43">¶</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> <span class="nv">unfoldSoak: </span><span class="nf">(o) -></span>
|
|
<span class="nx">@unfoldedSoak</span> <span class="o">?=</span> <span class="nx">do</span> <span class="o">=></span>
|
|
<span class="k">if</span> <span class="nv">ifn = </span><span class="nx">@base</span><span class="p">.</span><span class="nx">unfoldSoak</span> <span class="nx">o</span>
|
|
<span class="nx">ifn</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@properties</span><span class="p">...</span>
|
|
<span class="k">return</span> <span class="nx">ifn</span>
|
|
<span class="k">for</span> <span class="nx">prop</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">@properties</span> <span class="k">when</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">soak</span>
|
|
<span class="nv">prop.soak = </span><span class="kc">off</span>
|
|
<span class="nv">fst = </span><span class="k">new</span> <span class="nx">Value</span> <span class="nx">@base</span><span class="p">,</span> <span class="nx">@properties</span><span class="p">[...</span><span class="nx">i</span><span class="p">]</span>
|
|
<span class="nv">snd = </span><span class="k">new</span> <span class="nx">Value</span> <span class="nx">@base</span><span class="p">,</span> <span class="nx">@properties</span><span class="p">[</span><span class="nx">i</span><span class="p">..]</span>
|
|
<span class="k">if</span> <span class="nx">fst</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span>
|
|
<span class="nv">ref = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s">'ref'</span>
|
|
<span class="nv">fst = </span><span class="k">new</span> <span class="nx">Parens</span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">ref</span><span class="p">,</span> <span class="nx">fst</span>
|
|
<span class="nv">snd.base = </span><span class="nx">ref</span>
|
|
<span class="k">return</span> <span class="k">new</span> <span class="nx">If</span> <span class="k">new</span> <span class="nx">Existence</span><span class="p">(</span><span class="nx">fst</span><span class="p">),</span> <span class="nx">snd</span><span class="p">,</span> <span class="nv">soak: </span><span class="kc">on</span>
|
|
<span class="kc">no</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-44">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-44">¶</a>
|
|
</div>
|
|
|
|
<h3>Comment</h3>
|
|
<p>CoffeeScript passes through block comments as JavaScript block comments
|
|
at the same position.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre><span class="nv">exports.Comment = </span><span class="k">class</span> <span class="nx">Comment</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(@comment) -></span>
|
|
|
|
<span class="nv">isStatement: </span> <span class="nx">YES</span>
|
|
<span class="nv">makeReturn: </span> <span class="nx">THIS</span>
|
|
|
|
<span class="nv">compileNode: </span><span class="nf">(o, level) -></span>
|
|
<span class="nv">code = </span><span class="s">'/*'</span> <span class="o">+</span> <span class="nx">multident</span><span class="p">(</span><span class="nx">@comment</span><span class="p">,</span> <span class="nx">@tab</span><span class="p">)</span> <span class="o">+</span> <span class="s">"\n</span><span class="si">#{</span><span class="nx">@tab</span><span class="si">}</span><span class="s">*/\n"</span>
|
|
<span class="nv">code = </span><span class="nx">o</span><span class="p">.</span><span class="nx">indent</span> <span class="o">+</span> <span class="nx">code</span> <span class="k">if</span> <span class="p">(</span><span class="nx">level</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span><span class="p">)</span> <span class="o">is</span> <span class="nx">LEVEL_TOP</span>
|
|
<span class="p">[</span><span class="nx">@makeCode</span> <span class="nx">code</span><span class="p">]</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-45">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-45">¶</a>
|
|
</div>
|
|
|
|
<h3>Call</h3>
|
|
<p>Node for a function invocation. Takes care of converting <code>super()</code> calls into
|
|
calls against the prototype's function of the same name.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre><span class="nv">exports.Call = </span><span class="k">class</span> <span class="nx">Call</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(variable, @args = [], @soak) -></span>
|
|
<span class="vi">@isNew = </span><span class="kc">false</span>
|
|
<span class="vi">@isSuper = </span><span class="nx">variable</span> <span class="o">is</span> <span class="s">'super'</span>
|
|
<span class="vi">@variable = </span><span class="k">if</span> <span class="nx">@isSuper</span> <span class="k">then</span> <span class="kc">null</span> <span class="k">else</span> <span class="nx">variable</span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'variable'</span><span class="p">,</span> <span class="s">'args'</span><span class="p">]</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-46">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-46">¶</a>
|
|
</div>
|
|
|
|
<p>Tag this invocation as creating a new instance.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">newInstance: </span><span class="nf">-></span>
|
|
<span class="nv">base = </span><span class="nx">@variable</span><span class="o">?</span><span class="p">.</span><span class="nx">base</span> <span class="o">or</span> <span class="nx">@variable</span>
|
|
<span class="k">if</span> <span class="nx">base</span> <span class="k">instanceof</span> <span class="nx">Call</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">base</span><span class="p">.</span><span class="nx">isNew</span>
|
|
<span class="nx">base</span><span class="p">.</span><span class="nx">newInstance</span><span class="p">()</span>
|
|
<span class="k">else</span>
|
|
<span class="vi">@isNew = </span><span class="kc">true</span>
|
|
<span class="k">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>Grab the reference to the superclass's implementation of the current
|
|
method.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">superReference: </span><span class="nf">(o) -></span>
|
|
<span class="nv">method = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">namedMethod</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="nx">method</span><span class="o">?</span><span class="p">.</span><span class="nx">klass</span>
|
|
<span class="nv">accesses = </span><span class="p">[</span><span class="k">new</span> <span class="nx">Access</span><span class="p">(</span><span class="k">new</span> <span class="nx">Literal</span> <span class="s">'__super__'</span><span class="p">)]</span>
|
|
<span class="nx">accesses</span><span class="p">.</span><span class="nx">push</span> <span class="k">new</span> <span class="nx">Access</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">'constructor'</span> <span class="k">if</span> <span class="nx">method</span><span class="p">.</span><span class="nx">static</span>
|
|
<span class="nx">accesses</span><span class="p">.</span><span class="nx">push</span> <span class="k">new</span> <span class="nx">Access</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">method</span><span class="p">.</span><span class="nx">name</span>
|
|
<span class="p">(</span><span class="k">new</span> <span class="nx">Value</span> <span class="p">(</span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">method</span><span class="p">.</span><span class="nx">klass</span><span class="p">),</span> <span class="nx">accesses</span><span class="p">).</span><span class="nx">compile</span> <span class="nx">o</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="nx">method</span><span class="o">?</span><span class="p">.</span><span class="nx">ctor</span>
|
|
<span class="s">"</span><span class="si">#{</span><span class="nx">method</span><span class="p">.</span><span class="nx">name</span><span class="si">}</span><span class="s">.__super__.constructor"</span>
|
|
<span class="k">else</span>
|
|
<span class="nx">@error</span> <span class="s">'cannot call super outside of an instance method.'</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-48">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-48">¶</a>
|
|
</div>
|
|
|
|
<p>The appropriate <code>this</code> value for a <code>super</code> call.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">superThis : </span><span class="nf">(o) -></span>
|
|
<span class="nv">method = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">method</span>
|
|
<span class="p">(</span><span class="nx">method</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">method</span><span class="p">.</span><span class="nx">klass</span> <span class="o">and</span> <span class="nx">method</span><span class="p">.</span><span class="nx">context</span><span class="p">)</span> <span class="o">or</span> <span class="s">"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>Soaked chained invocations unfold into if/else ternary structures.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">unfoldSoak: </span><span class="nf">(o) -></span>
|
|
<span class="k">if</span> <span class="nx">@soak</span>
|
|
<span class="k">if</span> <span class="nx">@variable</span>
|
|
<span class="k">return</span> <span class="nx">ifn</span> <span class="k">if</span> <span class="nv">ifn = </span><span class="nx">unfoldSoak</span> <span class="nx">o</span><span class="p">,</span> <span class="k">this</span><span class="p">,</span> <span class="s">'variable'</span>
|
|
<span class="p">[</span><span class="nx">left</span><span class="p">,</span> <span class="nx">rite</span><span class="p">]</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="nx">@variable</span><span class="p">).</span><span class="nx">cacheReference</span> <span class="nx">o</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">left = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">@superReference</span> <span class="nx">o</span>
|
|
<span class="nv">rite = </span><span class="k">new</span> <span class="nx">Value</span> <span class="nx">left</span>
|
|
<span class="nv">rite = </span><span class="k">new</span> <span class="nx">Call</span> <span class="nx">rite</span><span class="p">,</span> <span class="nx">@args</span>
|
|
<span class="nv">rite.isNew = </span><span class="nx">@isNew</span>
|
|
<span class="nv">left = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="s">"typeof </span><span class="si">#{</span> <span class="nx">left</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span> <span class="si">}</span><span class="s"> === \"function\""</span>
|
|
<span class="k">return</span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">left</span><span class="p">,</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="nx">rite</span><span class="p">),</span> <span class="nv">soak: </span><span class="kc">yes</span>
|
|
<span class="nv">call = </span><span class="k">this</span>
|
|
<span class="nv">list = </span><span class="p">[]</span>
|
|
<span class="k">loop</span>
|
|
<span class="k">if</span> <span class="nx">call</span><span class="p">.</span><span class="nx">variable</span> <span class="k">instanceof</span> <span class="nx">Call</span>
|
|
<span class="nx">list</span><span class="p">.</span><span class="nx">push</span> <span class="nx">call</span>
|
|
<span class="nv">call = </span><span class="nx">call</span><span class="p">.</span><span class="nx">variable</span>
|
|
<span class="k">continue</span>
|
|
<span class="k">break</span> <span class="k">unless</span> <span class="nx">call</span><span class="p">.</span><span class="nx">variable</span> <span class="k">instanceof</span> <span class="nx">Value</span>
|
|
<span class="nx">list</span><span class="p">.</span><span class="nx">push</span> <span class="nx">call</span>
|
|
<span class="k">break</span> <span class="k">unless</span> <span class="p">(</span><span class="nv">call = </span><span class="nx">call</span><span class="p">.</span><span class="nx">variable</span><span class="p">.</span><span class="nx">base</span><span class="p">)</span> <span class="k">instanceof</span> <span class="nx">Call</span>
|
|
<span class="k">for</span> <span class="nx">call</span> <span class="k">in</span> <span class="nx">list</span><span class="p">.</span><span class="nx">reverse</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="nx">ifn</span>
|
|
<span class="k">if</span> <span class="nx">call</span><span class="p">.</span><span class="nx">variable</span> <span class="k">instanceof</span> <span class="nx">Call</span>
|
|
<span class="nv">call.variable = </span><span class="nx">ifn</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">call.variable.base = </span><span class="nx">ifn</span>
|
|
<span class="nv">ifn = </span><span class="nx">unfoldSoak</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">call</span><span class="p">,</span> <span class="s">'variable'</span>
|
|
<span class="nx">ifn</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-50">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-50">¶</a>
|
|
</div>
|
|
|
|
<p>Compile a vanilla function call.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="nx">@variable</span><span class="o">?</span><span class="p">.</span><span class="nv">front = </span><span class="nx">@front</span>
|
|
<span class="nv">compiledArray = </span><span class="nx">Splat</span><span class="p">.</span><span class="nx">compileSplattedArray</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">@args</span><span class="p">,</span> <span class="kc">true</span>
|
|
<span class="k">if</span> <span class="nx">compiledArray</span><span class="p">.</span><span class="nx">length</span>
|
|
<span class="k">return</span> <span class="nx">@compileSplat</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">compiledArray</span>
|
|
<span class="nv">compiledArgs = </span><span class="p">[]</span>
|
|
<span class="k">for</span> <span class="nx">arg</span><span class="p">,</span> <span class="nx">argIndex</span> <span class="k">in</span> <span class="nx">@args</span>
|
|
<span class="k">if</span> <span class="nx">argIndex</span> <span class="k">then</span> <span class="nx">compiledArgs</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="s">", "</span>
|
|
<span class="nx">compiledArgs</span><span class="p">.</span><span class="nx">push</span> <span class="p">(</span><span class="nx">arg</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span><span class="p">)...</span>
|
|
|
|
<span class="nv">fragments = </span><span class="p">[]</span>
|
|
<span class="k">if</span> <span class="nx">@isSuper</span>
|
|
<span class="nv">preface = </span><span class="nx">@superReference</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">+</span> <span class="s">".call(</span><span class="si">#{</span><span class="nx">@superThis</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="k">if</span> <span class="nx">compiledArgs</span><span class="p">.</span><span class="nx">length</span> <span class="k">then</span> <span class="nx">preface</span> <span class="o">+=</span> <span class="s">", "</span>
|
|
<span class="nx">fragments</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="nx">preface</span>
|
|
<span class="k">else</span>
|
|
<span class="k">if</span> <span class="nx">@isNew</span> <span class="k">then</span> <span class="nx">fragments</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="s">'new '</span>
|
|
<span class="nx">fragments</span><span class="p">.</span><span class="nx">push</span> <span class="p">(</span><span class="nx">@variable</span><span class="p">.</span><span class="nx">compileToFragments</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_ACCESS</span><span class="p">))...</span>
|
|
<span class="nx">fragments</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="s">"("</span>
|
|
<span class="nx">fragments</span><span class="p">.</span><span class="nx">push</span> <span class="nx">compiledArgs</span><span class="p">...</span>
|
|
<span class="nx">fragments</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="s">")"</span>
|
|
<span class="nx">fragments</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-51">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-51">¶</a>
|
|
</div>
|
|
|
|
<p>If you call a function with a splat, it's converted into a JavaScript
|
|
<code>.apply()</code> call to allow an array of arguments to be passed.
|
|
If it's a constructor, then things get real tricky. We have to inject an
|
|
inner constructor in order to be able to pass the varargs.
|
|
|
|
</p>
|
|
<p>splatArgs is an array of CodeFragments to put into the 'apply'.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">compileSplat: </span><span class="nf">(o, splatArgs) -></span>
|
|
<span class="k">if</span> <span class="nx">@isSuper</span>
|
|
<span class="k">return</span> <span class="p">[].</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"</span><span class="si">#{</span> <span class="nx">@superReference</span> <span class="nx">o</span> <span class="si">}</span><span class="s">.apply(</span><span class="si">#{</span><span class="nx">@superThis</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span><span class="si">}</span><span class="s">, "</span><span class="p">),</span>
|
|
<span class="nx">splatArgs</span><span class="p">,</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">")"</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="nx">@isNew</span>
|
|
<span class="nv">idt = </span><span class="nx">@tab</span> <span class="o">+</span> <span class="nx">TAB</span>
|
|
<span class="k">return</span> <span class="p">[].</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"""</span>
|
|
<span class="s"> (function(func, args, ctor) {</span>
|
|
<span class="s"> </span><span class="si">#{</span><span class="nx">idt</span><span class="si">}</span><span class="s">ctor.prototype = func.prototype;</span>
|
|
<span class="s"> </span><span class="si">#{</span><span class="nx">idt</span><span class="si">}</span><span class="s">var child = new ctor, result = func.apply(child, args);</span>
|
|
<span class="s"> </span><span class="si">#{</span><span class="nx">idt</span><span class="si">}</span><span class="s">return Object(result) === result ? result : child;</span>
|
|
<span class="s"> </span><span class="si">#{</span><span class="nx">@tab</span><span class="si">}</span><span class="s">})("""</span><span class="p">),</span>
|
|
<span class="p">(</span><span class="nx">@variable</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span><span class="p">),</span>
|
|
<span class="nx">@makeCode</span><span class="p">(</span><span class="s">", "</span><span class="p">),</span> <span class="nx">splatArgs</span><span class="p">,</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">", function(){})"</span><span class="p">)</span>
|
|
|
|
<span class="nv">answer = </span><span class="p">[]</span>
|
|
<span class="nv">base = </span><span class="k">new</span> <span class="nx">Value</span> <span class="nx">@variable</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nv">name = </span><span class="nx">base</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">pop</span><span class="p">())</span> <span class="o">and</span> <span class="nx">base</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span>
|
|
<span class="nv">ref = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s">'ref'</span>
|
|
<span class="nv">answer = </span><span class="nx">answer</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"(</span><span class="si">#{</span><span class="nx">ref</span><span class="si">}</span><span class="s"> = "</span><span class="p">),</span>
|
|
<span class="p">(</span><span class="nx">base</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span><span class="p">),</span>
|
|
<span class="nx">@makeCode</span><span class="p">(</span><span class="s">")"</span><span class="p">),</span>
|
|
<span class="nx">name</span><span class="p">.</span><span class="nx">compileToFragments</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">fun = </span><span class="nx">base</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_ACCESS</span>
|
|
<span class="nv">fun = </span><span class="nx">@wrapInBraces</span> <span class="nx">fun</span> <span class="k">if</span> <span class="nx">SIMPLENUM</span><span class="p">.</span><span class="nx">test</span> <span class="nx">fragmentsToText</span> <span class="nx">fun</span>
|
|
<span class="k">if</span> <span class="nx">name</span>
|
|
<span class="nv">ref = </span><span class="nx">fragmentsToText</span> <span class="nx">fun</span>
|
|
<span class="nx">fun</span><span class="p">.</span><span class="nx">push</span> <span class="p">(</span><span class="nx">name</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">)...</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">ref = </span><span class="s">'null'</span>
|
|
<span class="nv">answer = </span><span class="nx">answer</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">fun</span>
|
|
<span class="nv">answer = </span><span class="nx">answer</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">".apply(</span><span class="si">#{</span><span class="nx">ref</span><span class="si">}</span><span class="s">, "</span><span class="p">),</span> <span class="nx">splatArgs</span><span class="p">,</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">")"</span><span class="p">)</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-52">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-52">¶</a>
|
|
</div>
|
|
|
|
<h3>Extends</h3>
|
|
<p>Node to extend an object's prototype with an ancestor object.
|
|
After <code>goog.inherits</code> from the
|
|
<a href="http://closure-library.googlecode.com/svn/docs/closureGoogBase.js.html">Closure Library</a>.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre><span class="nv">exports.Extends = </span><span class="k">class</span> <span class="nx">Extends</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(@child, @parent) -></span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'child'</span><span class="p">,</span> <span class="s">'parent'</span><span class="p">]</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-53">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-53">¶</a>
|
|
</div>
|
|
|
|
<p>Hooks one constructor into another's prototype chain.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">compileToFragments: </span><span class="nf">(o) -></span>
|
|
<span class="k">new</span> <span class="nx">Call</span><span class="p">(</span><span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">utility</span> <span class="s">'extends'</span><span class="p">),</span> <span class="p">[</span><span class="nx">@child</span><span class="p">,</span> <span class="nx">@parent</span><span class="p">]).</span><span class="nx">compileToFragments</span> <span class="nx">o</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-54">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-54">¶</a>
|
|
</div>
|
|
|
|
<h3>Access</h3>
|
|
<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><span class="nv">exports.Access = </span><span class="k">class</span> <span class="nx">Access</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(@name, tag) -></span>
|
|
<span class="vi">@name.asKey = </span><span class="kc">yes</span>
|
|
<span class="vi">@soak = </span><span class="nx">tag</span> <span class="o">is</span> <span class="s">'soak'</span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'name'</span><span class="p">]</span>
|
|
|
|
<span class="nv">compileToFragments: </span><span class="nf">(o) -></span>
|
|
<span class="nv">name = </span><span class="nx">@name</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span>
|
|
<span class="k">if</span> <span class="nx">IDENTIFIER</span><span class="p">.</span><span class="nx">test</span> <span class="nx">fragmentsToText</span> <span class="nx">name</span>
|
|
<span class="nx">name</span><span class="p">.</span><span class="nx">unshift</span> <span class="nx">@makeCode</span> <span class="s">"."</span>
|
|
<span class="k">else</span>
|
|
<span class="nx">name</span><span class="p">.</span><span class="nx">unshift</span> <span class="nx">@makeCode</span> <span class="s">"["</span>
|
|
<span class="nx">name</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="s">"]"</span>
|
|
<span class="nx">name</span>
|
|
|
|
<span class="nv">isComplex: </span><span class="nx">NO</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-55">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-55">¶</a>
|
|
</div>
|
|
|
|
<h3>Index</h3>
|
|
<p>A <code>[ ... ]</code> indexed access into an array or object.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre><span class="nv">exports.Index = </span><span class="k">class</span> <span class="nx">Index</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(@index) -></span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'index'</span><span class="p">]</span>
|
|
|
|
<span class="nv">compileToFragments: </span><span class="nf">(o) -></span>
|
|
<span class="p">[].</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"["</span><span class="p">),</span> <span class="p">(</span><span class="nx">@index</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_PAREN</span><span class="p">),</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"]"</span><span class="p">)</span>
|
|
|
|
<span class="nv">isComplex: </span><span class="nf">-></span>
|
|
<span class="nx">@index</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-56">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-56">¶</a>
|
|
</div>
|
|
|
|
<h3>Range</h3>
|
|
<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><span class="nv">exports.Range = </span><span class="k">class</span> <span class="nx">Range</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'from'</span><span class="p">,</span> <span class="s">'to'</span><span class="p">]</span>
|
|
|
|
<span class="nv">constructor: </span><span class="nf">(@from, @to, tag) -></span>
|
|
<span class="vi">@exclusive = </span><span class="nx">tag</span> <span class="o">is</span> <span class="s">'exclusive'</span>
|
|
<span class="vi">@equals = </span><span class="k">if</span> <span class="nx">@exclusive</span> <span class="k">then</span> <span class="s">''</span> <span class="k">else</span> <span class="s">'='</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-57">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-57">¶</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> <span class="nv">compileVariables: </span><span class="nf">(o) -></span>
|
|
<span class="nv">o = </span><span class="nx">merge</span> <span class="nx">o</span><span class="p">,</span> <span class="nv">top: </span><span class="kc">true</span>
|
|
<span class="p">[</span><span class="nx">@fromC</span><span class="p">,</span> <span class="nx">@fromVar</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@cacheToCodeFragments</span> <span class="nx">@from</span><span class="p">.</span><span class="nx">cache</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
|
|
<span class="p">[</span><span class="nx">@toC</span><span class="p">,</span> <span class="nx">@toVar</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@cacheToCodeFragments</span> <span class="nx">@to</span><span class="p">.</span><span class="nx">cache</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
|
|
<span class="p">[</span><span class="nx">@step</span><span class="p">,</span> <span class="nx">@stepVar</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@cacheToCodeFragments</span> <span class="nx">step</span><span class="p">.</span><span class="nx">cache</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span> <span class="k">if</span> <span class="nv">step = </span><span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s">'step'</span>
|
|
<span class="p">[</span><span class="nx">@fromNum</span><span class="p">,</span> <span class="nx">@toNum</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">@fromVar</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">SIMPLENUM</span><span class="p">),</span> <span class="nx">@toVar</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">SIMPLENUM</span><span class="p">)]</span>
|
|
<span class="vi">@stepNum = </span><span class="nx">@stepVar</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">SIMPLENUM</span><span class="p">)</span> <span class="k">if</span> <span class="nx">@stepVar</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-58">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-58">¶</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> <span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="nx">@compileVariables</span> <span class="nx">o</span> <span class="k">unless</span> <span class="nx">@fromVar</span>
|
|
<span class="k">return</span> <span class="nx">@compileArray</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">unless</span> <span class="nx">o</span><span class="p">.</span><span class="nx">index</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-59">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-59">¶</a>
|
|
</div>
|
|
|
|
<p>Set up endpoints.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">known = </span><span class="nx">@fromNum</span> <span class="o">and</span> <span class="nx">@toNum</span>
|
|
<span class="nv">idx = </span><span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s">'index'</span>
|
|
<span class="nv">idxName = </span><span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s">'name'</span>
|
|
<span class="nv">namedIndex = </span><span class="nx">idxName</span> <span class="o">and</span> <span class="nx">idxName</span> <span class="o">isnt</span> <span class="nx">idx</span>
|
|
<span class="nv">varPart = </span><span class="s">"</span><span class="si">#{</span><span class="nx">idx</span><span class="si">}</span><span class="s"> = </span><span class="si">#{</span><span class="nx">@fromC</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="nx">varPart</span> <span class="o">+=</span> <span class="s">", </span><span class="si">#{</span><span class="nx">@toC</span><span class="si">}</span><span class="s">"</span> <span class="k">if</span> <span class="nx">@toC</span> <span class="o">isnt</span> <span class="nx">@toVar</span>
|
|
<span class="nx">varPart</span> <span class="o">+=</span> <span class="s">", </span><span class="si">#{</span><span class="nx">@step</span><span class="si">}</span><span class="s">"</span> <span class="k">if</span> <span class="nx">@step</span> <span class="o">isnt</span> <span class="nx">@stepVar</span>
|
|
<span class="p">[</span><span class="nx">lt</span><span class="p">,</span> <span class="nx">gt</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="s">"</span><span class="si">#{</span><span class="nx">idx</span><span class="si">}</span><span class="s"> <</span><span class="si">#{</span><span class="nx">@equals</span><span class="si">}</span><span class="s">"</span><span class="p">,</span> <span class="s">"</span><span class="si">#{</span><span class="nx">idx</span><span class="si">}</span><span class="s"> ></span><span class="si">#{</span><span class="nx">@equals</span><span class="si">}</span><span class="s">"</span><span class="p">]</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-60">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-60">¶</a>
|
|
</div>
|
|
|
|
<p>Generate the condition.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">condPart = </span><span class="k">if</span> <span class="nx">@stepNum</span>
|
|
<span class="k">if</span> <span class="o">+</span><span class="nx">@stepNum</span> <span class="o">></span> <span class="mi">0</span> <span class="k">then</span> <span class="s">"</span><span class="si">#{</span><span class="nx">lt</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="nx">@toVar</span><span class="si">}</span><span class="s">"</span> <span class="k">else</span> <span class="s">"</span><span class="si">#{</span><span class="nx">gt</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="nx">@toVar</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="nx">known</span>
|
|
<span class="p">[</span><span class="nx">from</span><span class="p">,</span> <span class="nx">to</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="o">+</span><span class="nx">@fromNum</span><span class="p">,</span> <span class="o">+</span><span class="nx">@toNum</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="nx">from</span> <span class="o"><=</span> <span class="nx">to</span> <span class="k">then</span> <span class="s">"</span><span class="si">#{</span><span class="nx">lt</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="nx">to</span><span class="si">}</span><span class="s">"</span> <span class="k">else</span> <span class="s">"</span><span class="si">#{</span><span class="nx">gt</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="nx">to</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">cond = </span><span class="k">if</span> <span class="nx">@stepVar</span> <span class="k">then</span> <span class="s">"</span><span class="si">#{</span><span class="nx">@stepVar</span><span class="si">}</span><span class="s"> > 0"</span> <span class="k">else</span> <span class="s">"</span><span class="si">#{</span><span class="nx">@fromVar</span><span class="si">}</span><span class="s"> <= </span><span class="si">#{</span><span class="nx">@toVar</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="s">"</span><span class="si">#{</span><span class="nx">cond</span><span class="si">}</span><span class="s"> ? </span><span class="si">#{</span><span class="nx">lt</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="nx">@toVar</span><span class="si">}</span><span class="s"> : </span><span class="si">#{</span><span class="nx">gt</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="nx">@toVar</span><span class="si">}</span><span class="s">"</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-61">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-61">¶</a>
|
|
</div>
|
|
|
|
<p>Generate the step.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">stepPart = </span><span class="k">if</span> <span class="nx">@stepVar</span>
|
|
<span class="s">"</span><span class="si">#{</span><span class="nx">idx</span><span class="si">}</span><span class="s"> += </span><span class="si">#{</span><span class="nx">@stepVar</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="nx">known</span>
|
|
<span class="k">if</span> <span class="nx">namedIndex</span>
|
|
<span class="k">if</span> <span class="nx">from</span> <span class="o"><=</span> <span class="nx">to</span> <span class="k">then</span> <span class="s">"++</span><span class="si">#{</span><span class="nx">idx</span><span class="si">}</span><span class="s">"</span> <span class="k">else</span> <span class="s">"--</span><span class="si">#{</span><span class="nx">idx</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="k">else</span>
|
|
<span class="k">if</span> <span class="nx">from</span> <span class="o"><=</span> <span class="nx">to</span> <span class="k">then</span> <span class="s">"</span><span class="si">#{</span><span class="nx">idx</span><span class="si">}</span><span class="s">++"</span> <span class="k">else</span> <span class="s">"</span><span class="si">#{</span><span class="nx">idx</span><span class="si">}</span><span class="s">--"</span>
|
|
<span class="k">else</span>
|
|
<span class="k">if</span> <span class="nx">namedIndex</span>
|
|
<span class="s">"</span><span class="si">#{</span><span class="nx">cond</span><span class="si">}</span><span class="s"> ? ++</span><span class="si">#{</span><span class="nx">idx</span><span class="si">}</span><span class="s"> : --</span><span class="si">#{</span><span class="nx">idx</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="k">else</span>
|
|
<span class="s">"</span><span class="si">#{</span><span class="nx">cond</span><span class="si">}</span><span class="s"> ? </span><span class="si">#{</span><span class="nx">idx</span><span class="si">}</span><span class="s">++ : </span><span class="si">#{</span><span class="nx">idx</span><span class="si">}</span><span class="s">--"</span>
|
|
|
|
<span class="nv">varPart = </span><span class="s">"</span><span class="si">#{</span><span class="nx">idxName</span><span class="si">}</span><span class="s"> = </span><span class="si">#{</span><span class="nx">varPart</span><span class="si">}</span><span class="s">"</span> <span class="k">if</span> <span class="nx">namedIndex</span>
|
|
<span class="nv">stepPart = </span><span class="s">"</span><span class="si">#{</span><span class="nx">idxName</span><span class="si">}</span><span class="s"> = </span><span class="si">#{</span><span class="nx">stepPart</span><span class="si">}</span><span class="s">"</span> <span class="k">if</span> <span class="nx">namedIndex</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-62">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-62">¶</a>
|
|
</div>
|
|
|
|
<p>The final loop body.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="p">[</span><span class="nx">@makeCode</span> <span class="s">"</span><span class="si">#{</span><span class="nx">varPart</span><span class="si">}</span><span class="s">; </span><span class="si">#{</span><span class="nx">condPart</span><span class="si">}</span><span class="s">; </span><span class="si">#{</span><span class="nx">stepPart</span><span class="si">}</span><span class="s">"</span><span class="p">]</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-63">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-63">¶</a>
|
|
</div>
|
|
|
|
<p>When used as a value, expand the range into the equivalent array.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">compileArray: </span><span class="nf">(o) -></span>
|
|
<span class="k">if</span> <span class="nx">@fromNum</span> <span class="o">and</span> <span class="nx">@toNum</span> <span class="o">and</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">abs</span><span class="p">(</span><span class="nx">@fromNum</span> <span class="o">-</span> <span class="nx">@toNum</span><span class="p">)</span> <span class="o"><=</span> <span class="mi">20</span>
|
|
<span class="nv">range = </span><span class="p">[</span><span class="o">+</span><span class="nx">@fromNum</span><span class="p">..</span><span class="o">+</span><span class="nx">@toNum</span><span class="p">]</span>
|
|
<span class="nx">range</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span> <span class="k">if</span> <span class="nx">@exclusive</span>
|
|
<span class="k">return</span> <span class="p">[</span><span class="nx">@makeCode</span> <span class="s">"[</span><span class="si">#{</span> <span class="nx">range</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s">', '</span><span class="p">)</span> <span class="si">}</span><span class="s">]"</span><span class="p">]</span>
|
|
<span class="nv">idt = </span><span class="nx">@tab</span> <span class="o">+</span> <span class="nx">TAB</span>
|
|
<span class="nv">i = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s">'i'</span>
|
|
<span class="nv">result = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s">'results'</span>
|
|
<span class="nv">pre = </span><span class="s">"\n</span><span class="si">#{</span><span class="nx">idt</span><span class="si">}#{</span><span class="nx">result</span><span class="si">}</span><span class="s"> = [];"</span>
|
|
<span class="k">if</span> <span class="nx">@fromNum</span> <span class="o">and</span> <span class="nx">@toNum</span>
|
|
<span class="nv">o.index = </span><span class="nx">i</span>
|
|
<span class="nv">body = </span><span class="nx">fragmentsToText</span> <span class="nx">@compileNode</span> <span class="nx">o</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">vars = </span><span class="s">"</span><span class="si">#{</span><span class="nx">i</span><span class="si">}</span><span class="s"> = </span><span class="si">#{</span><span class="nx">@fromC</span><span class="si">}</span><span class="s">"</span> <span class="o">+</span> <span class="k">if</span> <span class="nx">@toC</span> <span class="o">isnt</span> <span class="nx">@toVar</span> <span class="k">then</span> <span class="s">", </span><span class="si">#{</span><span class="nx">@toC</span><span class="si">}</span><span class="s">"</span> <span class="k">else</span> <span class="s">''</span>
|
|
<span class="nv">cond = </span><span class="s">"</span><span class="si">#{</span><span class="nx">@fromVar</span><span class="si">}</span><span class="s"> <= </span><span class="si">#{</span><span class="nx">@toVar</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="nv">body = </span><span class="s">"var </span><span class="si">#{</span><span class="nx">vars</span><span class="si">}</span><span class="s">; </span><span class="si">#{</span><span class="nx">cond</span><span class="si">}</span><span class="s"> ? </span><span class="si">#{</span><span class="nx">i</span><span class="si">}</span><span class="s"> <</span><span class="si">#{</span><span class="nx">@equals</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="nx">@toVar</span><span class="si">}</span><span class="s"> : </span><span class="si">#{</span><span class="nx">i</span><span class="si">}</span><span class="s"> ></span><span class="si">#{</span><span class="nx">@equals</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="nx">@toVar</span><span class="si">}</span><span class="s">; </span><span class="si">#{</span><span class="nx">cond</span><span class="si">}</span><span class="s"> ? </span><span class="si">#{</span><span class="nx">i</span><span class="si">}</span><span class="s">++ : </span><span class="si">#{</span><span class="nx">i</span><span class="si">}</span><span class="s">--"</span>
|
|
<span class="nv">post = </span><span class="s">"{ </span><span class="si">#{</span><span class="nx">result</span><span class="si">}</span><span class="s">.push(</span><span class="si">#{</span><span class="nx">i</span><span class="si">}</span><span class="s">); }\n</span><span class="si">#{</span><span class="nx">idt</span><span class="si">}</span><span class="s">return </span><span class="si">#{</span><span class="nx">result</span><span class="si">}</span><span class="s">;\n</span><span class="si">#{</span><span class="nx">o</span><span class="p">.</span><span class="nx">indent</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="nv">hasArgs = </span><span class="nf">(node) -></span> <span class="nx">node</span><span class="o">?</span><span class="p">.</span><span class="nx">contains</span> <span class="nf">(n) -></span> <span class="nx">n</span> <span class="k">instanceof</span> <span class="nx">Literal</span> <span class="o">and</span> <span class="nx">n</span><span class="p">.</span><span class="nx">value</span> <span class="o">is</span> <span class="s">'arguments'</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">n</span><span class="p">.</span><span class="nx">asKey</span>
|
|
<span class="nv">args = </span><span class="s">', arguments'</span> <span class="k">if</span> <span class="nx">hasArgs</span><span class="p">(</span><span class="nx">@from</span><span class="p">)</span> <span class="o">or</span> <span class="nx">hasArgs</span><span class="p">(</span><span class="nx">@to</span><span class="p">)</span>
|
|
<span class="p">[</span><span class="nx">@makeCode</span> <span class="s">"(function() {</span><span class="si">#{</span><span class="nx">pre</span><span class="si">}</span><span class="s">\n</span><span class="si">#{</span><span class="nx">idt</span><span class="si">}</span><span class="s">for (</span><span class="si">#{</span><span class="nx">body</span><span class="si">}</span><span class="s">)</span><span class="si">#{</span><span class="nx">post</span><span class="si">}</span><span class="s">}).apply(this</span><span class="si">#{</span><span class="nx">args</span> <span class="o">?</span> <span class="s">''</span><span class="si">}</span><span class="s">)"</span><span class="p">]</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-64">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-64">¶</a>
|
|
</div>
|
|
|
|
<h3>Slice</h3>
|
|
<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><span class="nv">exports.Slice = </span><span class="k">class</span> <span class="nx">Slice</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'range'</span><span class="p">]</span>
|
|
|
|
<span class="nv">constructor: </span><span class="nf">(@range) -></span>
|
|
<span class="k">super</span><span class="p">()</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-65">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-65">¶</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> <span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="p">{</span><span class="nx">to</span><span class="p">,</span> <span class="nx">from</span><span class="p">}</span> <span class="o">=</span> <span class="nx">@range</span>
|
|
<span class="nv">fromCompiled = </span><span class="nx">from</span> <span class="o">and</span> <span class="nx">from</span><span class="p">.</span><span class="nx">compileToFragments</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_PAREN</span><span class="p">)</span> <span class="o">or</span> <span class="p">[</span><span class="nx">@makeCode</span> <span class="s">'0'</span><span class="p">]</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-66">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-66">¶</a>
|
|
</div>
|
|
|
|
<p>TODO: jwalton - move this into the 'if'?
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="k">if</span> <span class="nx">to</span>
|
|
<span class="nv">compiled = </span><span class="nx">to</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_PAREN</span>
|
|
<span class="nv">compiledText = </span><span class="nx">fragmentsToText</span> <span class="nx">compiled</span>
|
|
<span class="k">if</span> <span class="o">not</span> <span class="p">(</span><span class="o">not</span> <span class="nx">@range</span><span class="p">.</span><span class="nx">exclusive</span> <span class="o">and</span> <span class="o">+</span><span class="nx">compiledText</span> <span class="o">is</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
|
|
<span class="nv">toStr = </span><span class="s">', '</span> <span class="o">+</span> <span class="k">if</span> <span class="nx">@range</span><span class="p">.</span><span class="nx">exclusive</span>
|
|
<span class="nx">compiledText</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="nx">SIMPLENUM</span><span class="p">.</span><span class="nx">test</span> <span class="nx">compiledText</span>
|
|
<span class="s">"</span><span class="si">#{</span><span class="o">+</span><span class="nx">compiledText</span> <span class="o">+</span> <span class="mi">1</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">compiled = </span><span class="nx">to</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_ACCESS</span>
|
|
<span class="s">"+</span><span class="si">#{</span><span class="nx">fragmentsToText</span> <span class="nx">compiled</span><span class="si">}</span><span class="s"> + 1 || 9e9"</span>
|
|
<span class="p">[</span><span class="nx">@makeCode</span> <span class="s">".slice(</span><span class="si">#{</span> <span class="nx">fragmentsToText</span> <span class="nx">fromCompiled</span> <span class="si">}#{</span> <span class="nx">toStr</span> <span class="o">or</span> <span class="s">''</span> <span class="si">}</span><span class="s">)"</span><span class="p">]</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-67">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-67">¶</a>
|
|
</div>
|
|
|
|
<h3>Obj</h3>
|
|
<p>An object literal, nothing fancy.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre><span class="nv">exports.Obj = </span><span class="k">class</span> <span class="nx">Obj</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(props, @generated = false) -></span>
|
|
<span class="vi">@objects = @properties = </span><span class="nx">props</span> <span class="o">or</span> <span class="p">[]</span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'properties'</span><span class="p">]</span>
|
|
|
|
<span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="nv">props = </span><span class="nx">@properties</span>
|
|
<span class="k">return</span> <span class="p">[</span><span class="nx">@makeCode</span><span class="p">(</span><span class="k">if</span> <span class="nx">@front</span> <span class="k">then</span> <span class="s">'({})'</span> <span class="k">else</span> <span class="s">'{}'</span><span class="p">)]</span> <span class="k">unless</span> <span class="nx">props</span><span class="p">.</span><span class="nx">length</span>
|
|
<span class="k">if</span> <span class="nx">@generated</span>
|
|
<span class="k">for</span> <span class="nx">node</span> <span class="k">in</span> <span class="nx">props</span> <span class="k">when</span> <span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Value</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">error</span> <span class="s">'cannot have an implicit value in an implicit object'</span>
|
|
<span class="nv">idt = </span><span class="nx">o</span><span class="p">.</span><span class="nx">indent</span> <span class="o">+=</span> <span class="nx">TAB</span>
|
|
<span class="nv">lastNoncom = </span><span class="nx">@lastNonComment</span> <span class="nx">@properties</span>
|
|
<span class="nv">answer = </span><span class="p">[]</span>
|
|
<span class="k">for</span> <span class="nx">prop</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">props</span>
|
|
<span class="nv">join = </span><span class="k">if</span> <span class="nx">i</span> <span class="o">is</span> <span class="nx">props</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
|
|
<span class="s">''</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="nx">prop</span> <span class="o">is</span> <span class="nx">lastNoncom</span> <span class="o">or</span> <span class="nx">prop</span> <span class="k">instanceof</span> <span class="nx">Comment</span>
|
|
<span class="s">'\n'</span>
|
|
<span class="k">else</span>
|
|
<span class="s">',\n'</span>
|
|
<span class="nv">indent = </span><span class="k">if</span> <span class="nx">prop</span> <span class="k">instanceof</span> <span class="nx">Comment</span> <span class="k">then</span> <span class="s">''</span> <span class="k">else</span> <span class="nx">idt</span>
|
|
<span class="k">if</span> <span class="nx">prop</span> <span class="k">instanceof</span> <span class="nx">Assign</span> <span class="o">and</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">variable</span> <span class="k">instanceof</span> <span class="nx">Value</span> <span class="o">and</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">variable</span><span class="p">.</span><span class="nx">hasProperties</span><span class="p">()</span>
|
|
<span class="k">throw</span> <span class="k">new</span> <span class="nx">SyntaxError</span> <span class="s">'Invalid object key'</span>
|
|
<span class="k">if</span> <span class="nx">prop</span> <span class="k">instanceof</span> <span class="nx">Value</span> <span class="o">and</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">this</span>
|
|
<span class="nv">prop = </span><span class="k">new</span> <span class="nx">Assign</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">properties</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">name</span><span class="p">,</span> <span class="nx">prop</span><span class="p">,</span> <span class="s">'object'</span>
|
|
<span class="k">if</span> <span class="nx">prop</span> <span class="o">not</span> <span class="k">instanceof</span> <span class="nx">Comment</span>
|
|
<span class="k">if</span> <span class="nx">prop</span> <span class="o">not</span> <span class="k">instanceof</span> <span class="nx">Assign</span>
|
|
<span class="nv">prop = </span><span class="k">new</span> <span class="nx">Assign</span> <span class="nx">prop</span><span class="p">,</span> <span class="nx">prop</span><span class="p">,</span> <span class="s">'object'</span>
|
|
<span class="p">(</span><span class="nx">prop</span><span class="p">.</span><span class="nx">variable</span><span class="p">.</span><span class="nx">base</span> <span class="o">or</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">variable</span><span class="p">).</span><span class="nv">asKey = </span><span class="kc">yes</span>
|
|
<span class="k">if</span> <span class="nx">indent</span> <span class="k">then</span> <span class="nx">answer</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="nx">indent</span>
|
|
<span class="nx">answer</span><span class="p">.</span><span class="nx">push</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">compileToFragments</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_TOP</span><span class="p">)...</span>
|
|
<span class="k">if</span> <span class="nx">join</span> <span class="k">then</span> <span class="nx">answer</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="nx">join</span>
|
|
<span class="nx">answer</span><span class="p">.</span><span class="nx">unshift</span> <span class="nx">@makeCode</span> <span class="s">"{</span><span class="si">#{</span> <span class="nx">props</span><span class="p">.</span><span class="nx">length</span> <span class="o">and</span> <span class="s">'\n'</span> <span class="si">}</span><span class="s">"</span>
|
|
<span class="nx">answer</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="s">"</span><span class="si">#{</span> <span class="nx">props</span><span class="p">.</span><span class="nx">length</span> <span class="o">and</span> <span class="s">'\n'</span> <span class="o">+</span> <span class="nx">@tab</span> <span class="si">}</span><span class="s">}"</span>
|
|
<span class="k">if</span> <span class="nx">@front</span> <span class="k">then</span> <span class="nx">@wrapInBraces</span> <span class="nx">answer</span> <span class="k">else</span> <span class="nx">answer</span>
|
|
|
|
<span class="nv">assigns: </span><span class="nf">(name) -></span>
|
|
<span class="k">for</span> <span class="nx">prop</span> <span class="k">in</span> <span class="nx">@properties</span> <span class="k">when</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">assigns</span> <span class="nx">name</span> <span class="k">then</span> <span class="k">return</span> <span class="kc">yes</span>
|
|
<span class="kc">no</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-68">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-68">¶</a>
|
|
</div>
|
|
|
|
<h3>Arr</h3>
|
|
<p>An array literal.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre><span class="nv">exports.Arr = </span><span class="k">class</span> <span class="nx">Arr</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(objs) -></span>
|
|
<span class="vi">@objects = </span><span class="nx">objs</span> <span class="o">or</span> <span class="p">[]</span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'objects'</span><span class="p">]</span>
|
|
|
|
<span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="k">return</span> <span class="p">[</span><span class="nx">@makeCode</span> <span class="s">'[]'</span><span class="p">]</span> <span class="k">unless</span> <span class="nx">@objects</span><span class="p">.</span><span class="nx">length</span>
|
|
<span class="nx">o</span><span class="p">.</span><span class="nx">indent</span> <span class="o">+=</span> <span class="nx">TAB</span>
|
|
<span class="nv">answer = </span><span class="nx">Splat</span><span class="p">.</span><span class="nx">compileSplattedArray</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">@objects</span>
|
|
<span class="k">return</span> <span class="nx">answer</span> <span class="k">if</span> <span class="nx">answer</span><span class="p">.</span><span class="nx">length</span>
|
|
|
|
<span class="nv">answer = </span><span class="p">[]</span>
|
|
<span class="nv">compiledObjs = </span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span> <span class="k">for</span> <span class="nx">obj</span> <span class="k">in</span> <span class="nx">@objects</span><span class="p">)</span>
|
|
<span class="k">for</span> <span class="nx">fragments</span><span class="p">,</span> <span class="nx">index</span> <span class="k">in</span> <span class="nx">compiledObjs</span>
|
|
<span class="k">if</span> <span class="nx">index</span>
|
|
<span class="nx">answer</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="s">", "</span>
|
|
<span class="nx">answer</span><span class="p">.</span><span class="nx">push</span> <span class="nx">fragments</span><span class="p">...</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">fragmentsToText</span> <span class="nx">answer</span><span class="p">).</span><span class="nx">indexOf</span><span class="p">(</span><span class="s">'\n'</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span>
|
|
<span class="nx">answer</span><span class="p">.</span><span class="nx">unshift</span> <span class="nx">@makeCode</span> <span class="s">"[\n</span><span class="si">#{</span><span class="nx">o</span><span class="p">.</span><span class="nx">indent</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="nx">answer</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="s">"\n</span><span class="si">#{</span><span class="nx">@tab</span><span class="si">}</span><span class="s">]"</span>
|
|
<span class="k">else</span>
|
|
<span class="nx">answer</span><span class="p">.</span><span class="nx">unshift</span> <span class="nx">@makeCode</span> <span class="s">"["</span>
|
|
<span class="nx">answer</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="s">"]"</span>
|
|
<span class="nx">answer</span>
|
|
|
|
<span class="nv">assigns: </span><span class="nf">(name) -></span>
|
|
<span class="k">for</span> <span class="nx">obj</span> <span class="k">in</span> <span class="nx">@objects</span> <span class="k">when</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">assigns</span> <span class="nx">name</span> <span class="k">then</span> <span class="k">return</span> <span class="kc">yes</span>
|
|
<span class="kc">no</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-69">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-69">¶</a>
|
|
</div>
|
|
|
|
<h3>Class</h3>
|
|
<p>The CoffeeScript class definition.
|
|
Initialize a <strong>Class</strong> with its name, an optional superclass, and a
|
|
list of prototype property assignments.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre><span class="nv">exports.Class = </span><span class="k">class</span> <span class="nx">Class</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(@variable, @parent, @body = new Block) -></span>
|
|
<span class="vi">@boundFuncs = </span><span class="p">[]</span>
|
|
<span class="vi">@body.classBody = </span><span class="kc">yes</span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'variable'</span><span class="p">,</span> <span class="s">'parent'</span><span class="p">,</span> <span class="s">'body'</span><span class="p">]</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-70">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-70">¶</a>
|
|
</div>
|
|
|
|
<p>Figure out the appropriate name for the constructor function of this class.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">determineName: </span><span class="nf">-></span>
|
|
<span class="k">return</span> <span class="kc">null</span> <span class="k">unless</span> <span class="nx">@variable</span>
|
|
<span class="nv">decl = </span><span class="k">if</span> <span class="nv">tail = </span><span class="nx">last</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">properties</span>
|
|
<span class="nx">tail</span> <span class="k">instanceof</span> <span class="nx">Access</span> <span class="o">and</span> <span class="nx">tail</span><span class="p">.</span><span class="nx">name</span><span class="p">.</span><span class="nx">value</span>
|
|
<span class="k">else</span>
|
|
<span class="nx">@variable</span><span class="p">.</span><span class="nx">base</span><span class="p">.</span><span class="nx">value</span>
|
|
<span class="k">if</span> <span class="nx">decl</span> <span class="k">in</span> <span class="nx">STRICT_PROSCRIBED</span>
|
|
<span class="nx">@variable</span><span class="p">.</span><span class="nx">error</span> <span class="s">"class variable name may not be </span><span class="si">#{</span><span class="nx">decl</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="nx">decl</span> <span class="o">and=</span> <span class="nx">IDENTIFIER</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">decl</span><span class="p">)</span> <span class="o">and</span> <span class="nx">decl</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-71">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-71">¶</a>
|
|
</div>
|
|
|
|
<p>For all <code>this</code>-references and bound functions in the class definition,
|
|
<code>this</code> is the Class being constructed.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">setContext: </span><span class="nf">(name) -></span>
|
|
<span class="nx">@body</span><span class="p">.</span><span class="nx">traverseChildren</span> <span class="kc">false</span><span class="p">,</span> <span class="nf">(node) -></span>
|
|
<span class="k">return</span> <span class="kc">false</span> <span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">classBody</span>
|
|
<span class="k">if</span> <span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Literal</span> <span class="o">and</span> <span class="nx">node</span><span class="p">.</span><span class="nx">value</span> <span class="o">is</span> <span class="s">'this'</span>
|
|
<span class="nv">node.value = </span><span class="nx">name</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Code</span>
|
|
<span class="nv">node.klass = </span><span class="nx">name</span>
|
|
<span class="nv">node.context = </span><span class="nx">name</span> <span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">bound</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-72">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-72">¶</a>
|
|
</div>
|
|
|
|
<p>Ensure that all functions bound to the instance are proxied in the
|
|
constructor.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">addBoundFunctions: </span><span class="nf">(o) -></span>
|
|
<span class="k">for</span> <span class="nx">bvar</span> <span class="k">in</span> <span class="nx">@boundFuncs</span>
|
|
<span class="nv">lhs = </span><span class="p">(</span><span class="k">new</span> <span class="nx">Value</span> <span class="p">(</span><span class="k">new</span> <span class="nx">Literal</span> <span class="s">"this"</span><span class="p">),</span> <span class="p">[</span><span class="k">new</span> <span class="nx">Access</span> <span class="nx">bvar</span><span class="p">]).</span><span class="nx">compile</span> <span class="nx">o</span>
|
|
<span class="nx">@ctor</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">unshift</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">"</span><span class="si">#{</span><span class="nx">lhs</span><span class="si">}</span><span class="s"> = </span><span class="si">#{</span><span class="nx">utility</span> <span class="s">'bind'</span><span class="si">}</span><span class="s">(</span><span class="si">#{</span><span class="nx">lhs</span><span class="si">}</span><span class="s">, this)"</span>
|
|
<span class="k">return</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-73">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-73">¶</a>
|
|
</div>
|
|
|
|
<p>Merge the properties from a top-level object as prototypal properties
|
|
on the class.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">addProperties: </span><span class="nf">(node, name, o) -></span>
|
|
<span class="nv">props = </span><span class="nx">node</span><span class="p">.</span><span class="nx">base</span><span class="p">.</span><span class="nx">properties</span><span class="p">[..]</span>
|
|
<span class="nv">exprs = </span><span class="k">while</span> <span class="nv">assign = </span><span class="nx">props</span><span class="p">.</span><span class="nx">shift</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="nx">assign</span> <span class="k">instanceof</span> <span class="nx">Assign</span>
|
|
<span class="nv">base = </span><span class="nx">assign</span><span class="p">.</span><span class="nx">variable</span><span class="p">.</span><span class="nx">base</span>
|
|
<span class="k">delete</span> <span class="nx">assign</span><span class="p">.</span><span class="nx">context</span>
|
|
<span class="nv">func = </span><span class="nx">assign</span><span class="p">.</span><span class="nx">value</span>
|
|
<span class="k">if</span> <span class="nx">base</span><span class="p">.</span><span class="nx">value</span> <span class="o">is</span> <span class="s">'constructor'</span>
|
|
<span class="k">if</span> <span class="nx">@ctor</span>
|
|
<span class="nx">assign</span><span class="p">.</span><span class="nx">error</span> <span class="s">'cannot define more than one constructor in a class'</span>
|
|
<span class="k">if</span> <span class="nx">func</span><span class="p">.</span><span class="nx">bound</span>
|
|
<span class="nx">assign</span><span class="p">.</span><span class="nx">error</span> <span class="s">'cannot define a constructor as a bound function'</span>
|
|
<span class="k">if</span> <span class="nx">func</span> <span class="k">instanceof</span> <span class="nx">Code</span>
|
|
<span class="nv">assign = </span><span class="vi">@ctor = </span><span class="nx">func</span>
|
|
<span class="k">else</span>
|
|
<span class="vi">@externalCtor = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s">'class'</span>
|
|
<span class="nv">assign = </span><span class="k">new</span> <span class="nx">Assign</span> <span class="k">new</span> <span class="nx">Literal</span><span class="p">(</span><span class="nx">@externalCtor</span><span class="p">),</span> <span class="nx">func</span>
|
|
<span class="k">else</span>
|
|
<span class="k">if</span> <span class="nx">assign</span><span class="p">.</span><span class="nx">variable</span><span class="p">.</span><span class="nx">this</span>
|
|
<span class="nv">func.static = </span><span class="kc">yes</span>
|
|
<span class="k">if</span> <span class="nx">func</span><span class="p">.</span><span class="nx">bound</span>
|
|
<span class="nv">func.context = </span><span class="nx">name</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">assign.variable = </span><span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="k">new</span> <span class="nx">Literal</span><span class="p">(</span><span class="nx">name</span><span class="p">),</span> <span class="p">[(</span><span class="k">new</span> <span class="nx">Access</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">'prototype'</span><span class="p">),</span> <span class="k">new</span> <span class="nx">Access</span> <span class="nx">base</span> <span class="p">])</span>
|
|
<span class="k">if</span> <span class="nx">func</span> <span class="k">instanceof</span> <span class="nx">Code</span> <span class="o">and</span> <span class="nx">func</span><span class="p">.</span><span class="nx">bound</span>
|
|
<span class="nx">@boundFuncs</span><span class="p">.</span><span class="nx">push</span> <span class="nx">base</span>
|
|
<span class="nv">func.bound = </span><span class="kc">no</span>
|
|
<span class="nx">assign</span>
|
|
<span class="nx">compact</span> <span class="nx">exprs</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-74">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-74">¶</a>
|
|
</div>
|
|
|
|
<p>Walk the body of the class, looking for prototype properties to be converted.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">walkBody: </span><span class="nf">(name, o) -></span>
|
|
<span class="nx">@traverseChildren</span> <span class="kc">false</span><span class="p">,</span> <span class="nf">(child) =></span>
|
|
<span class="nv">cont = </span><span class="kc">true</span>
|
|
<span class="k">return</span> <span class="kc">false</span> <span class="k">if</span> <span class="nx">child</span> <span class="k">instanceof</span> <span class="nx">Class</span>
|
|
<span class="k">if</span> <span class="nx">child</span> <span class="k">instanceof</span> <span class="nx">Block</span>
|
|
<span class="k">for</span> <span class="nx">node</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nv">exps = </span><span class="nx">child</span><span class="p">.</span><span class="nx">expressions</span>
|
|
<span class="k">if</span> <span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Value</span> <span class="o">and</span> <span class="nx">node</span><span class="p">.</span><span class="nx">isObject</span><span class="p">(</span><span class="kc">true</span><span class="p">)</span>
|
|
<span class="nv">cont = </span><span class="kc">false</span>
|
|
<span class="nx">exps</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@addProperties</span> <span class="nx">node</span><span class="p">,</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">o</span>
|
|
<span class="nv">child.expressions = exps = </span><span class="nx">flatten</span> <span class="nx">exps</span>
|
|
<span class="nx">cont</span> <span class="o">and</span> <span class="nx">child</span> <span class="o">not</span> <span class="k">instanceof</span> <span class="nx">Class</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-75">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-75">¶</a>
|
|
</div>
|
|
|
|
<p><code>use strict</code> (and other directives) must be the first expression statement(s)
|
|
of a function body. This method ensures the prologue is correctly positioned
|
|
above the <code>constructor</code>.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">hoistDirectivePrologue: </span><span class="nf">-></span>
|
|
<span class="nv">index = </span><span class="mi">0</span>
|
|
<span class="p">{</span><span class="nx">expressions</span><span class="p">}</span> <span class="o">=</span> <span class="nx">@body</span>
|
|
<span class="o">++</span><span class="nx">index</span> <span class="k">while</span> <span class="p">(</span><span class="nv">node = </span><span class="nx">expressions</span><span class="p">[</span><span class="nx">index</span><span class="p">])</span> <span class="o">and</span> <span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Comment</span> <span class="o">or</span>
|
|
<span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Value</span> <span class="o">and</span> <span class="nx">node</span><span class="p">.</span><span class="nx">isString</span><span class="p">()</span>
|
|
<span class="vi">@directives = </span><span class="nx">expressions</span><span class="p">.</span><span class="nx">splice</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">index</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-76">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-76">¶</a>
|
|
</div>
|
|
|
|
<p>Make sure that a constructor is defined for the class, and properly
|
|
configured.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">ensureConstructor: </span><span class="nf">(name, o) -></span>
|
|
<span class="nv">missing = </span><span class="o">not</span> <span class="nx">@ctor</span>
|
|
<span class="nx">@ctor</span> <span class="o">or=</span> <span class="k">new</span> <span class="nx">Code</span>
|
|
<span class="vi">@ctor.ctor = @ctor.name = </span><span class="nx">name</span>
|
|
<span class="vi">@ctor.klass = </span><span class="kc">null</span>
|
|
<span class="vi">@ctor.noReturn = </span><span class="kc">yes</span>
|
|
<span class="k">if</span> <span class="nx">missing</span>
|
|
<span class="nv">superCall = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="s">"</span><span class="si">#{</span><span class="nx">name</span><span class="si">}</span><span class="s">.__super__.constructor.apply(this, arguments)"</span> <span class="k">if</span> <span class="nx">@parent</span>
|
|
<span class="nv">superCall = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="s">"</span><span class="si">#{</span><span class="nx">@externalCtor</span><span class="si">}</span><span class="s">.apply(this, arguments)"</span> <span class="k">if</span> <span class="nx">@externalCtor</span>
|
|
<span class="k">if</span> <span class="nx">superCall</span>
|
|
<span class="nv">ref = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s">'ref'</span>
|
|
<span class="nx">@ctor</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">unshift</span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">ref</span><span class="p">,</span> <span class="nx">superCall</span>
|
|
<span class="nx">@addBoundFunctions</span> <span class="nx">o</span>
|
|
<span class="k">if</span> <span class="nx">superCall</span>
|
|
<span class="nx">@ctor</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">push</span> <span class="nx">ref</span>
|
|
<span class="nx">@ctor</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">makeReturn</span><span class="p">()</span>
|
|
<span class="nx">@body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">unshift</span> <span class="nx">@ctor</span>
|
|
<span class="k">else</span>
|
|
<span class="nx">@addBoundFunctions</span> <span class="nx">o</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-77">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-77">¶</a>
|
|
</div>
|
|
|
|
<p>Instead of generating the JavaScript string directly, we build up the
|
|
equivalent syntax tree and compile that, in pieces. You can see the
|
|
constructor, property assignments, and inheritance getting built out below.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="nv">decl = </span><span class="nx">@determineName</span><span class="p">()</span>
|
|
<span class="nv">name = </span><span class="nx">decl</span> <span class="o">or</span> <span class="s">'_Class'</span>
|
|
<span class="nv">name = </span><span class="s">"_</span><span class="si">#{</span><span class="nx">name</span><span class="si">}</span><span class="s">"</span> <span class="k">if</span> <span class="nx">name</span><span class="p">.</span><span class="nx">reserved</span>
|
|
<span class="nv">lname = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">name</span>
|
|
|
|
<span class="nx">@hoistDirectivePrologue</span><span class="p">()</span>
|
|
<span class="nx">@setContext</span> <span class="nx">name</span>
|
|
<span class="nx">@walkBody</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">o</span>
|
|
<span class="nx">@ensureConstructor</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">o</span>
|
|
<span class="vi">@body.spaced = </span><span class="kc">yes</span>
|
|
<span class="nx">@body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">unshift</span> <span class="nx">@ctor</span> <span class="k">unless</span> <span class="nx">@ctor</span> <span class="k">instanceof</span> <span class="nx">Code</span>
|
|
<span class="nx">@body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">push</span> <span class="nx">lname</span>
|
|
<span class="nx">@body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">unshift</span> <span class="nx">@directives</span><span class="p">...</span>
|
|
|
|
<span class="nv">call = </span><span class="nx">Closure</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">@body</span>
|
|
|
|
<span class="k">if</span> <span class="nx">@parent</span>
|
|
<span class="vi">@superClass = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s">'super'</span><span class="p">,</span> <span class="kc">no</span>
|
|
<span class="nx">@body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">unshift</span> <span class="k">new</span> <span class="nx">Extends</span> <span class="nx">lname</span><span class="p">,</span> <span class="nx">@superClass</span>
|
|
<span class="nx">call</span><span class="p">.</span><span class="nx">args</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@parent</span>
|
|
<span class="nv">params = </span><span class="nx">call</span><span class="p">.</span><span class="nx">variable</span><span class="p">.</span><span class="nx">params</span> <span class="o">or</span> <span class="nx">call</span><span class="p">.</span><span class="nx">variable</span><span class="p">.</span><span class="nx">base</span><span class="p">.</span><span class="nx">params</span>
|
|
<span class="nx">params</span><span class="p">.</span><span class="nx">push</span> <span class="k">new</span> <span class="nx">Param</span> <span class="nx">@superClass</span>
|
|
|
|
<span class="nv">klass = </span><span class="k">new</span> <span class="nx">Parens</span> <span class="nx">call</span><span class="p">,</span> <span class="kc">yes</span>
|
|
<span class="nv">klass = </span><span class="k">new</span> <span class="nx">Assign</span> <span class="nx">@variable</span><span class="p">,</span> <span class="nx">klass</span> <span class="k">if</span> <span class="nx">@variable</span>
|
|
<span class="nx">klass</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-78">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-78">¶</a>
|
|
</div>
|
|
|
|
<h3>Assign</h3>
|
|
<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><span class="nv">exports.Assign = </span><span class="k">class</span> <span class="nx">Assign</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(@variable, @value, @context, options) -></span>
|
|
<span class="vi">@param = </span><span class="nx">options</span> <span class="o">and</span> <span class="nx">options</span><span class="p">.</span><span class="nx">param</span>
|
|
<span class="vi">@subpattern = </span><span class="nx">options</span> <span class="o">and</span> <span class="nx">options</span><span class="p">.</span><span class="nx">subpattern</span>
|
|
<span class="nv">forbidden = </span><span class="p">(</span><span class="nv">name = </span><span class="nx">@variable</span><span class="p">.</span><span class="nx">unwrapAll</span><span class="p">().</span><span class="nx">value</span><span class="p">)</span> <span class="k">in</span> <span class="nx">STRICT_PROSCRIBED</span>
|
|
<span class="k">if</span> <span class="nx">forbidden</span> <span class="o">and</span> <span class="nx">@context</span> <span class="o">isnt</span> <span class="s">'object'</span>
|
|
<span class="nx">@variable</span><span class="p">.</span><span class="nx">error</span> <span class="s">"variable name may not be \"</span><span class="si">#{</span><span class="nx">name</span><span class="si">}</span><span class="s">\""</span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'variable'</span><span class="p">,</span> <span class="s">'value'</span><span class="p">]</span>
|
|
|
|
<span class="nv">isStatement: </span><span class="nf">(o) -></span>
|
|
<span class="nx">o</span><span class="o">?</span><span class="p">.</span><span class="nx">level</span> <span class="o">is</span> <span class="nx">LEVEL_TOP</span> <span class="o">and</span> <span class="nx">@context</span><span class="o">?</span> <span class="o">and</span> <span class="s">"?"</span> <span class="k">in</span> <span class="nx">@context</span>
|
|
|
|
<span class="nv">assigns: </span><span class="nf">(name) -></span>
|
|
<span class="nx">@</span><span class="p">[</span><span class="k">if</span> <span class="nx">@context</span> <span class="o">is</span> <span class="s">'object'</span> <span class="k">then</span> <span class="s">'value'</span> <span class="k">else</span> <span class="s">'variable'</span><span class="p">].</span><span class="nx">assigns</span> <span class="nx">name</span>
|
|
|
|
<span class="nv">unfoldSoak: </span><span class="nf">(o) -></span>
|
|
<span class="nx">unfoldSoak</span> <span class="nx">o</span><span class="p">,</span> <span class="k">this</span><span class="p">,</span> <span class="s">'variable'</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-79">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-79">¶</a>
|
|
</div>
|
|
|
|
<p>Compile an assignment, delegating to <code>compilePatternMatch</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> <span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="k">if</span> <span class="nv">isValue = </span><span class="nx">@variable</span> <span class="k">instanceof</span> <span class="nx">Value</span>
|
|
<span class="k">return</span> <span class="nx">@compilePatternMatch</span> <span class="nx">o</span> <span class="k">if</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">isArray</span><span class="p">()</span> <span class="o">or</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">isObject</span><span class="p">()</span>
|
|
<span class="k">return</span> <span class="nx">@compileSplice</span> <span class="nx">o</span> <span class="k">if</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">isSplice</span><span class="p">()</span>
|
|
<span class="k">return</span> <span class="nx">@compileConditional</span> <span class="nx">o</span> <span class="k">if</span> <span class="nx">@context</span> <span class="k">in</span> <span class="p">[</span><span class="s">'||='</span><span class="p">,</span> <span class="s">'&&='</span><span class="p">,</span> <span class="s">'?='</span><span class="p">]</span>
|
|
<span class="nv">compiledName = </span><span class="nx">@variable</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
|
|
<span class="nv">name = </span><span class="nx">fragmentsToText</span> <span class="nx">compiledName</span>
|
|
<span class="k">unless</span> <span class="nx">@context</span>
|
|
<span class="nv">varBase = </span><span class="nx">@variable</span><span class="p">.</span><span class="nx">unwrapAll</span><span class="p">()</span>
|
|
<span class="k">unless</span> <span class="nx">varBase</span><span class="p">.</span><span class="nx">isAssignable</span><span class="p">()</span>
|
|
<span class="nx">@variable</span><span class="p">.</span><span class="nx">error</span> <span class="s">"\"</span><span class="si">#{</span><span class="nx">@variable</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="si">}</span><span class="s">\" cannot be assigned"</span>
|
|
<span class="k">unless</span> <span class="nx">varBase</span><span class="p">.</span><span class="nx">hasProperties</span><span class="o">?</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="nx">@param</span>
|
|
<span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">add</span> <span class="nx">name</span><span class="p">,</span> <span class="s">'var'</span>
|
|
<span class="k">else</span>
|
|
<span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">find</span> <span class="nx">name</span>
|
|
<span class="k">if</span> <span class="nx">@value</span> <span class="k">instanceof</span> <span class="nx">Code</span> <span class="o">and</span> <span class="nv">match = </span><span class="nx">METHOD_DEF</span><span class="p">.</span><span class="nx">exec</span> <span class="nx">name</span>
|
|
<span class="vi">@value.klass = </span><span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">if</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
|
<span class="vi">@value.name = </span><span class="nx">match</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">?</span> <span class="nx">match</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">?</span> <span class="nx">match</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">?</span> <span class="nx">match</span><span class="p">[</span><span class="mi">5</span><span class="p">]</span>
|
|
<span class="nv">val = </span><span class="nx">@value</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
|
|
<span class="k">return</span> <span class="p">(</span><span class="nx">compiledName</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">": "</span><span class="p">),</span> <span class="nx">val</span><span class="p">)</span> <span class="k">if</span> <span class="nx">@context</span> <span class="o">is</span> <span class="s">'object'</span>
|
|
<span class="nv">answer = </span><span class="nx">compiledName</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">" </span><span class="si">#{</span> <span class="nx">@context</span> <span class="o">or</span> <span class="s">'='</span> <span class="si">}</span><span class="s"> "</span><span class="p">),</span> <span class="nx">val</span>
|
|
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o"><=</span> <span class="nx">LEVEL_LIST</span> <span class="k">then</span> <span class="nx">answer</span> <span class="k">else</span> <span class="nx">@wrapInBraces</span> <span class="nx">answer</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-80">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-80">¶</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.
|
|
See the <a href="http://wiki.ecmascript.org/doku.php?id=harmony:destructuring">ECMAScript Harmony Wiki</a>
|
|
for details.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">compilePatternMatch: </span><span class="nf">(o) -></span>
|
|
<span class="nv">top = </span><span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">is</span> <span class="nx">LEVEL_TOP</span>
|
|
<span class="p">{</span><span class="nx">value</span><span class="p">}</span> <span class="o">=</span> <span class="k">this</span>
|
|
<span class="p">{</span><span class="nx">objects</span><span class="p">}</span> <span class="o">=</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">base</span>
|
|
<span class="k">unless</span> <span class="nv">olen = </span><span class="nx">objects</span><span class="p">.</span><span class="nx">length</span>
|
|
<span class="nv">code = </span><span class="nx">value</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span>
|
|
<span class="k">return</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">>=</span> <span class="nx">LEVEL_OP</span> <span class="k">then</span> <span class="nx">@wrapInBraces</span> <span class="nx">code</span> <span class="k">else</span> <span class="nx">code</span>
|
|
<span class="nv">isObject = </span><span class="nx">@variable</span><span class="p">.</span><span class="nx">isObject</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="nx">top</span> <span class="o">and</span> <span class="nx">olen</span> <span class="o">is</span> <span class="mi">1</span> <span class="o">and</span> <span class="p">(</span><span class="nv">obj = </span><span class="nx">objects</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">not</span> <span class="k">instanceof</span> <span class="nx">Splat</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-81">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-81">¶</a>
|
|
</div>
|
|
|
|
<p>Unroll simplest cases: <code>{v} = x</code> -> <code>v = x.v</code>
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="k">if</span> <span class="nx">obj</span> <span class="k">instanceof</span> <span class="nx">Assign</span>
|
|
<span class="p">{</span><span class="nv">variable: </span><span class="p">{</span><span class="nv">base: </span><span class="nx">idx</span><span class="p">},</span> <span class="nv">value: </span><span class="nx">obj</span><span class="p">}</span> <span class="o">=</span> <span class="nx">obj</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">idx = </span><span class="k">if</span> <span class="nx">isObject</span>
|
|
<span class="k">if</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">this</span> <span class="k">then</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">properties</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">name</span> <span class="k">else</span> <span class="nx">obj</span>
|
|
<span class="k">else</span>
|
|
<span class="k">new</span> <span class="nx">Literal</span> <span class="mi">0</span>
|
|
<span class="nv">acc = </span><span class="nx">IDENTIFIER</span><span class="p">.</span><span class="nx">test</span> <span class="nx">idx</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">().</span><span class="nx">value</span> <span class="o">or</span> <span class="mi">0</span>
|
|
<span class="nv">value = </span><span class="k">new</span> <span class="nx">Value</span> <span class="nx">value</span>
|
|
<span class="nx">value</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">push</span> <span class="k">new</span> <span class="p">(</span><span class="k">if</span> <span class="nx">acc</span> <span class="k">then</span> <span class="nx">Access</span> <span class="k">else</span> <span class="nx">Index</span><span class="p">)</span> <span class="nx">idx</span>
|
|
<span class="k">if</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">().</span><span class="nx">value</span> <span class="k">in</span> <span class="nx">RESERVED</span>
|
|
<span class="nx">obj</span><span class="p">.</span><span class="nx">error</span> <span class="s">"assignment to a reserved word: </span><span class="si">#{</span><span class="nx">obj</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="k">return</span> <span class="k">new</span> <span class="nx">Assign</span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">value</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nv">param: </span><span class="nx">@param</span><span class="p">).</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_TOP</span>
|
|
<span class="nv">vvar = </span><span class="nx">value</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
|
|
<span class="nv">vvarText = </span><span class="nx">fragmentsToText</span> <span class="nx">vvar</span>
|
|
<span class="nv">assigns = </span><span class="p">[]</span>
|
|
<span class="nv">splat = </span><span class="kc">false</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-82">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-82">¶</a>
|
|
</div>
|
|
|
|
<p>Make vvar into a simple variable if it isn't already.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="k">if</span> <span class="o">not</span> <span class="nx">IDENTIFIER</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">vvarText</span><span class="p">)</span> <span class="o">or</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">assigns</span><span class="p">(</span><span class="nx">vvarText</span><span class="p">)</span>
|
|
<span class="nx">assigns</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="nx">@makeCode</span><span class="p">(</span><span class="s">"</span><span class="si">#{</span> <span class="nv">ref = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s">'ref'</span> <span class="si">}</span><span class="s"> = "</span><span class="p">),</span> <span class="nx">vvar</span><span class="p">...]</span>
|
|
<span class="nv">vvar = </span><span class="p">[</span><span class="nx">@makeCode</span> <span class="nx">ref</span><span class="p">]</span>
|
|
<span class="nv">vvarText = </span><span class="nx">ref</span>
|
|
<span class="k">for</span> <span class="nx">obj</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">objects</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-83">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-83">¶</a>
|
|
</div>
|
|
|
|
<p>A regular array pattern-match.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">idx = </span><span class="nx">i</span>
|
|
<span class="k">if</span> <span class="nx">isObject</span>
|
|
<span class="k">if</span> <span class="nx">obj</span> <span class="k">instanceof</span> <span class="nx">Assign</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-84">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-84">¶</a>
|
|
</div>
|
|
|
|
<p>A regular object pattern-match.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="p">{</span><span class="nv">variable: </span><span class="p">{</span><span class="nv">base: </span><span class="nx">idx</span><span class="p">},</span> <span class="nv">value: </span><span class="nx">obj</span><span class="p">}</span> <span class="o">=</span> <span class="nx">obj</span>
|
|
<span class="k">else</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-85">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-85">¶</a>
|
|
</div>
|
|
|
|
<p>A shorthand <code>{a, b, @c} = val</code> pattern-match.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="k">if</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">base</span> <span class="k">instanceof</span> <span class="nx">Parens</span>
|
|
<span class="p">[</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">idx</span><span class="p">]</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">unwrapAll</span><span class="p">()).</span><span class="nx">cacheReference</span> <span class="nx">o</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">idx = </span><span class="k">if</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">this</span> <span class="k">then</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">properties</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">name</span> <span class="k">else</span> <span class="nx">obj</span>
|
|
<span class="k">if</span> <span class="o">not</span> <span class="nx">splat</span> <span class="o">and</span> <span class="nx">obj</span> <span class="k">instanceof</span> <span class="nx">Splat</span>
|
|
<span class="nv">name = </span><span class="nx">obj</span><span class="p">.</span><span class="nx">name</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">().</span><span class="nx">value</span>
|
|
<span class="nv">obj = </span><span class="nx">obj</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span>
|
|
<span class="nv">val = </span><span class="s">"</span><span class="si">#{</span><span class="nx">olen</span><span class="si">}</span><span class="s"> <= </span><span class="si">#{</span><span class="nx">vvarText</span><span class="si">}</span><span class="s">.length ? </span><span class="si">#{</span> <span class="nx">utility</span> <span class="s">'slice'</span> <span class="si">}</span><span class="s">.call(</span><span class="si">#{</span><span class="nx">vvarText</span><span class="si">}</span><span class="s">, </span><span class="si">#{</span><span class="nx">i</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="k">if</span> <span class="nv">rest = </span><span class="nx">olen</span> <span class="o">-</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span>
|
|
<span class="nv">ivar = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s">'i'</span>
|
|
<span class="nx">val</span> <span class="o">+=</span> <span class="s">", </span><span class="si">#{</span><span class="nx">ivar</span><span class="si">}</span><span class="s"> = </span><span class="si">#{</span><span class="nx">vvarText</span><span class="si">}</span><span class="s">.length - </span><span class="si">#{</span><span class="nx">rest</span><span class="si">}</span><span class="s">) : (</span><span class="si">#{</span><span class="nx">ivar</span><span class="si">}</span><span class="s"> = </span><span class="si">#{</span><span class="nx">i</span><span class="si">}</span><span class="s">, [])"</span>
|
|
<span class="k">else</span>
|
|
<span class="nx">val</span> <span class="o">+=</span> <span class="s">") : []"</span>
|
|
<span class="nv">val = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">val</span>
|
|
<span class="nv">splat = </span><span class="s">"</span><span class="si">#{</span><span class="nx">ivar</span><span class="si">}</span><span class="s">++"</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">name = </span><span class="nx">obj</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">().</span><span class="nx">value</span>
|
|
<span class="k">if</span> <span class="nx">obj</span> <span class="k">instanceof</span> <span class="nx">Splat</span>
|
|
<span class="nx">obj</span><span class="p">.</span><span class="nx">error</span> <span class="s">"multiple splats are disallowed in an assignment"</span>
|
|
<span class="k">if</span> <span class="k">typeof</span> <span class="nx">idx</span> <span class="o">is</span> <span class="s">'number'</span>
|
|
<span class="nv">idx = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">splat</span> <span class="o">or</span> <span class="nx">idx</span>
|
|
<span class="nv">acc = </span><span class="kc">no</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">acc = </span><span class="nx">isObject</span> <span class="o">and</span> <span class="nx">IDENTIFIER</span><span class="p">.</span><span class="nx">test</span> <span class="nx">idx</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">().</span><span class="nx">value</span> <span class="o">or</span> <span class="mi">0</span>
|
|
<span class="nv">val = </span><span class="k">new</span> <span class="nx">Value</span> <span class="k">new</span> <span class="nx">Literal</span><span class="p">(</span><span class="nx">vvarText</span><span class="p">),</span> <span class="p">[</span><span class="k">new</span> <span class="p">(</span><span class="k">if</span> <span class="nx">acc</span> <span class="k">then</span> <span class="nx">Access</span> <span class="k">else</span> <span class="nx">Index</span><span class="p">)</span> <span class="nx">idx</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="nx">name</span><span class="o">?</span> <span class="o">and</span> <span class="nx">name</span> <span class="k">in</span> <span class="nx">RESERVED</span>
|
|
<span class="nx">obj</span><span class="p">.</span><span class="nx">error</span> <span class="s">"assignment to a reserved word: </span><span class="si">#{</span><span class="nx">obj</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="nx">assigns</span><span class="p">.</span><span class="nx">push</span> <span class="k">new</span> <span class="nx">Assign</span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">val</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nv">param: </span><span class="nx">@param</span><span class="p">,</span> <span class="nv">subpattern: </span><span class="kc">yes</span><span class="p">).</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
|
|
<span class="nx">assigns</span><span class="p">.</span><span class="nx">push</span> <span class="nx">vvar</span> <span class="k">unless</span> <span class="nx">top</span> <span class="o">or</span> <span class="nx">@subpattern</span>
|
|
<span class="nv">fragments = </span><span class="nx">@joinFragmentArrays</span> <span class="nx">assigns</span><span class="p">,</span> <span class="s">', '</span>
|
|
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o"><</span> <span class="nx">LEVEL_LIST</span> <span class="k">then</span> <span class="nx">fragments</span> <span class="k">else</span> <span class="nx">@wrapInBraces</span> <span class="nx">fragments</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-86">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-86">¶</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> <span class="nv">compileConditional: </span><span class="nf">(o) -></span>
|
|
<span class="p">[</span><span class="nx">left</span><span class="p">,</span> <span class="nx">right</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">cacheReference</span> <span class="nx">o</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-87">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-87">¶</a>
|
|
</div>
|
|
|
|
<p>Disallow conditional assignment of undefined variables.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="k">if</span> <span class="o">not</span> <span class="nx">left</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">length</span> <span class="o">and</span> <span class="nx">left</span><span class="p">.</span><span class="nx">base</span> <span class="k">instanceof</span> <span class="nx">Literal</span> <span class="o">and</span>
|
|
<span class="nx">left</span><span class="p">.</span><span class="nx">base</span><span class="p">.</span><span class="nx">value</span> <span class="o">!=</span> <span class="s">"this"</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">check</span> <span class="nx">left</span><span class="p">.</span><span class="nx">base</span><span class="p">.</span><span class="nx">value</span>
|
|
<span class="nx">@variable</span><span class="p">.</span><span class="nx">error</span> <span class="s">"the variable \"</span><span class="si">#{</span><span class="nx">left</span><span class="p">.</span><span class="nx">base</span><span class="p">.</span><span class="nx">value</span><span class="si">}</span><span class="s">\" can't be assigned with </span><span class="si">#{</span><span class="nx">@context</span><span class="si">}</span><span class="s"> because it has not been declared before"</span>
|
|
<span class="k">if</span> <span class="s">"?"</span> <span class="k">in</span> <span class="nx">@context</span> <span class="k">then</span> <span class="nv">o.isExistentialEquals = </span><span class="kc">true</span>
|
|
<span class="k">new</span> <span class="nx">Op</span><span class="p">(</span><span class="nx">@context</span><span class="p">[...</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="nx">left</span><span class="p">,</span> <span class="k">new</span> <span class="nx">Assign</span><span class="p">(</span><span class="nx">right</span><span class="p">,</span> <span class="nx">@value</span><span class="p">,</span> <span class="s">'='</span><span class="p">)</span> <span class="p">).</span><span class="nx">compileToFragments</span> <span class="nx">o</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-88">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-88">¶</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> <span class="nv">compileSplice: </span><span class="nf">(o) -></span>
|
|
<span class="p">{</span><span class="nv">range: </span><span class="p">{</span><span class="nx">from</span><span class="p">,</span> <span class="nx">to</span><span class="p">,</span> <span class="nx">exclusive</span><span class="p">}}</span> <span class="o">=</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
|
<span class="nv">name = </span><span class="nx">@variable</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span>
|
|
<span class="k">if</span> <span class="nx">from</span>
|
|
<span class="p">[</span><span class="nx">fromDecl</span><span class="p">,</span> <span class="nx">fromRef</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@cacheToCodeFragments</span> <span class="nx">from</span><span class="p">.</span><span class="nx">cache</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_OP</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">fromDecl = fromRef = </span><span class="s">'0'</span>
|
|
<span class="k">if</span> <span class="nx">to</span>
|
|
<span class="k">if</span> <span class="nx">from</span><span class="o">?</span><span class="p">.</span><span class="nx">isSimpleNumber</span><span class="p">()</span> <span class="o">and</span> <span class="nx">to</span><span class="p">.</span><span class="nx">isSimpleNumber</span><span class="p">()</span>
|
|
<span class="nv">to = </span><span class="o">+</span><span class="nx">to</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-</span> <span class="o">+</span><span class="nx">fromRef</span>
|
|
<span class="nx">to</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">unless</span> <span class="nx">exclusive</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">to = </span><span class="nx">to</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_ACCESS</span><span class="p">)</span> <span class="o">+</span> <span class="s">' - '</span> <span class="o">+</span> <span class="nx">fromRef</span>
|
|
<span class="nx">to</span> <span class="o">+=</span> <span class="s">' + 1'</span> <span class="k">unless</span> <span class="nx">exclusive</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">to = </span><span class="s">"9e9"</span>
|
|
<span class="p">[</span><span class="nx">valDef</span><span class="p">,</span> <span class="nx">valRef</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@value</span><span class="p">.</span><span class="nx">cache</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
|
|
<span class="nv">answer = </span><span class="p">[].</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"[].splice.apply(</span><span class="si">#{</span><span class="nx">name</span><span class="si">}</span><span class="s">, [</span><span class="si">#{</span><span class="nx">fromDecl</span><span class="si">}</span><span class="s">, </span><span class="si">#{</span><span class="nx">to</span><span class="si">}</span><span class="s">].concat("</span><span class="p">),</span> <span class="nx">valDef</span><span class="p">,</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">")), "</span><span class="p">),</span> <span class="nx">valRef</span>
|
|
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">></span> <span class="nx">LEVEL_TOP</span> <span class="k">then</span> <span class="nx">@wrapInBraces</span> <span class="nx">answer</span> <span class="k">else</span> <span class="nx">answer</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-89">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-89">¶</a>
|
|
</div>
|
|
|
|
<h3>Code</h3>
|
|
<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><span class="nv">exports.Code = </span><span class="k">class</span> <span class="nx">Code</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(params, body, tag) -></span>
|
|
<span class="vi">@params = </span><span class="nx">params</span> <span class="o">or</span> <span class="p">[]</span>
|
|
<span class="vi">@body = </span><span class="nx">body</span> <span class="o">or</span> <span class="k">new</span> <span class="nx">Block</span>
|
|
<span class="vi">@bound = </span><span class="nx">tag</span> <span class="o">is</span> <span class="s">'boundfunc'</span>
|
|
<span class="vi">@context = </span><span class="s">'_this'</span> <span class="k">if</span> <span class="nx">@bound</span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'params'</span><span class="p">,</span> <span class="s">'body'</span><span class="p">]</span>
|
|
|
|
<span class="nv">isStatement: </span><span class="nf">-></span> <span class="o">!!</span><span class="nx">@ctor</span>
|
|
|
|
<span class="nv">jumps: </span><span class="nx">NO</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-90">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-90">¶</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 peeking at
|
|
the JavaScript <code>arguments</code> object. If the function is bound with the <code>=></code>
|
|
arrow, generates a wrapper that saves the current value of <code>this</code> through
|
|
a closure.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="nv">o.scope = </span><span class="k">new</span> <span class="nx">Scope</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">,</span> <span class="nx">@body</span><span class="p">,</span> <span class="k">this</span>
|
|
<span class="nv">o.scope.shared = </span><span class="nx">del</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="s">'sharedScope'</span><span class="p">)</span>
|
|
<span class="nx">o</span><span class="p">.</span><span class="nx">indent</span> <span class="o">+=</span> <span class="nx">TAB</span>
|
|
<span class="k">delete</span> <span class="nx">o</span><span class="p">.</span><span class="nx">bare</span>
|
|
<span class="k">delete</span> <span class="nx">o</span><span class="p">.</span><span class="nx">isExistentialEquals</span>
|
|
<span class="nv">params = </span><span class="p">[]</span>
|
|
<span class="nv">exprs = </span><span class="p">[]</span>
|
|
<span class="nx">@eachParamName</span> <span class="nf">(name) -></span> <span class="c1"># this step must be performed before the others</span>
|
|
<span class="k">unless</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">check</span> <span class="nx">name</span> <span class="k">then</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">parameter</span> <span class="nx">name</span>
|
|
<span class="k">for</span> <span class="nx">param</span> <span class="k">in</span> <span class="nx">@params</span> <span class="k">when</span> <span class="nx">param</span><span class="p">.</span><span class="nx">splat</span>
|
|
<span class="k">for</span> <span class="p">{</span><span class="nv">name: </span><span class="nx">p</span><span class="p">}</span> <span class="k">in</span> <span class="nx">@params</span>
|
|
<span class="k">if</span> <span class="nx">p</span><span class="p">.</span><span class="nx">this</span> <span class="k">then</span> <span class="nv">p = </span><span class="nx">p</span><span class="p">.</span><span class="nx">properties</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">name</span>
|
|
<span class="k">if</span> <span class="nx">p</span><span class="p">.</span><span class="nx">value</span> <span class="k">then</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">add</span> <span class="nx">p</span><span class="p">.</span><span class="nx">value</span><span class="p">,</span> <span class="s">'var'</span><span class="p">,</span> <span class="kc">yes</span>
|
|
<span class="nv">splats = </span><span class="k">new</span> <span class="nx">Assign</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="k">new</span> <span class="nx">Arr</span><span class="p">(</span><span class="nx">p</span><span class="p">.</span><span class="nx">asReference</span> <span class="nx">o</span> <span class="k">for</span> <span class="nx">p</span> <span class="k">in</span> <span class="nx">@params</span><span class="p">)),</span>
|
|
<span class="k">new</span> <span class="nx">Value</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">'arguments'</span>
|
|
<span class="k">break</span>
|
|
<span class="k">for</span> <span class="nx">param</span> <span class="k">in</span> <span class="nx">@params</span>
|
|
<span class="k">if</span> <span class="nx">param</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span>
|
|
<span class="nv">val = ref = </span><span class="nx">param</span><span class="p">.</span><span class="nx">asReference</span> <span class="nx">o</span>
|
|
<span class="nv">val = </span><span class="k">new</span> <span class="nx">Op</span> <span class="s">'?'</span><span class="p">,</span> <span class="nx">ref</span><span class="p">,</span> <span class="nx">param</span><span class="p">.</span><span class="nx">value</span> <span class="k">if</span> <span class="nx">param</span><span class="p">.</span><span class="nx">value</span>
|
|
<span class="nx">exprs</span><span class="p">.</span><span class="nx">push</span> <span class="k">new</span> <span class="nx">Assign</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="nx">param</span><span class="p">.</span><span class="nx">name</span><span class="p">),</span> <span class="nx">val</span><span class="p">,</span> <span class="s">'='</span><span class="p">,</span> <span class="nv">param: </span><span class="kc">yes</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">ref = </span><span class="nx">param</span>
|
|
<span class="k">if</span> <span class="nx">param</span><span class="p">.</span><span class="nx">value</span>
|
|
<span class="nv">lit = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">ref</span><span class="p">.</span><span class="nx">name</span><span class="p">.</span><span class="nx">value</span> <span class="o">+</span> <span class="s">' == null'</span>
|
|
<span class="nv">val = </span><span class="k">new</span> <span class="nx">Assign</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="nx">param</span><span class="p">.</span><span class="nx">name</span><span class="p">),</span> <span class="nx">param</span><span class="p">.</span><span class="nx">value</span><span class="p">,</span> <span class="s">'='</span>
|
|
<span class="nx">exprs</span><span class="p">.</span><span class="nx">push</span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">lit</span><span class="p">,</span> <span class="nx">val</span>
|
|
<span class="nx">params</span><span class="p">.</span><span class="nx">push</span> <span class="nx">ref</span> <span class="k">unless</span> <span class="nx">splats</span>
|
|
<span class="nv">wasEmpty = </span><span class="nx">@body</span><span class="p">.</span><span class="nx">isEmpty</span><span class="p">()</span>
|
|
<span class="nx">exprs</span><span class="p">.</span><span class="nx">unshift</span> <span class="nx">splats</span> <span class="k">if</span> <span class="nx">splats</span>
|
|
<span class="nx">@body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">unshift</span> <span class="nx">exprs</span><span class="p">...</span> <span class="k">if</span> <span class="nx">exprs</span><span class="p">.</span><span class="nx">length</span>
|
|
<span class="k">for</span> <span class="nx">p</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">params</span>
|
|
<span class="nx">params</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="nx">p</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span>
|
|
<span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">parameter</span> <span class="nx">fragmentsToText</span> <span class="nx">params</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>
|
|
<span class="nv">uniqs = </span><span class="p">[]</span>
|
|
<span class="nx">@eachParamName</span> <span class="nf">(name, node) -></span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">error</span> <span class="s">"multiple parameters named '</span><span class="si">#{</span><span class="nx">name</span><span class="si">}</span><span class="s">'"</span> <span class="k">if</span> <span class="nx">name</span> <span class="k">in</span> <span class="nx">uniqs</span>
|
|
<span class="nx">uniqs</span><span class="p">.</span><span class="nx">push</span> <span class="nx">name</span>
|
|
<span class="nx">@body</span><span class="p">.</span><span class="nx">makeReturn</span><span class="p">()</span> <span class="k">unless</span> <span class="nx">wasEmpty</span> <span class="o">or</span> <span class="nx">@noReturn</span>
|
|
<span class="k">if</span> <span class="nx">@bound</span>
|
|
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">parent</span><span class="p">.</span><span class="nx">method</span><span class="o">?</span><span class="p">.</span><span class="nx">bound</span>
|
|
<span class="vi">@bound = @context = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">parent</span><span class="p">.</span><span class="nx">method</span><span class="p">.</span><span class="nx">context</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">@static</span>
|
|
<span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">parent</span><span class="p">.</span><span class="nx">assign</span> <span class="s">'_this'</span><span class="p">,</span> <span class="s">'this'</span>
|
|
<span class="nv">idt = </span><span class="nx">o</span><span class="p">.</span><span class="nx">indent</span>
|
|
<span class="nv">code = </span><span class="s">'function'</span>
|
|
<span class="nx">code</span> <span class="o">+=</span> <span class="s">' '</span> <span class="o">+</span> <span class="nx">@name</span> <span class="k">if</span> <span class="nx">@ctor</span>
|
|
<span class="nx">code</span> <span class="o">+=</span> <span class="s">'('</span>
|
|
<span class="nv">answer = </span><span class="p">[</span><span class="nx">@makeCode</span><span class="p">(</span><span class="nx">code</span><span class="p">)]</span>
|
|
<span class="k">for</span> <span class="nx">p</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">params</span>
|
|
<span class="k">if</span> <span class="nx">i</span> <span class="k">then</span> <span class="nx">answer</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="s">", "</span>
|
|
<span class="nx">answer</span><span class="p">.</span><span class="nx">push</span> <span class="nx">p</span><span class="p">...</span>
|
|
<span class="nx">answer</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="s">') {'</span>
|
|
<span class="nv">answer = </span><span class="nx">answer</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">@makeCode</span><span class="p">(</span><span class="s">"\n"</span><span class="p">),</span> <span class="nx">@body</span><span class="p">.</span><span class="nx">compileWithDeclarations</span><span class="p">(</span><span class="nx">o</span><span class="p">),</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"\n</span><span class="si">#{</span><span class="nx">@tab</span><span class="si">}</span><span class="s">"</span><span class="p">))</span> <span class="k">unless</span> <span class="nx">@body</span><span class="p">.</span><span class="nx">isEmpty</span><span class="p">()</span>
|
|
<span class="nx">answer</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="s">'}'</span>
|
|
|
|
<span class="k">return</span> <span class="p">[</span><span class="nx">@makeCode</span><span class="p">(</span><span class="nx">@tab</span><span class="p">),</span> <span class="nx">answer</span><span class="p">...]</span> <span class="k">if</span> <span class="nx">@ctor</span>
|
|
<span class="k">if</span> <span class="nx">@front</span> <span class="o">or</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">>=</span> <span class="nx">LEVEL_ACCESS</span><span class="p">)</span> <span class="k">then</span> <span class="nx">@wrapInBraces</span> <span class="nx">answer</span> <span class="k">else</span> <span class="nx">answer</span>
|
|
|
|
<span class="nv">eachParamName: </span><span class="nf">(iterator) -></span>
|
|
<span class="nx">param</span><span class="p">.</span><span class="nx">eachName</span> <span class="nx">iterator</span> <span class="k">for</span> <span class="nx">param</span> <span class="k">in</span> <span class="nx">@params</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-91">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-91">¶</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> <span class="nv">traverseChildren: </span><span class="nf">(crossScope, func) -></span>
|
|
<span class="k">super</span><span class="p">(</span><span class="nx">crossScope</span><span class="p">,</span> <span class="nx">func</span><span class="p">)</span> <span class="k">if</span> <span class="nx">crossScope</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-92">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-92">¶</a>
|
|
</div>
|
|
|
|
<h3>Param</h3>
|
|
<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><span class="nv">exports.Param = </span><span class="k">class</span> <span class="nx">Param</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(@name, @value, @splat) -></span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nv">name = </span><span class="nx">@name</span><span class="p">.</span><span class="nx">unwrapAll</span><span class="p">().</span><span class="nx">value</span><span class="p">)</span> <span class="k">in</span> <span class="nx">STRICT_PROSCRIBED</span>
|
|
<span class="nx">@name</span><span class="p">.</span><span class="nx">error</span> <span class="s">"parameter name \"</span><span class="si">#{</span><span class="nx">name</span><span class="si">}</span><span class="s">\" is not allowed"</span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'name'</span><span class="p">,</span> <span class="s">'value'</span><span class="p">]</span>
|
|
|
|
<span class="nv">compileToFragments: </span><span class="nf">(o) -></span>
|
|
<span class="nx">@name</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
|
|
|
|
<span class="nv">asReference: </span><span class="nf">(o) -></span>
|
|
<span class="k">return</span> <span class="nx">@reference</span> <span class="k">if</span> <span class="nx">@reference</span>
|
|
<span class="nv">node = </span><span class="nx">@name</span>
|
|
<span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">this</span>
|
|
<span class="nv">node = </span><span class="nx">node</span><span class="p">.</span><span class="nx">properties</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">name</span>
|
|
<span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">reserved</span>
|
|
<span class="nv">node = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="nx">node</span><span class="p">.</span><span class="nx">value</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span>
|
|
<span class="nv">node = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s">'arg'</span>
|
|
<span class="nv">node = </span><span class="k">new</span> <span class="nx">Value</span> <span class="nx">node</span>
|
|
<span class="nv">node = </span><span class="k">new</span> <span class="nx">Splat</span> <span class="nx">node</span> <span class="k">if</span> <span class="nx">@splat</span>
|
|
<span class="vi">@reference = </span><span class="nx">node</span>
|
|
|
|
<span class="nv">isComplex: </span><span class="nf">-></span>
|
|
<span class="nx">@name</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-93">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-93">¶</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> <span class="nv">eachName: </span><span class="nf">(iterator, name = @name)-></span>
|
|
<span class="nv">atParam = </span><span class="nf">(obj) -></span>
|
|
<span class="nv">node = </span><span class="nx">obj</span><span class="p">.</span><span class="nx">properties</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">name</span>
|
|
<span class="nx">iterator</span> <span class="nx">node</span><span class="p">.</span><span class="nx">value</span><span class="p">,</span> <span class="nx">node</span> <span class="k">unless</span> <span class="nx">node</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">reserved</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-94">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-94">¶</a>
|
|
</div>
|
|
|
|
<ul>
|
|
<li>simple literals <code>foo</code></li>
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="k">return</span> <span class="nx">iterator</span> <span class="nx">name</span><span class="p">.</span><span class="nx">value</span><span class="p">,</span> <span class="nx">name</span> <span class="k">if</span> <span class="nx">name</span> <span class="k">instanceof</span> <span class="nx">Literal</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-95">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-95">¶</a>
|
|
</div>
|
|
|
|
<ul>
|
|
<li>at-params <code>@foo</code></li>
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="k">return</span> <span class="nx">atParam</span> <span class="nx">name</span> <span class="k">if</span> <span class="nx">name</span> <span class="k">instanceof</span> <span class="nx">Value</span>
|
|
<span class="k">for</span> <span class="nx">obj</span> <span class="k">in</span> <span class="nx">name</span><span class="p">.</span><span class="nx">objects</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-96">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-96">¶</a>
|
|
</div>
|
|
|
|
<ul>
|
|
<li>assignments within destructured parameters <code>{foo:bar}</code></li>
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="k">if</span> <span class="nx">obj</span> <span class="k">instanceof</span> <span class="nx">Assign</span>
|
|
<span class="nx">@eachName</span> <span class="nx">iterator</span><span class="p">,</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-97">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-97">¶</a>
|
|
</div>
|
|
|
|
<ul>
|
|
<li>splats within destructured parameters <code>[xs...]</code></li>
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="k">else</span> <span class="k">if</span> <span class="nx">obj</span> <span class="k">instanceof</span> <span class="nx">Splat</span>
|
|
<span class="nv">node = </span><span class="nx">obj</span><span class="p">.</span><span class="nx">name</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span>
|
|
<span class="nx">iterator</span> <span class="nx">node</span><span class="p">.</span><span class="nx">value</span><span class="p">,</span> <span class="nx">node</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="nx">obj</span> <span class="k">instanceof</span> <span class="nx">Value</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-98">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-98">¶</a>
|
|
</div>
|
|
|
|
<ul>
|
|
<li>destructured parameters within destructured parameters <code>[{a}]</code></li>
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="k">if</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">isArray</span><span class="p">()</span> <span class="o">or</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">isObject</span><span class="p">()</span>
|
|
<span class="nx">@eachName</span> <span class="nx">iterator</span><span class="p">,</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">base</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-99">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-99">¶</a>
|
|
</div>
|
|
|
|
<ul>
|
|
<li>at-params within destructured parameters <code>{@foo}</code></li>
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="k">else</span> <span class="k">if</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">this</span>
|
|
<span class="nx">atParam</span> <span class="nx">obj</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-100">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-100">¶</a>
|
|
</div>
|
|
|
|
<ul>
|
|
<li>simple destructured parameters {foo}</li>
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="k">else</span> <span class="nx">iterator</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">base</span><span class="p">.</span><span class="nx">value</span><span class="p">,</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">base</span>
|
|
<span class="k">else</span>
|
|
<span class="nx">obj</span><span class="p">.</span><span class="nx">error</span> <span class="s">"illegal parameter </span><span class="si">#{</span><span class="nx">obj</span><span class="p">.</span><span class="nx">compile</span><span class="p">()</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="k">return</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-101">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-101">¶</a>
|
|
</div>
|
|
|
|
<h3>Splat</h3>
|
|
<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><span class="nv">exports.Splat = </span><span class="k">class</span> <span class="nx">Splat</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'name'</span><span class="p">]</span>
|
|
|
|
<span class="nv">isAssignable: </span><span class="nx">YES</span>
|
|
|
|
<span class="nv">constructor: </span><span class="nf">(name) -></span>
|
|
<span class="vi">@name = </span><span class="k">if</span> <span class="nx">name</span><span class="p">.</span><span class="nx">compile</span> <span class="k">then</span> <span class="nx">name</span> <span class="k">else</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">name</span>
|
|
|
|
<span class="nv">assigns: </span><span class="nf">(name) -></span>
|
|
<span class="nx">@name</span><span class="p">.</span><span class="nx">assigns</span> <span class="nx">name</span>
|
|
|
|
<span class="nv">compileToFragments: </span><span class="nf">(o) -></span>
|
|
<span class="nx">@name</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span>
|
|
|
|
<span class="nv">unwrap: </span><span class="nf">-></span> <span class="nx">@name</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-102">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-102">¶</a>
|
|
</div>
|
|
|
|
<p>Utility function that converts an arbitrary number of elements, mixed with
|
|
splats, to a proper array.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="vi">@compileSplattedArray: </span><span class="nf">(o, list, apply) -></span>
|
|
<span class="nv">index = </span><span class="o">-</span><span class="mi">1</span>
|
|
<span class="k">continue</span> <span class="k">while</span> <span class="p">(</span><span class="nv">node = </span><span class="nx">list</span><span class="p">[</span><span class="o">++</span><span class="nx">index</span><span class="p">])</span> <span class="o">and</span> <span class="nx">node</span> <span class="o">not</span> <span class="k">instanceof</span> <span class="nx">Splat</span>
|
|
<span class="k">return</span> <span class="p">[]</span> <span class="k">if</span> <span class="nx">index</span> <span class="o">>=</span> <span class="nx">list</span><span class="p">.</span><span class="nx">length</span>
|
|
<span class="k">if</span> <span class="nx">list</span><span class="p">.</span><span class="nx">length</span> <span class="o">is</span> <span class="mi">1</span>
|
|
<span class="nv">node = </span><span class="nx">list</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="nv">fragments = </span><span class="nx">node</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
|
|
<span class="k">return</span> <span class="nx">fragments</span> <span class="k">if</span> <span class="nx">apply</span>
|
|
<span class="k">return</span> <span class="p">[].</span><span class="nx">concat</span> <span class="nx">node</span><span class="p">.</span><span class="nx">makeCode</span><span class="p">(</span><span class="s">"</span><span class="si">#{</span> <span class="nx">utility</span> <span class="s">'slice'</span> <span class="si">}</span><span class="s">.call("</span><span class="p">),</span> <span class="nx">fragments</span><span class="p">,</span> <span class="nx">node</span><span class="p">.</span><span class="nx">makeCode</span><span class="p">(</span><span class="s">")"</span><span class="p">)</span>
|
|
<span class="nv">args = </span><span class="nx">list</span><span class="p">[</span><span class="nx">index</span><span class="p">..]</span>
|
|
<span class="k">for</span> <span class="nx">node</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">args</span>
|
|
<span class="nv">compiledNode = </span><span class="nx">node</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
|
|
<span class="nx">args</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="k">if</span> <span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Splat</span>
|
|
<span class="k">then</span> <span class="p">[].</span><span class="nx">concat</span> <span class="nx">node</span><span class="p">.</span><span class="nx">makeCode</span><span class="p">(</span><span class="s">"</span><span class="si">#{</span> <span class="nx">utility</span> <span class="s">'slice'</span> <span class="si">}</span><span class="s">.call("</span><span class="p">),</span> <span class="nx">compiledNode</span><span class="p">,</span> <span class="nx">node</span><span class="p">.</span><span class="nx">makeCode</span><span class="p">(</span><span class="s">")"</span><span class="p">)</span>
|
|
<span class="k">else</span> <span class="p">[].</span><span class="nx">concat</span> <span class="nx">node</span><span class="p">.</span><span class="nx">makeCode</span><span class="p">(</span><span class="s">"["</span><span class="p">),</span> <span class="nx">compiledNode</span><span class="p">,</span> <span class="nx">node</span><span class="p">.</span><span class="nx">makeCode</span><span class="p">(</span><span class="s">"]"</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nx">index</span> <span class="o">is</span> <span class="mi">0</span>
|
|
<span class="nv">node = </span><span class="nx">list</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="nv">concatPart = </span><span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">joinFragmentArrays</span> <span class="nx">args</span><span class="p">[</span><span class="mi">1</span><span class="p">..],</span> <span class="s">', '</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="nx">args</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">node</span><span class="p">.</span><span class="nx">makeCode</span><span class="p">(</span><span class="s">".concat("</span><span class="p">),</span> <span class="nx">concatPart</span><span class="p">,</span> <span class="nx">node</span><span class="p">.</span><span class="nx">makeCode</span><span class="p">(</span><span class="s">")"</span><span class="p">)</span>
|
|
<span class="nv">base = </span><span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span> <span class="k">for</span> <span class="nx">node</span> <span class="k">in</span> <span class="nx">list</span><span class="p">[...</span><span class="nx">index</span><span class="p">])</span>
|
|
<span class="nv">base = </span><span class="nx">list</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">joinFragmentArrays</span> <span class="nx">base</span><span class="p">,</span> <span class="s">', '</span>
|
|
<span class="nv">concatPart = </span><span class="nx">list</span><span class="p">[</span><span class="nx">index</span><span class="p">].</span><span class="nx">joinFragmentArrays</span> <span class="nx">args</span><span class="p">,</span> <span class="s">', '</span>
|
|
<span class="p">[].</span><span class="nx">concat</span> <span class="nx">list</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">makeCode</span><span class="p">(</span><span class="s">"["</span><span class="p">),</span> <span class="nx">base</span><span class="p">,</span> <span class="nx">list</span><span class="p">[</span><span class="nx">index</span><span class="p">].</span><span class="nx">makeCode</span><span class="p">(</span><span class="s">"].concat("</span><span class="p">),</span> <span class="nx">concatPart</span><span class="p">,</span> <span class="p">(</span><span class="nx">last</span> <span class="nx">list</span><span class="p">).</span><span class="nx">makeCode</span><span class="p">(</span><span class="s">")"</span><span class="p">)</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-103">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-103">¶</a>
|
|
</div>
|
|
|
|
<h3>While</h3>
|
|
<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><span class="nv">exports.While = </span><span class="k">class</span> <span class="nx">While</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(condition, options) -></span>
|
|
<span class="vi">@condition = </span><span class="k">if</span> <span class="nx">options</span><span class="o">?</span><span class="p">.</span><span class="nx">invert</span> <span class="k">then</span> <span class="nx">condition</span><span class="p">.</span><span class="nx">invert</span><span class="p">()</span> <span class="k">else</span> <span class="nx">condition</span>
|
|
<span class="vi">@guard = </span><span class="nx">options</span><span class="o">?</span><span class="p">.</span><span class="nx">guard</span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'condition'</span><span class="p">,</span> <span class="s">'guard'</span><span class="p">,</span> <span class="s">'body'</span><span class="p">]</span>
|
|
|
|
<span class="nv">isStatement: </span><span class="nx">YES</span>
|
|
|
|
<span class="nv">makeReturn: </span><span class="nf">(res) -></span>
|
|
<span class="k">if</span> <span class="nx">res</span>
|
|
<span class="k">super</span>
|
|
<span class="k">else</span>
|
|
<span class="vi">@returns = </span><span class="o">not</span> <span class="nx">@jumps</span> <span class="k">loop</span><span class="o">:</span> <span class="kc">yes</span>
|
|
<span class="k">this</span>
|
|
|
|
<span class="nv">addBody: </span><span class="nf">(@body) -></span>
|
|
<span class="k">this</span>
|
|
|
|
<span class="nv">jumps: </span><span class="nf">-></span>
|
|
<span class="p">{</span><span class="nx">expressions</span><span class="p">}</span> <span class="o">=</span> <span class="nx">@body</span>
|
|
<span class="k">return</span> <span class="kc">no</span> <span class="k">unless</span> <span class="nx">expressions</span><span class="p">.</span><span class="nx">length</span>
|
|
<span class="k">for</span> <span class="nx">node</span> <span class="k">in</span> <span class="nx">expressions</span>
|
|
<span class="k">return</span> <span class="nx">node</span> <span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">jumps</span> <span class="k">loop</span><span class="o">:</span> <span class="kc">yes</span>
|
|
<span class="kc">no</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-104">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-104">¶</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> <span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="nx">o</span><span class="p">.</span><span class="nx">indent</span> <span class="o">+=</span> <span class="nx">TAB</span>
|
|
<span class="nv">set = </span><span class="s">''</span>
|
|
<span class="p">{</span><span class="nx">body</span><span class="p">}</span> <span class="o">=</span> <span class="k">this</span>
|
|
<span class="k">if</span> <span class="nx">body</span><span class="p">.</span><span class="nx">isEmpty</span><span class="p">()</span>
|
|
<span class="nv">body = </span><span class="s">''</span>
|
|
<span class="k">else</span>
|
|
<span class="k">if</span> <span class="nx">@returns</span>
|
|
<span class="nx">body</span><span class="p">.</span><span class="nx">makeReturn</span> <span class="nv">rvar = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s">'results'</span>
|
|
<span class="nv">set = </span><span class="s">"</span><span class="si">#{</span><span class="nx">@tab</span><span class="si">}#{</span><span class="nx">rvar</span><span class="si">}</span><span class="s"> = [];\n"</span>
|
|
<span class="k">if</span> <span class="nx">@guard</span>
|
|
<span class="k">if</span> <span class="nx">body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">1</span>
|
|
<span class="nx">body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">unshift</span> <span class="k">new</span> <span class="nx">If</span> <span class="p">(</span><span class="k">new</span> <span class="nx">Parens</span> <span class="nx">@guard</span><span class="p">).</span><span class="nx">invert</span><span class="p">(),</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">"continue"</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">body = </span><span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="k">new</span> <span class="nx">If</span> <span class="nx">@guard</span><span class="p">,</span> <span class="nx">body</span><span class="p">]</span> <span class="k">if</span> <span class="nx">@guard</span>
|
|
<span class="nv">body = </span><span class="p">[].</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"\n"</span><span class="p">),</span> <span class="p">(</span><span class="nx">body</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_TOP</span><span class="p">),</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"\n</span><span class="si">#{</span><span class="nx">@tab</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
|
|
<span class="nv">answer = </span><span class="p">[].</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="nx">set</span> <span class="o">+</span> <span class="nx">@tab</span> <span class="o">+</span> <span class="s">"while ("</span><span class="p">),</span> <span class="nx">@condition</span><span class="p">.</span><span class="nx">compileToFragments</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_PAREN</span><span class="p">),</span>
|
|
<span class="nx">@makeCode</span><span class="p">(</span><span class="s">") {"</span><span class="p">),</span> <span class="nx">body</span><span class="p">,</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"}"</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nx">@returns</span>
|
|
<span class="nx">answer</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="s">"\n</span><span class="si">#{</span><span class="nx">@tab</span><span class="si">}</span><span class="s">return </span><span class="si">#{</span><span class="nx">rvar</span><span class="si">}</span><span class="s">;"</span>
|
|
<span class="nx">answer</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-105">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-105">¶</a>
|
|
</div>
|
|
|
|
<h3>Op</h3>
|
|
<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><span class="nv">exports.Op = </span><span class="k">class</span> <span class="nx">Op</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(op, first, second, flip ) -></span>
|
|
<span class="k">return</span> <span class="k">new</span> <span class="nx">In</span> <span class="nx">first</span><span class="p">,</span> <span class="nx">second</span> <span class="k">if</span> <span class="nx">op</span> <span class="o">is</span> <span class="s">'in'</span>
|
|
<span class="k">if</span> <span class="nx">op</span> <span class="o">is</span> <span class="s">'do'</span>
|
|
<span class="k">return</span> <span class="nx">@generateDo</span> <span class="nx">first</span>
|
|
<span class="k">if</span> <span class="nx">op</span> <span class="o">is</span> <span class="s">'new'</span>
|
|
<span class="k">return</span> <span class="nx">first</span><span class="p">.</span><span class="nx">newInstance</span><span class="p">()</span> <span class="k">if</span> <span class="nx">first</span> <span class="k">instanceof</span> <span class="nx">Call</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">first</span><span class="p">.</span><span class="nx">do</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">first</span><span class="p">.</span><span class="nx">isNew</span>
|
|
<span class="nv">first = </span><span class="k">new</span> <span class="nx">Parens</span> <span class="nx">first</span> <span class="k">if</span> <span class="nx">first</span> <span class="k">instanceof</span> <span class="nx">Code</span> <span class="o">and</span> <span class="nx">first</span><span class="p">.</span><span class="nx">bound</span> <span class="o">or</span> <span class="nx">first</span><span class="p">.</span><span class="nx">do</span>
|
|
<span class="vi">@operator = </span><span class="nx">CONVERSIONS</span><span class="p">[</span><span class="nx">op</span><span class="p">]</span> <span class="o">or</span> <span class="nx">op</span>
|
|
<span class="vi">@first = </span><span class="nx">first</span>
|
|
<span class="vi">@second = </span><span class="nx">second</span>
|
|
<span class="vi">@flip = </span><span class="o">!!</span><span class="nx">flip</span>
|
|
<span class="k">return</span> <span class="k">this</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-106">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-106">¶</a>
|
|
</div>
|
|
|
|
<p>The map of conversions from CoffeeScript to JavaScript symbols.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">CONVERSIONS =</span>
|
|
<span class="s">'=='</span><span class="o">:</span> <span class="s">'==='</span>
|
|
<span class="s">'!='</span><span class="o">:</span> <span class="s">'!=='</span>
|
|
<span class="s">'of'</span><span class="o">:</span> <span class="s">'in'</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-107">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-107">¶</a>
|
|
</div>
|
|
|
|
<p>The map of invertible operators.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">INVERSIONS =</span>
|
|
<span class="s">'!=='</span><span class="o">:</span> <span class="s">'==='</span>
|
|
<span class="s">'==='</span><span class="o">:</span> <span class="s">'!=='</span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'first'</span><span class="p">,</span> <span class="s">'second'</span><span class="p">]</span>
|
|
|
|
<span class="nv">isSimpleNumber: </span><span class="nx">NO</span>
|
|
|
|
<span class="nv">isUnary: </span><span class="nf">-></span>
|
|
<span class="o">not</span> <span class="nx">@second</span>
|
|
|
|
<span class="nv">isComplex: </span><span class="nf">-></span>
|
|
<span class="o">not</span> <span class="p">(</span><span class="nx">@isUnary</span><span class="p">()</span> <span class="o">and</span> <span class="p">(</span><span class="nx">@operator</span> <span class="k">in</span> <span class="p">[</span><span class="s">'+'</span><span class="p">,</span> <span class="s">'-'</span><span class="p">]))</span> <span class="o">or</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-108">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-108">¶</a>
|
|
</div>
|
|
|
|
<p>Am I capable of
|
|
<a href="http://docs.python.org/reference/expressions.html#notin">Python-style comparison chaining</a>?
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">isChainable: </span><span class="nf">-></span>
|
|
<span class="nx">@operator</span> <span class="k">in</span> <span class="p">[</span><span class="s">'<'</span><span class="p">,</span> <span class="s">'>'</span><span class="p">,</span> <span class="s">'>='</span><span class="p">,</span> <span class="s">'<='</span><span class="p">,</span> <span class="s">'==='</span><span class="p">,</span> <span class="s">'!=='</span><span class="p">]</span>
|
|
|
|
<span class="nv">invert: </span><span class="nf">-></span>
|
|
<span class="k">if</span> <span class="nx">@isChainable</span><span class="p">()</span> <span class="o">and</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">isChainable</span><span class="p">()</span>
|
|
<span class="nv">allInvertable = </span><span class="kc">yes</span>
|
|
<span class="nv">curr = </span><span class="k">this</span>
|
|
<span class="k">while</span> <span class="nx">curr</span> <span class="o">and</span> <span class="nx">curr</span><span class="p">.</span><span class="nx">operator</span>
|
|
<span class="nx">allInvertable</span> <span class="o">and=</span> <span class="p">(</span><span class="nx">curr</span><span class="p">.</span><span class="nx">operator</span> <span class="k">of</span> <span class="nx">INVERSIONS</span><span class="p">)</span>
|
|
<span class="nv">curr = </span><span class="nx">curr</span><span class="p">.</span><span class="nx">first</span>
|
|
<span class="k">return</span> <span class="k">new</span> <span class="nx">Parens</span><span class="p">(</span><span class="k">this</span><span class="p">).</span><span class="nx">invert</span><span class="p">()</span> <span class="k">unless</span> <span class="nx">allInvertable</span>
|
|
<span class="nv">curr = </span><span class="k">this</span>
|
|
<span class="k">while</span> <span class="nx">curr</span> <span class="o">and</span> <span class="nx">curr</span><span class="p">.</span><span class="nx">operator</span>
|
|
<span class="nv">curr.invert = </span><span class="o">!</span><span class="nx">curr</span><span class="p">.</span><span class="nx">invert</span>
|
|
<span class="nv">curr.operator = </span><span class="nx">INVERSIONS</span><span class="p">[</span><span class="nx">curr</span><span class="p">.</span><span class="nx">operator</span><span class="p">]</span>
|
|
<span class="nv">curr = </span><span class="nx">curr</span><span class="p">.</span><span class="nx">first</span>
|
|
<span class="k">this</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="nv">op = </span><span class="nx">INVERSIONS</span><span class="p">[</span><span class="nx">@operator</span><span class="p">]</span>
|
|
<span class="vi">@operator = </span><span class="nx">op</span>
|
|
<span class="k">if</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span> <span class="k">instanceof</span> <span class="nx">Op</span>
|
|
<span class="nx">@first</span><span class="p">.</span><span class="nx">invert</span><span class="p">()</span>
|
|
<span class="k">this</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="nx">@second</span>
|
|
<span class="k">new</span> <span class="nx">Parens</span><span class="p">(</span><span class="k">this</span><span class="p">).</span><span class="nx">invert</span><span class="p">()</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="nx">@operator</span> <span class="o">is</span> <span class="s">'!'</span> <span class="o">and</span> <span class="p">(</span><span class="nv">fst = </span><span class="nx">@first</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">())</span> <span class="k">instanceof</span> <span class="nx">Op</span> <span class="o">and</span>
|
|
<span class="nx">fst</span><span class="p">.</span><span class="nx">operator</span> <span class="k">in</span> <span class="p">[</span><span class="s">'!'</span><span class="p">,</span> <span class="s">'in'</span><span class="p">,</span> <span class="s">'instanceof'</span><span class="p">]</span>
|
|
<span class="nx">fst</span>
|
|
<span class="k">else</span>
|
|
<span class="k">new</span> <span class="nx">Op</span> <span class="s">'!'</span><span class="p">,</span> <span class="k">this</span>
|
|
|
|
<span class="nv">unfoldSoak: </span><span class="nf">(o) -></span>
|
|
<span class="nx">@operator</span> <span class="k">in</span> <span class="p">[</span><span class="s">'++'</span><span class="p">,</span> <span class="s">'--'</span><span class="p">,</span> <span class="s">'delete'</span><span class="p">]</span> <span class="o">and</span> <span class="nx">unfoldSoak</span> <span class="nx">o</span><span class="p">,</span> <span class="k">this</span><span class="p">,</span> <span class="s">'first'</span>
|
|
|
|
<span class="nv">generateDo: </span><span class="nf">(exp) -></span>
|
|
<span class="nv">passedParams = </span><span class="p">[]</span>
|
|
<span class="nv">func = </span><span class="k">if</span> <span class="nx">exp</span> <span class="k">instanceof</span> <span class="nx">Assign</span> <span class="o">and</span> <span class="p">(</span><span class="nv">ref = </span><span class="nx">exp</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">())</span> <span class="k">instanceof</span> <span class="nx">Code</span>
|
|
<span class="nx">ref</span>
|
|
<span class="k">else</span>
|
|
<span class="nx">exp</span>
|
|
<span class="k">for</span> <span class="nx">param</span> <span class="k">in</span> <span class="nx">func</span><span class="p">.</span><span class="nx">params</span> <span class="o">or</span> <span class="p">[]</span>
|
|
<span class="k">if</span> <span class="nx">param</span><span class="p">.</span><span class="nx">value</span>
|
|
<span class="nx">passedParams</span><span class="p">.</span><span class="nx">push</span> <span class="nx">param</span><span class="p">.</span><span class="nx">value</span>
|
|
<span class="k">delete</span> <span class="nx">param</span><span class="p">.</span><span class="nx">value</span>
|
|
<span class="k">else</span>
|
|
<span class="nx">passedParams</span><span class="p">.</span><span class="nx">push</span> <span class="nx">param</span>
|
|
<span class="nv">call = </span><span class="k">new</span> <span class="nx">Call</span> <span class="nx">exp</span><span class="p">,</span> <span class="nx">passedParams</span>
|
|
<span class="nv">call.do = </span><span class="kc">yes</span>
|
|
<span class="nx">call</span>
|
|
|
|
<span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="nv">isChain = </span><span class="nx">@isChainable</span><span class="p">()</span> <span class="o">and</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">isChainable</span><span class="p">()</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-109">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-109">¶</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> <span class="vi">@first.front = </span><span class="nx">@front</span> <span class="k">unless</span> <span class="nx">isChain</span>
|
|
<span class="k">if</span> <span class="nx">@operator</span> <span class="o">is</span> <span class="s">'delete'</span> <span class="o">and</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">check</span><span class="p">(</span><span class="nx">@first</span><span class="p">.</span><span class="nx">unwrapAll</span><span class="p">().</span><span class="nx">value</span><span class="p">)</span>
|
|
<span class="nx">@error</span> <span class="s">'delete operand may not be argument or var'</span>
|
|
<span class="k">if</span> <span class="nx">@operator</span> <span class="k">in</span> <span class="p">[</span><span class="s">'--'</span><span class="p">,</span> <span class="s">'++'</span><span class="p">]</span> <span class="o">and</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">unwrapAll</span><span class="p">().</span><span class="nx">value</span> <span class="k">in</span> <span class="nx">STRICT_PROSCRIBED</span>
|
|
<span class="nx">@error</span> <span class="s">"cannot increment/decrement \"</span><span class="si">#{</span><span class="nx">@first</span><span class="p">.</span><span class="nx">unwrapAll</span><span class="p">().</span><span class="nx">value</span><span class="si">}</span><span class="s">\""</span>
|
|
<span class="k">return</span> <span class="nx">@compileUnary</span> <span class="nx">o</span> <span class="k">if</span> <span class="nx">@isUnary</span><span class="p">()</span>
|
|
<span class="k">return</span> <span class="nx">@compileChain</span> <span class="nx">o</span> <span class="k">if</span> <span class="nx">isChain</span>
|
|
<span class="k">return</span> <span class="nx">@compileExistence</span> <span class="nx">o</span> <span class="k">if</span> <span class="nx">@operator</span> <span class="o">is</span> <span class="s">'?'</span>
|
|
<span class="nv">answer = </span><span class="p">[].</span><span class="nx">concat</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">compileToFragments</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_OP</span><span class="p">),</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">' '</span> <span class="o">+</span> <span class="nx">@operator</span> <span class="o">+</span> <span class="s">' '</span><span class="p">),</span>
|
|
<span class="nx">@second</span><span class="p">.</span><span class="nx">compileToFragments</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_OP</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o"><=</span> <span class="nx">LEVEL_OP</span> <span class="k">then</span> <span class="nx">answer</span> <span class="k">else</span> <span class="nx">@wrapInBraces</span> <span class="nx">answer</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-110">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-110">¶</a>
|
|
</div>
|
|
|
|
<p>Mimic Python's chained comparisons when multiple comparison operators are
|
|
used sequentially. For example:
|
|
|
|
</p>
|
|
<pre><code>bin/coffee -e 'console.log 50 < 65 > 10'
|
|
true</code></pre>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">compileChain: </span><span class="nf">(o) -></span>
|
|
<span class="p">[</span><span class="nx">@first</span><span class="p">.</span><span class="nx">second</span><span class="p">,</span> <span class="nx">shared</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">second</span><span class="p">.</span><span class="nx">cache</span> <span class="nx">o</span>
|
|
<span class="nv">fst = </span><span class="nx">@first</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_OP</span>
|
|
<span class="nv">fragments = </span><span class="nx">fst</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">" </span><span class="si">#{</span><span class="k">if</span> <span class="nx">@invert</span> <span class="k">then</span> <span class="s">'&&'</span> <span class="k">else</span> <span class="s">'||'</span><span class="si">}</span><span class="s"> "</span><span class="p">),</span>
|
|
<span class="p">(</span><span class="nx">shared</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">),</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">" </span><span class="si">#{</span><span class="nx">@operator</span><span class="si">}</span><span class="s"> "</span><span class="p">),</span> <span class="p">(</span><span class="nx">@second</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_OP</span><span class="p">)</span>
|
|
<span class="nx">@wrapInBraces</span> <span class="nx">fragments</span>
|
|
|
|
<span class="nv">compileExistence: </span><span class="nf">(o) -></span>
|
|
<span class="k">if</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span>
|
|
<span class="nv">ref = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s">'ref'</span>
|
|
<span class="nv">fst = </span><span class="k">new</span> <span class="nx">Parens</span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">ref</span><span class="p">,</span> <span class="nx">@first</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">fst = </span><span class="nx">@first</span>
|
|
<span class="nv">ref = </span><span class="nx">fst</span>
|
|
<span class="k">new</span> <span class="nx">If</span><span class="p">(</span><span class="k">new</span> <span class="nx">Existence</span><span class="p">(</span><span class="nx">fst</span><span class="p">),</span> <span class="nx">ref</span><span class="p">,</span> <span class="nv">type: </span><span class="s">'if'</span><span class="p">).</span><span class="nx">addElse</span><span class="p">(</span><span class="nx">@second</span><span class="p">).</span><span class="nx">compileToFragments</span> <span class="nx">o</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-111">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-111">¶</a>
|
|
</div>
|
|
|
|
<p>Compile a unary <strong>Op</strong>.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">compileUnary: </span><span class="nf">(o) -></span>
|
|
<span class="nv">parts = </span><span class="p">[]</span>
|
|
<span class="nv">op = </span><span class="nx">@operator</span>
|
|
<span class="nx">parts</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="nx">@makeCode</span> <span class="nx">op</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="nx">op</span> <span class="o">is</span> <span class="s">'!'</span> <span class="o">and</span> <span class="nx">@first</span> <span class="k">instanceof</span> <span class="nx">Existence</span>
|
|
<span class="vi">@first.negated = </span><span class="o">not</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">negated</span>
|
|
<span class="k">return</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span>
|
|
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">>=</span> <span class="nx">LEVEL_ACCESS</span>
|
|
<span class="k">return</span> <span class="p">(</span><span class="k">new</span> <span class="nx">Parens</span> <span class="k">this</span><span class="p">).</span><span class="nx">compileToFragments</span> <span class="nx">o</span>
|
|
<span class="nv">plusMinus = </span><span class="nx">op</span> <span class="k">in</span> <span class="p">[</span><span class="s">'+'</span><span class="p">,</span> <span class="s">'-'</span><span class="p">]</span>
|
|
<span class="nx">parts</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="nx">@makeCode</span><span class="p">(</span><span class="s">' '</span><span class="p">)]</span> <span class="k">if</span> <span class="nx">op</span> <span class="k">in</span> <span class="p">[</span><span class="s">'new'</span><span class="p">,</span> <span class="s">'typeof'</span><span class="p">,</span> <span class="s">'delete'</span><span class="p">]</span> <span class="o">or</span>
|
|
<span class="nx">plusMinus</span> <span class="o">and</span> <span class="nx">@first</span> <span class="k">instanceof</span> <span class="nx">Op</span> <span class="o">and</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">operator</span> <span class="o">is</span> <span class="nx">op</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">plusMinus</span> <span class="o">&&</span> <span class="nx">@first</span> <span class="k">instanceof</span> <span class="nx">Op</span><span class="p">)</span> <span class="o">or</span> <span class="p">(</span><span class="nx">op</span> <span class="o">is</span> <span class="s">'new'</span> <span class="o">and</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">isStatement</span> <span class="nx">o</span><span class="p">)</span>
|
|
<span class="vi">@first = </span><span class="k">new</span> <span class="nx">Parens</span> <span class="nx">@first</span>
|
|
<span class="nx">parts</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_OP</span>
|
|
<span class="nx">parts</span><span class="p">.</span><span class="nx">reverse</span><span class="p">()</span> <span class="k">if</span> <span class="nx">@flip</span>
|
|
<span class="nx">@joinFragmentArrays</span> <span class="nx">parts</span><span class="p">,</span> <span class="s">''</span>
|
|
|
|
<span class="nv">toString: </span><span class="nf">(idt) -></span>
|
|
<span class="k">super</span> <span class="nx">idt</span><span class="p">,</span> <span class="nx">@constructor</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span> <span class="s">' '</span> <span class="o">+</span> <span class="nx">@operator</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-112">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-112">¶</a>
|
|
</div>
|
|
|
|
<h3>In</h3>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre><span class="nv">exports.In = </span><span class="k">class</span> <span class="nx">In</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(@object, @array) -></span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'object'</span><span class="p">,</span> <span class="s">'array'</span><span class="p">]</span>
|
|
|
|
<span class="nv">invert: </span><span class="nx">NEGATE</span>
|
|
|
|
<span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="k">if</span> <span class="nx">@array</span> <span class="k">instanceof</span> <span class="nx">Value</span> <span class="o">and</span> <span class="nx">@array</span><span class="p">.</span><span class="nx">isArray</span><span class="p">()</span>
|
|
<span class="k">for</span> <span class="nx">obj</span> <span class="k">in</span> <span class="nx">@array</span><span class="p">.</span><span class="nx">base</span><span class="p">.</span><span class="nx">objects</span> <span class="k">when</span> <span class="nx">obj</span> <span class="k">instanceof</span> <span class="nx">Splat</span>
|
|
<span class="nv">hasSplat = </span><span class="kc">yes</span>
|
|
<span class="k">break</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-113">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-113">¶</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="k">return</span> <span class="nx">@compileOrTest</span> <span class="nx">o</span> <span class="k">unless</span> <span class="nx">hasSplat</span>
|
|
<span class="nx">@compileLoopTest</span> <span class="nx">o</span>
|
|
|
|
<span class="nv">compileOrTest: </span><span class="nf">(o) -></span>
|
|
<span class="k">return</span> <span class="p">[</span><span class="nx">@makeCode</span><span class="p">(</span><span class="s">"</span><span class="si">#{</span><span class="o">!!</span><span class="nx">@negated</span><span class="si">}</span><span class="s">"</span><span class="p">)]</span> <span class="k">if</span> <span class="nx">@array</span><span class="p">.</span><span class="nx">base</span><span class="p">.</span><span class="nx">objects</span><span class="p">.</span><span class="nx">length</span> <span class="o">is</span> <span class="mi">0</span>
|
|
<span class="p">[</span><span class="nx">sub</span><span class="p">,</span> <span class="nx">ref</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@object</span><span class="p">.</span><span class="nx">cache</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_OP</span>
|
|
<span class="p">[</span><span class="nx">cmp</span><span class="p">,</span> <span class="nx">cnj</span><span class="p">]</span> <span class="o">=</span> <span class="k">if</span> <span class="nx">@negated</span> <span class="k">then</span> <span class="p">[</span><span class="s">' !== '</span><span class="p">,</span> <span class="s">' && '</span><span class="p">]</span> <span class="k">else</span> <span class="p">[</span><span class="s">' === '</span><span class="p">,</span> <span class="s">' || '</span><span class="p">]</span>
|
|
<span class="nv">tests = </span><span class="p">[]</span>
|
|
<span class="k">for</span> <span class="nx">item</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">@array</span><span class="p">.</span><span class="nx">base</span><span class="p">.</span><span class="nx">objects</span>
|
|
<span class="k">if</span> <span class="nx">i</span> <span class="k">then</span> <span class="nx">tests</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="nx">cnj</span>
|
|
<span class="nv">tests = </span><span class="nx">tests</span><span class="p">.</span><span class="nx">concat</span> <span class="p">(</span><span class="k">if</span> <span class="nx">i</span> <span class="k">then</span> <span class="nx">ref</span> <span class="k">else</span> <span class="nx">sub</span><span class="p">),</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="nx">cmp</span><span class="p">),</span> <span class="nx">item</span><span class="p">.</span><span class="nx">compileToFragments</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_ACCESS</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o"><</span> <span class="nx">LEVEL_OP</span> <span class="k">then</span> <span class="nx">tests</span> <span class="k">else</span> <span class="nx">@wrapInBraces</span> <span class="nx">tests</span>
|
|
|
|
<span class="nv">compileLoopTest: </span><span class="nf">(o) -></span>
|
|
<span class="p">[</span><span class="nx">sub</span><span class="p">,</span> <span class="nx">ref</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@object</span><span class="p">.</span><span class="nx">cache</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
|
|
<span class="nv">fragments = </span><span class="p">[].</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="nx">utility</span><span class="p">(</span><span class="s">'indexOf'</span><span class="p">)</span> <span class="o">+</span> <span class="s">".call("</span><span class="p">),</span> <span class="nx">@array</span><span class="p">.</span><span class="nx">compileToFragments</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span><span class="p">),</span>
|
|
<span class="nx">@makeCode</span><span class="p">(</span><span class="s">", "</span><span class="p">),</span> <span class="nx">ref</span><span class="p">,</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">") "</span> <span class="o">+</span> <span class="k">if</span> <span class="nx">@negated</span> <span class="k">then</span> <span class="s">'< 0'</span> <span class="k">else</span> <span class="s">'>= 0'</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="nx">fragments</span> <span class="k">if</span> <span class="p">(</span><span class="nx">fragmentsToText</span> <span class="nx">sub</span><span class="p">)</span> <span class="o">is</span> <span class="p">(</span><span class="nx">fragmentsToText</span> <span class="nx">ref</span><span class="p">)</span>
|
|
<span class="nv">fragments = </span><span class="nx">sub</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">', '</span><span class="p">),</span> <span class="nx">fragments</span>
|
|
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o"><</span> <span class="nx">LEVEL_LIST</span> <span class="k">then</span> <span class="nx">fragments</span> <span class="k">else</span> <span class="nx">@wrapInBraces</span> <span class="nx">fragments</span>
|
|
|
|
<span class="nv">toString: </span><span class="nf">(idt) -></span>
|
|
<span class="k">super</span> <span class="nx">idt</span><span class="p">,</span> <span class="nx">@constructor</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span> <span class="k">if</span> <span class="nx">@negated</span> <span class="k">then</span> <span class="s">'!'</span> <span class="k">else</span> <span class="s">''</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-114">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-114">¶</a>
|
|
</div>
|
|
|
|
<h3>Try</h3>
|
|
<p>A classic <em>try/catch/finally</em> block.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre><span class="nv">exports.Try = </span><span class="k">class</span> <span class="nx">Try</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(@attempt, @errorVariable, @recovery, @ensure) -></span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'attempt'</span><span class="p">,</span> <span class="s">'recovery'</span><span class="p">,</span> <span class="s">'ensure'</span><span class="p">]</span>
|
|
|
|
<span class="nv">isStatement: </span><span class="nx">YES</span>
|
|
|
|
<span class="nv">jumps: </span><span class="nf">(o) -></span> <span class="nx">@attempt</span><span class="p">.</span><span class="nx">jumps</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">or</span> <span class="nx">@recovery</span><span class="o">?</span><span class="p">.</span><span class="nx">jumps</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
|
|
|
|
<span class="nv">makeReturn: </span><span class="nf">(res) -></span>
|
|
<span class="vi">@attempt = </span><span class="nx">@attempt</span> <span class="p">.</span><span class="nx">makeReturn</span> <span class="nx">res</span> <span class="k">if</span> <span class="nx">@attempt</span>
|
|
<span class="vi">@recovery = </span><span class="nx">@recovery</span><span class="p">.</span><span class="nx">makeReturn</span> <span class="nx">res</span> <span class="k">if</span> <span class="nx">@recovery</span>
|
|
<span class="k">this</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-115">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-115">¶</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> <span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="nx">o</span><span class="p">.</span><span class="nx">indent</span> <span class="o">+=</span> <span class="nx">TAB</span>
|
|
<span class="nv">tryPart = </span><span class="nx">@attempt</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_TOP</span>
|
|
|
|
<span class="nv">catchPart = </span><span class="k">if</span> <span class="nx">@recovery</span>
|
|
<span class="nv">placeholder = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="s">'_error'</span>
|
|
<span class="nx">@recovery</span><span class="p">.</span><span class="nx">unshift</span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">@errorVariable</span><span class="p">,</span> <span class="nx">placeholder</span>
|
|
<span class="vi">@errorVariable = </span><span class="nx">placeholder</span>
|
|
<span class="k">if</span> <span class="nx">@errorVariable</span><span class="p">.</span><span class="nx">value</span> <span class="k">in</span> <span class="nx">STRICT_PROSCRIBED</span>
|
|
<span class="nx">@errorVariable</span><span class="p">.</span><span class="nx">error</span> <span class="s">"catch variable may not be \"</span><span class="si">#{</span><span class="nx">@errorVariable</span><span class="p">.</span><span class="nx">value</span><span class="si">}</span><span class="s">\""</span>
|
|
<span class="p">[].</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">" catch ("</span><span class="p">),</span> <span class="nx">@errorVariable</span><span class="p">.</span><span class="nx">compileToFragments</span><span class="p">(</span><span class="nx">o</span><span class="p">),</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">") {\n"</span><span class="p">),</span>
|
|
<span class="nx">@recovery</span><span class="p">.</span><span class="nx">compileToFragments</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_TOP</span><span class="p">),</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"\n</span><span class="si">#{</span><span class="nx">@tab</span><span class="si">}</span><span class="s">}"</span><span class="p">)</span>
|
|
<span class="k">else</span> <span class="k">unless</span> <span class="nx">@ensure</span> <span class="o">or</span> <span class="nx">@recovery</span>
|
|
<span class="p">[</span><span class="nx">@makeCode</span><span class="p">(</span><span class="s">' catch (_error) {}'</span><span class="p">)]</span>
|
|
<span class="k">else</span>
|
|
<span class="p">[]</span>
|
|
|
|
<span class="nv">ensurePart = </span><span class="k">if</span> <span class="nx">@ensure</span> <span class="k">then</span> <span class="p">([].</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">" finally {\n"</span><span class="p">),</span> <span class="p">(</span><span class="nx">@ensure</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_TOP</span><span class="p">),</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"\n</span><span class="si">#{</span><span class="nx">@tab</span><span class="si">}</span><span class="s">}"</span><span class="p">))</span> <span class="k">else</span> <span class="p">[]</span>
|
|
|
|
<span class="p">[].</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"</span><span class="si">#{</span><span class="nx">@tab</span><span class="si">}</span><span class="s">try {\n"</span><span class="p">),</span>
|
|
<span class="nx">tryPart</span><span class="p">,</span>
|
|
<span class="nx">@makeCode</span><span class="p">(</span><span class="s">"\n</span><span class="si">#{</span><span class="nx">@tab</span><span class="si">}</span><span class="s">}"</span><span class="p">),</span> <span class="nx">catchPart</span><span class="p">,</span> <span class="nx">ensurePart</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-116">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-116">¶</a>
|
|
</div>
|
|
|
|
<h3>Throw</h3>
|
|
<p>Simple node to throw an exception.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre><span class="nv">exports.Throw = </span><span class="k">class</span> <span class="nx">Throw</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(@expression) -></span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'expression'</span><span class="p">]</span>
|
|
|
|
<span class="nv">isStatement: </span><span class="nx">YES</span>
|
|
<span class="nv">jumps: </span> <span class="nx">NO</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-117">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-117">¶</a>
|
|
</div>
|
|
|
|
<p>A <strong>Throw</strong> is already a return, of sorts...
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">makeReturn: </span><span class="nx">THIS</span>
|
|
|
|
<span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="p">[].</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="nx">@tab</span> <span class="o">+</span> <span class="s">"throw "</span><span class="p">),</span> <span class="p">(</span><span class="nx">@expression</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">),</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">";"</span><span class="p">)</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-118">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-118">¶</a>
|
|
</div>
|
|
|
|
<h3>Existence</h3>
|
|
<p>Checks a variable for existence -- not <em>null</em> and not <em>undefined</em>. This is
|
|
similar to <code>.nil?</code> in Ruby, and avoids having to consult a JavaScript truth
|
|
table.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre><span class="nv">exports.Existence = </span><span class="k">class</span> <span class="nx">Existence</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(@expression) -></span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'expression'</span><span class="p">]</span>
|
|
|
|
<span class="nv">invert: </span><span class="nx">NEGATE</span>
|
|
|
|
<span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="vi">@expression.front = </span><span class="nx">@front</span>
|
|
<span class="nv">code = </span><span class="nx">@expression</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_OP</span>
|
|
<span class="k">if</span> <span class="nx">IDENTIFIER</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">code</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">check</span> <span class="nx">code</span>
|
|
<span class="p">[</span><span class="nx">cmp</span><span class="p">,</span> <span class="nx">cnj</span><span class="p">]</span> <span class="o">=</span> <span class="k">if</span> <span class="nx">@negated</span> <span class="k">then</span> <span class="p">[</span><span class="s">'==='</span><span class="p">,</span> <span class="s">'||'</span><span class="p">]</span> <span class="k">else</span> <span class="p">[</span><span class="s">'!=='</span><span class="p">,</span> <span class="s">'&&'</span><span class="p">]</span>
|
|
<span class="nv">code = </span><span class="s">"typeof </span><span class="si">#{</span><span class="nx">code</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="nx">cmp</span><span class="si">}</span><span class="s"> \"undefined\" </span><span class="si">#{</span><span class="nx">cnj</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="nx">code</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="nx">cmp</span><span class="si">}</span><span class="s"> null"</span>
|
|
<span class="k">else</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-119">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-119">¶</a>
|
|
</div>
|
|
|
|
<p>do not use strict equality here; it will break existing code
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">code = </span><span class="s">"</span><span class="si">#{</span><span class="nx">code</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="k">if</span> <span class="nx">@negated</span> <span class="k">then</span> <span class="s">'=='</span> <span class="k">else</span> <span class="s">'!='</span><span class="si">}</span><span class="s"> null"</span>
|
|
<span class="p">[</span><span class="nx">@makeCode</span><span class="p">(</span><span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o"><=</span> <span class="nx">LEVEL_COND</span> <span class="k">then</span> <span class="nx">code</span> <span class="k">else</span> <span class="s">"(</span><span class="si">#{</span><span class="nx">code</span><span class="si">}</span><span class="s">)"</span><span class="p">)]</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-120">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-120">¶</a>
|
|
</div>
|
|
|
|
<h3>Parens</h3>
|
|
<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><span class="nv">exports.Parens = </span><span class="k">class</span> <span class="nx">Parens</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(@body) -></span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'body'</span><span class="p">]</span>
|
|
|
|
<span class="nv">unwrap : </span><span class="nf">-></span> <span class="nx">@body</span>
|
|
<span class="nv">isComplex : </span><span class="nf">-></span> <span class="nx">@body</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span>
|
|
|
|
<span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="nv">expr = </span><span class="nx">@body</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="nx">expr</span> <span class="k">instanceof</span> <span class="nx">Value</span> <span class="o">and</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">isAtomic</span><span class="p">()</span>
|
|
<span class="nv">expr.front = </span><span class="nx">@front</span>
|
|
<span class="k">return</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span>
|
|
<span class="nv">fragments = </span><span class="nx">expr</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_PAREN</span>
|
|
<span class="nv">bare = </span><span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o"><</span> <span class="nx">LEVEL_OP</span> <span class="o">and</span> <span class="p">(</span><span class="nx">expr</span> <span class="k">instanceof</span> <span class="nx">Op</span> <span class="o">or</span> <span class="nx">expr</span> <span class="k">instanceof</span> <span class="nx">Call</span> <span class="o">or</span>
|
|
<span class="p">(</span><span class="nx">expr</span> <span class="k">instanceof</span> <span class="nx">For</span> <span class="o">and</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">returns</span><span class="p">))</span>
|
|
<span class="k">if</span> <span class="nx">bare</span> <span class="k">then</span> <span class="nx">fragments</span> <span class="k">else</span> <span class="nx">@wrapInBraces</span> <span class="nx">fragments</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-121">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-121">¶</a>
|
|
</div>
|
|
|
|
<h3>For</h3>
|
|
<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><span class="nv">exports.For = </span><span class="k">class</span> <span class="nx">For</span> <span class="k">extends</span> <span class="nx">While</span>
|
|
<span class="nv">constructor: </span><span class="nf">(body, source) -></span>
|
|
<span class="p">{</span><span class="nx">@source</span><span class="p">,</span> <span class="nx">@guard</span><span class="p">,</span> <span class="nx">@step</span><span class="p">,</span> <span class="nx">@name</span><span class="p">,</span> <span class="nx">@index</span><span class="p">}</span> <span class="o">=</span> <span class="nx">source</span>
|
|
<span class="vi">@body = </span><span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">body</span><span class="p">]</span>
|
|
<span class="vi">@own = </span><span class="o">!!</span><span class="nx">source</span><span class="p">.</span><span class="nx">own</span>
|
|
<span class="vi">@object = </span><span class="o">!!</span><span class="nx">source</span><span class="p">.</span><span class="nx">object</span>
|
|
<span class="p">[</span><span class="nx">@name</span><span class="p">,</span> <span class="nx">@index</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">@index</span><span class="p">,</span> <span class="nx">@name</span><span class="p">]</span> <span class="k">if</span> <span class="nx">@object</span>
|
|
<span class="nx">@index</span><span class="p">.</span><span class="nx">error</span> <span class="s">'index cannot be a pattern matching expression'</span> <span class="k">if</span> <span class="nx">@index</span> <span class="k">instanceof</span> <span class="nx">Value</span>
|
|
<span class="vi">@range = </span><span class="nx">@source</span> <span class="k">instanceof</span> <span class="nx">Value</span> <span class="o">and</span> <span class="nx">@source</span><span class="p">.</span><span class="nx">base</span> <span class="k">instanceof</span> <span class="nx">Range</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@source</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">length</span>
|
|
<span class="vi">@pattern = </span><span class="nx">@name</span> <span class="k">instanceof</span> <span class="nx">Value</span>
|
|
<span class="nx">@index</span><span class="p">.</span><span class="nx">error</span> <span class="s">'indexes do not apply to range loops'</span> <span class="k">if</span> <span class="nx">@range</span> <span class="o">and</span> <span class="nx">@index</span>
|
|
<span class="nx">@name</span><span class="p">.</span><span class="nx">error</span> <span class="s">'cannot pattern match over range loops'</span> <span class="k">if</span> <span class="nx">@range</span> <span class="o">and</span> <span class="nx">@pattern</span>
|
|
<span class="vi">@returns = </span><span class="kc">false</span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'body'</span><span class="p">,</span> <span class="s">'source'</span><span class="p">,</span> <span class="s">'guard'</span><span class="p">,</span> <span class="s">'step'</span><span class="p">]</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-122">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-122">¶</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> <span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="nv">body = </span><span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">@body</span><span class="p">]</span>
|
|
<span class="nv">lastJumps = </span><span class="nx">last</span><span class="p">(</span><span class="nx">body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">)</span><span class="o">?</span><span class="p">.</span><span class="nx">jumps</span><span class="p">()</span>
|
|
<span class="vi">@returns = </span><span class="kc">no</span> <span class="k">if</span> <span class="nx">lastJumps</span> <span class="o">and</span> <span class="nx">lastJumps</span> <span class="k">instanceof</span> <span class="nx">Return</span>
|
|
<span class="nv">source = </span><span class="k">if</span> <span class="nx">@range</span> <span class="k">then</span> <span class="nx">@source</span><span class="p">.</span><span class="nx">base</span> <span class="k">else</span> <span class="nx">@source</span>
|
|
<span class="nv">scope = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span>
|
|
<span class="nv">name = </span><span class="nx">@name</span> <span class="o">and</span> <span class="p">(</span><span class="nx">@name</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span><span class="p">)</span>
|
|
<span class="nv">index = </span><span class="nx">@index</span> <span class="o">and</span> <span class="p">(</span><span class="nx">@index</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span><span class="p">)</span>
|
|
<span class="nx">scope</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="k">if</span> <span class="nx">name</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@pattern</span>
|
|
<span class="nx">scope</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">index</span><span class="p">)</span> <span class="k">if</span> <span class="nx">index</span>
|
|
<span class="nv">rvar = </span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s">'results'</span> <span class="k">if</span> <span class="nx">@returns</span>
|
|
<span class="nv">ivar = </span><span class="p">(</span><span class="nx">@object</span> <span class="o">and</span> <span class="nx">index</span><span class="p">)</span> <span class="o">or</span> <span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s">'i'</span>
|
|
<span class="nv">kvar = </span><span class="p">(</span><span class="nx">@range</span> <span class="o">and</span> <span class="nx">name</span><span class="p">)</span> <span class="o">or</span> <span class="nx">index</span> <span class="o">or</span> <span class="nx">ivar</span>
|
|
<span class="nv">kvarAssign = </span><span class="k">if</span> <span class="nx">kvar</span> <span class="o">isnt</span> <span class="nx">ivar</span> <span class="k">then</span> <span class="s">"</span><span class="si">#{</span><span class="nx">kvar</span><span class="si">}</span><span class="s"> = "</span> <span class="k">else</span> <span class="s">""</span>
|
|
<span class="k">if</span> <span class="nx">@step</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@range</span>
|
|
<span class="p">[</span><span class="nx">step</span><span class="p">,</span> <span class="nx">stepVar</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@cacheToCodeFragments</span> <span class="nx">@step</span><span class="p">.</span><span class="nx">cache</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
|
|
<span class="nv">stepNum = </span><span class="nx">stepVar</span><span class="p">.</span><span class="nx">match</span> <span class="nx">SIMPLENUM</span>
|
|
<span class="nv">name = </span><span class="nx">ivar</span> <span class="k">if</span> <span class="nx">@pattern</span>
|
|
<span class="nv">varPart = </span><span class="s">''</span>
|
|
<span class="nv">guardPart = </span><span class="s">''</span>
|
|
<span class="nv">defPart = </span><span class="s">''</span>
|
|
<span class="nv">idt1 = </span><span class="nx">@tab</span> <span class="o">+</span> <span class="nx">TAB</span>
|
|
<span class="k">if</span> <span class="nx">@range</span>
|
|
<span class="nv">forPartFragments = </span><span class="nx">source</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="p">{</span><span class="nv">index: </span><span class="nx">ivar</span><span class="p">,</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">@step</span><span class="p">})</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">svar = </span><span class="nx">@source</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">name</span> <span class="o">or</span> <span class="nx">@</span><span class="k">own</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">IDENTIFIER</span><span class="p">.</span><span class="nx">test</span> <span class="nx">svar</span>
|
|
<span class="nx">defPart</span> <span class="o">+=</span> <span class="s">"</span><span class="si">#{</span><span class="nx">@tab</span><span class="si">}#{</span><span class="nv">ref = </span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s">'ref'</span><span class="si">}</span><span class="s"> = </span><span class="si">#{</span><span class="nx">svar</span><span class="si">}</span><span class="s">;\n"</span>
|
|
<span class="nv">svar = </span><span class="nx">ref</span>
|
|
<span class="k">if</span> <span class="nx">name</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@pattern</span>
|
|
<span class="nv">namePart = </span><span class="s">"</span><span class="si">#{</span><span class="nx">name</span><span class="si">}</span><span class="s"> = </span><span class="si">#{</span><span class="nx">svar</span><span class="si">}</span><span class="s">[</span><span class="si">#{</span><span class="nx">kvar</span><span class="si">}</span><span class="s">]"</span>
|
|
<span class="k">if</span> <span class="o">not</span> <span class="nx">@object</span>
|
|
<span class="nx">defPart</span> <span class="o">+=</span> <span class="s">"</span><span class="si">#{</span><span class="nx">@tab</span><span class="si">}#{</span><span class="nx">step</span><span class="si">}</span><span class="s">;\n"</span> <span class="k">if</span> <span class="nx">step</span> <span class="o">isnt</span> <span class="nx">stepVar</span>
|
|
<span class="nv">lvar = </span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s">'len'</span> <span class="k">unless</span> <span class="nx">@step</span> <span class="o">and</span> <span class="nx">stepNum</span> <span class="o">and</span> <span class="nv">down = </span><span class="p">(</span><span class="o">+</span><span class="nx">stepNum</span> <span class="o"><</span> <span class="mi">0</span><span class="p">)</span>
|
|
<span class="nv">declare = </span><span class="s">"</span><span class="si">#{</span><span class="nx">kvarAssign</span><span class="si">}#{</span><span class="nx">ivar</span><span class="si">}</span><span class="s"> = 0, </span><span class="si">#{</span><span class="nx">lvar</span><span class="si">}</span><span class="s"> = </span><span class="si">#{</span><span class="nx">svar</span><span class="si">}</span><span class="s">.length"</span>
|
|
<span class="nv">declareDown = </span><span class="s">"</span><span class="si">#{</span><span class="nx">kvarAssign</span><span class="si">}#{</span><span class="nx">ivar</span><span class="si">}</span><span class="s"> = </span><span class="si">#{</span><span class="nx">svar</span><span class="si">}</span><span class="s">.length - 1"</span>
|
|
<span class="nv">compare = </span><span class="s">"</span><span class="si">#{</span><span class="nx">ivar</span><span class="si">}</span><span class="s"> < </span><span class="si">#{</span><span class="nx">lvar</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="nv">compareDown = </span><span class="s">"</span><span class="si">#{</span><span class="nx">ivar</span><span class="si">}</span><span class="s"> >= 0"</span>
|
|
<span class="k">if</span> <span class="nx">@step</span>
|
|
<span class="k">if</span> <span class="nx">stepNum</span>
|
|
<span class="k">if</span> <span class="nx">down</span>
|
|
<span class="nv">compare = </span><span class="nx">compareDown</span>
|
|
<span class="nv">declare = </span><span class="nx">declareDown</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">compare = </span><span class="s">"</span><span class="si">#{</span><span class="nx">stepVar</span><span class="si">}</span><span class="s"> > 0 ? </span><span class="si">#{</span><span class="nx">compare</span><span class="si">}</span><span class="s"> : </span><span class="si">#{</span><span class="nx">compareDown</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="nv">declare = </span><span class="s">"(</span><span class="si">#{</span><span class="nx">stepVar</span><span class="si">}</span><span class="s"> > 0 ? (</span><span class="si">#{</span><span class="nx">declare</span><span class="si">}</span><span class="s">) : </span><span class="si">#{</span><span class="nx">declareDown</span><span class="si">}</span><span class="s">)"</span>
|
|
<span class="nv">increment = </span><span class="s">"</span><span class="si">#{</span><span class="nx">ivar</span><span class="si">}</span><span class="s"> += </span><span class="si">#{</span><span class="nx">stepVar</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">increment = </span><span class="s">"</span><span class="si">#{</span><span class="k">if</span> <span class="nx">kvar</span> <span class="o">isnt</span> <span class="nx">ivar</span> <span class="k">then</span> <span class="s">"++</span><span class="si">#{</span><span class="nx">ivar</span><span class="si">}</span><span class="s">"</span> <span class="k">else</span> <span class="s">"</span><span class="si">#{</span><span class="nx">ivar</span><span class="si">}</span><span class="s">++"</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="nv">forPartFragments = </span><span class="p">[</span><span class="nx">@makeCode</span><span class="p">(</span><span class="s">"</span><span class="si">#{</span><span class="nx">declare</span><span class="si">}</span><span class="s">; </span><span class="si">#{</span><span class="nx">compare</span><span class="si">}</span><span class="s">; </span><span class="si">#{</span><span class="nx">kvarAssign</span><span class="si">}#{</span><span class="nx">increment</span><span class="si">}</span><span class="s">"</span><span class="p">)]</span>
|
|
<span class="k">if</span> <span class="nx">@returns</span>
|
|
<span class="nv">resultPart = </span><span class="s">"</span><span class="si">#{</span><span class="nx">@tab</span><span class="si">}#{</span><span class="nx">rvar</span><span class="si">}</span><span class="s"> = [];\n"</span>
|
|
<span class="nv">returnResult = </span><span class="s">"\n</span><span class="si">#{</span><span class="nx">@tab</span><span class="si">}</span><span class="s">return </span><span class="si">#{</span><span class="nx">rvar</span><span class="si">}</span><span class="s">;"</span>
|
|
<span class="nx">body</span><span class="p">.</span><span class="nx">makeReturn</span> <span class="nx">rvar</span>
|
|
<span class="k">if</span> <span class="nx">@guard</span>
|
|
<span class="k">if</span> <span class="nx">body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">1</span>
|
|
<span class="nx">body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">unshift</span> <span class="k">new</span> <span class="nx">If</span> <span class="p">(</span><span class="k">new</span> <span class="nx">Parens</span> <span class="nx">@guard</span><span class="p">).</span><span class="nx">invert</span><span class="p">(),</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">"continue"</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">body = </span><span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="k">new</span> <span class="nx">If</span> <span class="nx">@guard</span><span class="p">,</span> <span class="nx">body</span><span class="p">]</span> <span class="k">if</span> <span class="nx">@guard</span>
|
|
<span class="k">if</span> <span class="nx">@pattern</span>
|
|
<span class="nx">body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">unshift</span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">@name</span><span class="p">,</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">"</span><span class="si">#{</span><span class="nx">svar</span><span class="si">}</span><span class="s">[</span><span class="si">#{</span><span class="nx">kvar</span><span class="si">}</span><span class="s">]"</span>
|
|
<span class="nv">defPartFragments = </span><span class="p">[].</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="nx">defPart</span><span class="p">),</span> <span class="nx">@pluckDirectCall</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">body</span><span class="p">)</span>
|
|
<span class="nv">varPart = </span><span class="s">"\n</span><span class="si">#{</span><span class="nx">idt1</span><span class="si">}#{</span><span class="nx">namePart</span><span class="si">}</span><span class="s">;"</span> <span class="k">if</span> <span class="nx">namePart</span>
|
|
<span class="k">if</span> <span class="nx">@object</span>
|
|
<span class="nv">forPartFragments = </span><span class="p">[</span><span class="nx">@makeCode</span><span class="p">(</span><span class="s">"</span><span class="si">#{</span><span class="nx">kvar</span><span class="si">}</span><span class="s"> in </span><span class="si">#{</span><span class="nx">svar</span><span class="si">}</span><span class="s">"</span><span class="p">)]</span>
|
|
<span class="nv">guardPart = </span><span class="s">"\n</span><span class="si">#{</span><span class="nx">idt1</span><span class="si">}</span><span class="s">if (!</span><span class="si">#{</span><span class="nx">utility</span> <span class="s">'hasProp'</span><span class="si">}</span><span class="s">.call(</span><span class="si">#{</span><span class="nx">svar</span><span class="si">}</span><span class="s">, </span><span class="si">#{</span><span class="nx">kvar</span><span class="si">}</span><span class="s">)) continue;"</span> <span class="k">if</span> <span class="nx">@</span><span class="k">own</span>
|
|
<span class="nv">bodyFragments = </span><span class="nx">body</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nv">indent: </span><span class="nx">idt1</span><span class="p">),</span> <span class="nx">LEVEL_TOP</span>
|
|
<span class="k">if</span> <span class="nx">bodyFragments</span> <span class="o">and</span> <span class="p">(</span><span class="nx">bodyFragments</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span>
|
|
<span class="nv">bodyFragments = </span><span class="p">[].</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"\n"</span><span class="p">),</span> <span class="nx">bodyFragments</span><span class="p">,</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"\n"</span><span class="p">)</span>
|
|
<span class="p">[].</span><span class="nx">concat</span> <span class="nx">defPartFragments</span><span class="p">,</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"</span><span class="si">#{</span><span class="nx">resultPart</span> <span class="o">or</span> <span class="s">''</span><span class="si">}#{</span><span class="nx">@tab</span><span class="si">}</span><span class="s">for ("</span><span class="p">),</span>
|
|
<span class="nx">forPartFragments</span><span class="p">,</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">") {</span><span class="si">#{</span><span class="nx">guardPart</span><span class="si">}#{</span><span class="nx">varPart</span><span class="si">}</span><span class="s">"</span><span class="p">),</span> <span class="nx">bodyFragments</span><span class="p">,</span>
|
|
<span class="nx">@makeCode</span><span class="p">(</span><span class="s">"</span><span class="si">#{</span><span class="nx">@tab</span><span class="si">}</span><span class="s">}</span><span class="si">#{</span><span class="nx">returnResult</span> <span class="o">or</span> <span class="s">''</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
|
|
|
|
<span class="nv">pluckDirectCall: </span><span class="nf">(o, body) -></span>
|
|
<span class="nv">defs = </span><span class="p">[]</span>
|
|
<span class="k">for</span> <span class="nx">expr</span><span class="p">,</span> <span class="nx">idx</span> <span class="k">in</span> <span class="nx">body</span><span class="p">.</span><span class="nx">expressions</span>
|
|
<span class="nv">expr = </span><span class="nx">expr</span><span class="p">.</span><span class="nx">unwrapAll</span><span class="p">()</span>
|
|
<span class="k">continue</span> <span class="k">unless</span> <span class="nx">expr</span> <span class="k">instanceof</span> <span class="nx">Call</span>
|
|
<span class="nv">val = </span><span class="nx">expr</span><span class="p">.</span><span class="nx">variable</span><span class="p">.</span><span class="nx">unwrapAll</span><span class="p">()</span>
|
|
<span class="k">continue</span> <span class="k">unless</span> <span class="p">(</span><span class="nx">val</span> <span class="k">instanceof</span> <span class="nx">Code</span><span class="p">)</span> <span class="o">or</span>
|
|
<span class="p">(</span><span class="nx">val</span> <span class="k">instanceof</span> <span class="nx">Value</span> <span class="o">and</span>
|
|
<span class="nx">val</span><span class="p">.</span><span class="nx">base</span><span class="o">?</span><span class="p">.</span><span class="nx">unwrapAll</span><span class="p">()</span> <span class="k">instanceof</span> <span class="nx">Code</span> <span class="o">and</span>
|
|
<span class="nx">val</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">length</span> <span class="o">is</span> <span class="mi">1</span> <span class="o">and</span>
|
|
<span class="nx">val</span><span class="p">.</span><span class="nx">properties</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">name</span><span class="o">?</span><span class="p">.</span><span class="nx">value</span> <span class="k">in</span> <span class="p">[</span><span class="s">'call'</span><span class="p">,</span> <span class="s">'apply'</span><span class="p">])</span>
|
|
<span class="nv">fn = </span><span class="nx">val</span><span class="p">.</span><span class="nx">base</span><span class="o">?</span><span class="p">.</span><span class="nx">unwrapAll</span><span class="p">()</span> <span class="o">or</span> <span class="nx">val</span>
|
|
<span class="nv">ref = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s">'fn'</span>
|
|
<span class="nv">base = </span><span class="k">new</span> <span class="nx">Value</span> <span class="nx">ref</span>
|
|
<span class="k">if</span> <span class="nx">val</span><span class="p">.</span><span class="nx">base</span>
|
|
<span class="p">[</span><span class="nx">val</span><span class="p">.</span><span class="nx">base</span><span class="p">,</span> <span class="nx">base</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">base</span><span class="p">,</span> <span class="nx">val</span><span class="p">]</span>
|
|
<span class="nx">body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">[</span><span class="nx">idx</span><span class="p">]</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Call</span> <span class="nx">base</span><span class="p">,</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">args</span>
|
|
<span class="nv">defs = </span><span class="nx">defs</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="nx">@tab</span><span class="p">),</span> <span class="p">(</span><span class="k">new</span> <span class="nx">Assign</span><span class="p">(</span><span class="nx">ref</span><span class="p">,</span> <span class="nx">fn</span><span class="p">).</span><span class="nx">compileToFragments</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_TOP</span><span class="p">)),</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">';\n'</span><span class="p">)</span>
|
|
<span class="nx">defs</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-123">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-123">¶</a>
|
|
</div>
|
|
|
|
<h3>Switch</h3>
|
|
<p>A JavaScript <em>switch</em> statement. Converts into a returnable expression on-demand.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre><span class="nv">exports.Switch = </span><span class="k">class</span> <span class="nx">Switch</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(@subject, @cases, @otherwise) -></span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'subject'</span><span class="p">,</span> <span class="s">'cases'</span><span class="p">,</span> <span class="s">'otherwise'</span><span class="p">]</span>
|
|
|
|
<span class="nv">isStatement: </span><span class="nx">YES</span>
|
|
|
|
<span class="nv">jumps: </span><span class="nf">(o = {block: yes}) -></span>
|
|
<span class="k">for</span> <span class="p">[</span><span class="nx">conds</span><span class="p">,</span> <span class="nx">block</span><span class="p">]</span> <span class="k">in</span> <span class="nx">@cases</span>
|
|
<span class="k">return</span> <span class="nx">block</span> <span class="k">if</span> <span class="nx">block</span><span class="p">.</span><span class="nx">jumps</span> <span class="nx">o</span>
|
|
<span class="nx">@otherwise</span><span class="o">?</span><span class="p">.</span><span class="nx">jumps</span> <span class="nx">o</span>
|
|
|
|
<span class="nv">makeReturn: </span><span class="nf">(res) -></span>
|
|
<span class="nx">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">makeReturn</span> <span class="nx">res</span> <span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">@cases</span>
|
|
<span class="nx">@otherwise</span> <span class="o">or=</span> <span class="k">new</span> <span class="nx">Block</span> <span class="p">[</span><span class="k">new</span> <span class="nx">Literal</span> <span class="s">'void 0'</span><span class="p">]</span> <span class="k">if</span> <span class="nx">res</span>
|
|
<span class="nx">@otherwise</span><span class="o">?</span><span class="p">.</span><span class="nx">makeReturn</span> <span class="nx">res</span>
|
|
<span class="k">this</span>
|
|
|
|
<span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="nv">idt1 = </span><span class="nx">o</span><span class="p">.</span><span class="nx">indent</span> <span class="o">+</span> <span class="nx">TAB</span>
|
|
<span class="nv">idt2 = o.indent = </span><span class="nx">idt1</span> <span class="o">+</span> <span class="nx">TAB</span>
|
|
<span class="nv">fragments = </span><span class="p">[].</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="nx">@tab</span> <span class="o">+</span> <span class="s">"switch ("</span><span class="p">),</span>
|
|
<span class="p">(</span><span class="k">if</span> <span class="nx">@subject</span> <span class="k">then</span> <span class="nx">@subject</span><span class="p">.</span><span class="nx">compileToFragments</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_PAREN</span><span class="p">)</span> <span class="k">else</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"false"</span><span class="p">)),</span>
|
|
<span class="nx">@makeCode</span><span class="p">(</span><span class="s">") {\n"</span><span class="p">)</span>
|
|
<span class="k">for</span> <span class="p">[</span><span class="nx">conditions</span><span class="p">,</span> <span class="nx">block</span><span class="p">],</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">@cases</span>
|
|
<span class="k">for</span> <span class="nx">cond</span> <span class="k">in</span> <span class="nx">flatten</span> <span class="p">[</span><span class="nx">conditions</span><span class="p">]</span>
|
|
<span class="nv">cond = </span><span class="nx">cond</span><span class="p">.</span><span class="nx">invert</span><span class="p">()</span> <span class="k">unless</span> <span class="nx">@subject</span>
|
|
<span class="nv">fragments = </span><span class="nx">fragments</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="nx">idt1</span> <span class="o">+</span> <span class="s">"case "</span><span class="p">),</span> <span class="nx">cond</span><span class="p">.</span><span class="nx">compileToFragments</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_PAREN</span><span class="p">),</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">":\n"</span><span class="p">)</span>
|
|
<span class="nv">fragments = </span><span class="nx">fragments</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">body</span><span class="p">,</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">'\n'</span><span class="p">)</span> <span class="k">if</span> <span class="p">(</span><span class="nv">body = </span><span class="nx">block</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_TOP</span><span class="p">).</span><span class="nx">length</span> <span class="o">></span> <span class="mi">0</span>
|
|
<span class="k">break</span> <span class="k">if</span> <span class="nx">i</span> <span class="o">is</span> <span class="nx">@cases</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@otherwise</span>
|
|
<span class="nv">expr = </span><span class="nx">@lastNonComment</span> <span class="nx">block</span><span class="p">.</span><span class="nx">expressions</span>
|
|
<span class="k">continue</span> <span class="k">if</span> <span class="nx">expr</span> <span class="k">instanceof</span> <span class="nx">Return</span> <span class="o">or</span> <span class="p">(</span><span class="nx">expr</span> <span class="k">instanceof</span> <span class="nx">Literal</span> <span class="o">and</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">jumps</span><span class="p">()</span> <span class="o">and</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">value</span> <span class="o">isnt</span> <span class="s">'debugger'</span><span class="p">)</span>
|
|
<span class="nx">fragments</span><span class="p">.</span><span class="nx">push</span> <span class="nx">cond</span><span class="p">.</span><span class="nx">makeCode</span><span class="p">(</span><span class="nx">idt2</span> <span class="o">+</span> <span class="s">'break;\n'</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nx">@otherwise</span> <span class="o">and</span> <span class="nx">@otherwise</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">length</span>
|
|
<span class="nx">fragments</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="nx">idt1</span> <span class="o">+</span> <span class="s">"default:\n"</span><span class="p">),</span> <span class="p">(</span><span class="nx">@otherwise</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_TOP</span><span class="p">)...,</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"\n"</span><span class="p">)</span>
|
|
<span class="nx">fragments</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@makeCode</span> <span class="nx">@tab</span> <span class="o">+</span> <span class="s">'}'</span>
|
|
<span class="nx">fragments</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-124">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-124">¶</a>
|
|
</div>
|
|
|
|
<h3>If</h3>
|
|
<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><span class="nv">exports.If = </span><span class="k">class</span> <span class="nx">If</span> <span class="k">extends</span> <span class="nx">Base</span>
|
|
<span class="nv">constructor: </span><span class="nf">(condition, @body, options = {}) -></span>
|
|
<span class="vi">@condition = </span><span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s">'unless'</span> <span class="k">then</span> <span class="nx">condition</span><span class="p">.</span><span class="nx">invert</span><span class="p">()</span> <span class="k">else</span> <span class="nx">condition</span>
|
|
<span class="vi">@elseBody = </span><span class="kc">null</span>
|
|
<span class="vi">@isChain = </span><span class="kc">false</span>
|
|
<span class="p">{</span><span class="nx">@soak</span><span class="p">}</span> <span class="o">=</span> <span class="nx">options</span>
|
|
|
|
<span class="nv">children: </span><span class="p">[</span><span class="s">'condition'</span><span class="p">,</span> <span class="s">'body'</span><span class="p">,</span> <span class="s">'elseBody'</span><span class="p">]</span>
|
|
|
|
<span class="nv">bodyNode: </span> <span class="nf">-></span> <span class="nx">@body</span><span class="o">?</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span>
|
|
<span class="nv">elseBodyNode: </span><span class="nf">-></span> <span class="nx">@elseBody</span><span class="o">?</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-125">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-125">¶</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> <span class="nv">addElse: </span><span class="nf">(elseBody) -></span>
|
|
<span class="k">if</span> <span class="nx">@isChain</span>
|
|
<span class="nx">@elseBodyNode</span><span class="p">().</span><span class="nx">addElse</span> <span class="nx">elseBody</span>
|
|
<span class="k">else</span>
|
|
<span class="vi">@isChain = </span><span class="nx">elseBody</span> <span class="k">instanceof</span> <span class="nx">If</span>
|
|
<span class="vi">@elseBody = </span><span class="nx">@ensureBlock</span> <span class="nx">elseBody</span>
|
|
<span class="k">this</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-126">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-126">¶</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> <span class="nv">isStatement: </span><span class="nf">(o) -></span>
|
|
<span class="nx">o</span><span class="o">?</span><span class="p">.</span><span class="nx">level</span> <span class="o">is</span> <span class="nx">LEVEL_TOP</span> <span class="o">or</span>
|
|
<span class="nx">@bodyNode</span><span class="p">().</span><span class="nx">isStatement</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">or</span> <span class="nx">@elseBodyNode</span><span class="p">()</span><span class="o">?</span><span class="p">.</span><span class="nx">isStatement</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
|
|
|
|
<span class="nv">jumps: </span><span class="nf">(o) -></span> <span class="nx">@body</span><span class="p">.</span><span class="nx">jumps</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">or</span> <span class="nx">@elseBody</span><span class="o">?</span><span class="p">.</span><span class="nx">jumps</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
|
|
|
|
<span class="nv">compileNode: </span><span class="nf">(o) -></span>
|
|
<span class="k">if</span> <span class="nx">@isStatement</span> <span class="nx">o</span> <span class="k">then</span> <span class="nx">@compileStatement</span> <span class="nx">o</span> <span class="k">else</span> <span class="nx">@compileExpression</span> <span class="nx">o</span>
|
|
|
|
<span class="nv">makeReturn: </span><span class="nf">(res) -></span>
|
|
<span class="nx">@elseBody</span> <span class="o">or=</span> <span class="k">new</span> <span class="nx">Block</span> <span class="p">[</span><span class="k">new</span> <span class="nx">Literal</span> <span class="s">'void 0'</span><span class="p">]</span> <span class="k">if</span> <span class="nx">res</span>
|
|
<span class="nx">@body</span> <span class="o">and=</span> <span class="k">new</span> <span class="nx">Block</span> <span class="p">[</span><span class="nx">@body</span><span class="p">.</span><span class="nx">makeReturn</span> <span class="nx">res</span><span class="p">]</span>
|
|
<span class="nx">@elseBody</span> <span class="o">and=</span> <span class="k">new</span> <span class="nx">Block</span> <span class="p">[</span><span class="nx">@elseBody</span><span class="p">.</span><span class="nx">makeReturn</span> <span class="nx">res</span><span class="p">]</span>
|
|
<span class="k">this</span>
|
|
|
|
<span class="nv">ensureBlock: </span><span class="nf">(node) -></span>
|
|
<span class="k">if</span> <span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Block</span> <span class="k">then</span> <span class="nx">node</span> <span class="k">else</span> <span class="k">new</span> <span class="nx">Block</span> <span class="p">[</span><span class="nx">node</span><span class="p">]</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-127">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-127">¶</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> <span class="nv">compileStatement: </span><span class="nf">(o) -></span>
|
|
<span class="nv">child = </span><span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s">'chainChild'</span>
|
|
<span class="nv">exeq = </span><span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s">'isExistentialEquals'</span>
|
|
|
|
<span class="k">if</span> <span class="nx">exeq</span>
|
|
<span class="k">return</span> <span class="k">new</span> <span class="nx">If</span><span class="p">(</span><span class="nx">@condition</span><span class="p">.</span><span class="nx">invert</span><span class="p">(),</span> <span class="nx">@elseBodyNode</span><span class="p">(),</span> <span class="nv">type: </span><span class="s">'if'</span><span class="p">).</span><span class="nx">compileToFragments</span> <span class="nx">o</span>
|
|
|
|
<span class="nv">indent = </span><span class="nx">o</span><span class="p">.</span><span class="nx">indent</span> <span class="o">+</span> <span class="nx">TAB</span>
|
|
<span class="nv">cond = </span><span class="nx">@condition</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_PAREN</span>
|
|
<span class="nv">body = </span><span class="nx">@ensureBlock</span><span class="p">(</span><span class="nx">@body</span><span class="p">).</span><span class="nx">compileToFragments</span> <span class="nx">merge</span> <span class="nx">o</span><span class="p">,</span> <span class="p">{</span><span class="nx">indent</span><span class="p">}</span>
|
|
<span class="nv">ifPart = </span><span class="p">[].</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"if ("</span><span class="p">),</span> <span class="nx">cond</span><span class="p">,</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">") {\n"</span><span class="p">),</span> <span class="nx">body</span><span class="p">,</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"\n</span><span class="si">#{</span><span class="nx">@tab</span><span class="si">}</span><span class="s">}"</span><span class="p">)</span>
|
|
<span class="nx">ifPart</span><span class="p">.</span><span class="nx">unshift</span> <span class="nx">@makeCode</span> <span class="nx">@tab</span> <span class="k">unless</span> <span class="nx">child</span>
|
|
<span class="k">return</span> <span class="nx">ifPart</span> <span class="k">unless</span> <span class="nx">@elseBody</span>
|
|
<span class="nv">answer = </span><span class="nx">ifPart</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">' else '</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nx">@isChain</span>
|
|
<span class="nv">o.chainChild = </span><span class="kc">yes</span>
|
|
<span class="nv">answer = </span><span class="nx">answer</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">@elseBody</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">().</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_TOP</span>
|
|
<span class="k">else</span>
|
|
<span class="nv">answer = </span><span class="nx">answer</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"{\n"</span><span class="p">),</span> <span class="nx">@elseBody</span><span class="p">.</span><span class="nx">compileToFragments</span><span class="p">(</span><span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="p">{</span><span class="nx">indent</span><span class="p">}),</span> <span class="nx">LEVEL_TOP</span><span class="p">),</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">"\n</span><span class="si">#{</span><span class="nx">@tab</span><span class="si">}</span><span class="s">}"</span><span class="p">)</span>
|
|
<span class="nx">answer</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-128">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-128">¶</a>
|
|
</div>
|
|
|
|
<p>Compile the <code>If</code> as a conditional operator.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">compileExpression: </span><span class="nf">(o) -></span>
|
|
<span class="nv">cond = </span><span class="nx">@condition</span><span class="p">.</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_COND</span>
|
|
<span class="nv">body = </span><span class="nx">@bodyNode</span><span class="p">().</span><span class="nx">compileToFragments</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
|
|
<span class="nv">alt = </span><span class="k">if</span> <span class="nx">@elseBodyNode</span><span class="p">()</span> <span class="k">then</span> <span class="nx">@elseBodyNode</span><span class="p">().</span><span class="nx">compileToFragments</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span><span class="p">)</span> <span class="k">else</span> <span class="p">[</span><span class="nx">@makeCode</span><span class="p">(</span><span class="s">'void 0'</span><span class="p">)]</span>
|
|
<span class="nv">fragments = </span><span class="nx">cond</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">" ? "</span><span class="p">),</span> <span class="nx">body</span><span class="p">,</span> <span class="nx">@makeCode</span><span class="p">(</span><span class="s">" : "</span><span class="p">),</span> <span class="nx">alt</span>
|
|
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o">>=</span> <span class="nx">LEVEL_COND</span> <span class="k">then</span> <span class="nx">@wrapInBraces</span> <span class="nx">fragments</span> <span class="k">else</span> <span class="nx">fragments</span>
|
|
|
|
<span class="nv">unfoldSoak: </span><span class="nf">-></span>
|
|
<span class="nx">@soak</span> <span class="o">and</span> <span class="k">this</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-129">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-129">¶</a>
|
|
</div>
|
|
|
|
<h2>Faux-Nodes</h2>
|
|
<p>Faux-nodes are never created by the grammar, but are used during code
|
|
generation to generate other combinations of nodes.
|
|
|
|
</p>
|
|
<h3>Closure</h3>
|
|
<p>A faux-node used to wrap an expressions body in a closure.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre><span class="nv">Closure =</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-130">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-130">¶</a>
|
|
</div>
|
|
|
|
<p>Wrap the expressions body, unless it contains a pure statement,
|
|
in which case, no dice. If the body mentions <code>this</code> or <code>arguments</code>,
|
|
then make sure that the closure wrapper preserves the original values.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">wrap: </span><span class="nf">(expressions, statement, noReturn) -></span>
|
|
<span class="k">return</span> <span class="nx">expressions</span> <span class="k">if</span> <span class="nx">expressions</span><span class="p">.</span><span class="nx">jumps</span><span class="p">()</span>
|
|
<span class="nv">func = </span><span class="k">new</span> <span class="nx">Code</span> <span class="p">[],</span> <span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">expressions</span><span class="p">]</span>
|
|
<span class="nv">args = </span><span class="p">[]</span>
|
|
<span class="nv">argumentsNode = </span><span class="nx">expressions</span><span class="p">.</span><span class="nx">contains</span> <span class="nx">@isLiteralArguments</span>
|
|
<span class="k">if</span> <span class="nx">argumentsNode</span> <span class="o">and</span> <span class="nx">expressions</span><span class="p">.</span><span class="nx">classBody</span>
|
|
<span class="nx">argumentsNode</span><span class="p">.</span><span class="nx">error</span> <span class="s">"Class bodies shouldn't reference arguments"</span>
|
|
<span class="k">if</span> <span class="nx">argumentsNode</span> <span class="o">or</span> <span class="nx">expressions</span><span class="p">.</span><span class="nx">contains</span> <span class="nx">@isLiteralThis</span>
|
|
<span class="nv">meth = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="k">if</span> <span class="nx">argumentsNode</span> <span class="k">then</span> <span class="s">'apply'</span> <span class="k">else</span> <span class="s">'call'</span>
|
|
<span class="nv">args = </span><span class="p">[</span><span class="k">new</span> <span class="nx">Literal</span> <span class="s">'this'</span><span class="p">]</span>
|
|
<span class="nx">args</span><span class="p">.</span><span class="nx">push</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">'arguments'</span> <span class="k">if</span> <span class="nx">argumentsNode</span>
|
|
<span class="nv">func = </span><span class="k">new</span> <span class="nx">Value</span> <span class="nx">func</span><span class="p">,</span> <span class="p">[</span><span class="k">new</span> <span class="nx">Access</span> <span class="nx">meth</span><span class="p">]</span>
|
|
<span class="nv">func.noReturn = </span><span class="nx">noReturn</span>
|
|
<span class="nv">call = </span><span class="k">new</span> <span class="nx">Call</span> <span class="nx">func</span><span class="p">,</span> <span class="nx">args</span>
|
|
<span class="k">if</span> <span class="nx">statement</span> <span class="k">then</span> <span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">call</span><span class="p">]</span> <span class="k">else</span> <span class="nx">call</span>
|
|
|
|
<span class="nv">isLiteralArguments: </span><span class="nf">(node) -></span>
|
|
<span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Literal</span> <span class="o">and</span> <span class="nx">node</span><span class="p">.</span><span class="nx">value</span> <span class="o">is</span> <span class="s">'arguments'</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">node</span><span class="p">.</span><span class="nx">asKey</span>
|
|
|
|
<span class="nv">isLiteralThis: </span><span class="nf">(node) -></span>
|
|
<span class="p">(</span><span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Literal</span> <span class="o">and</span> <span class="nx">node</span><span class="p">.</span><span class="nx">value</span> <span class="o">is</span> <span class="s">'this'</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">node</span><span class="p">.</span><span class="nx">asKey</span><span class="p">)</span> <span class="o">or</span>
|
|
<span class="p">(</span><span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Code</span> <span class="o">and</span> <span class="nx">node</span><span class="p">.</span><span class="nx">bound</span><span class="p">)</span> <span class="o">or</span>
|
|
<span class="p">(</span><span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Call</span> <span class="o">and</span> <span class="nx">node</span><span class="p">.</span><span class="nx">isSuper</span><span class="p">)</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-131">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-131">¶</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="nv">unfoldSoak = </span><span class="nf">(o, parent, name) -></span>
|
|
<span class="k">return</span> <span class="k">unless</span> <span class="nv">ifn = </span><span class="nx">parent</span><span class="p">[</span><span class="nx">name</span><span class="p">].</span><span class="nx">unfoldSoak</span> <span class="nx">o</span>
|
|
<span class="nx">parent</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="nx">ifn</span><span class="p">.</span><span class="nx">body</span>
|
|
<span class="nv">ifn.body = </span><span class="k">new</span> <span class="nx">Value</span> <span class="nx">parent</span>
|
|
<span class="nx">ifn</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-132">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-132">¶</a>
|
|
</div>
|
|
|
|
<h2>Constants</h2>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre><span class="nv">UTILITIES =</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-133">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-133">¶</a>
|
|
</div>
|
|
|
|
<p>Correctly set up a prototype chain for inheritance, including a reference
|
|
to the superclass for <code>super()</code> calls, and copies of any static properties.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="k">extends</span><span class="o">:</span> <span class="nf">-></span> <span class="s">"""</span>
|
|
<span class="s"> function(child, parent) { for (var key in parent) { if (</span><span class="si">#{</span><span class="nx">utility</span> <span class="s">'hasProp'</span><span class="si">}</span><span class="s">.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }</span>
|
|
<span class="s"> """</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-134">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-134">¶</a>
|
|
</div>
|
|
|
|
<p>Create a function bound to the current value of "this".
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">bind: </span><span class="nf">-></span> <span class="s">'''</span>
|
|
<span class="s"> function(fn, me){ return function(){ return fn.apply(me, arguments); }; }</span>
|
|
<span class="s"> '''</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-135">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-135">¶</a>
|
|
</div>
|
|
|
|
<p>Discover if an item is in an array.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">indexOf: </span><span class="nf">-></span> <span class="s">"""</span>
|
|
<span class="s"> [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }</span>
|
|
<span class="s"> """</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-136">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-136">¶</a>
|
|
</div>
|
|
|
|
<p>Shortcuts to speed up the lookup time for native functions.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre> <span class="nv">hasProp: </span><span class="nf">-></span> <span class="s">'{}.hasOwnProperty'</span>
|
|
<span class="nv">slice : </span><span class="nf">-></span> <span class="s">'[].slice'</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-137">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-137">¶</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><span class="nv">LEVEL_TOP = </span><span class="mi">1</span> <span class="c1"># ...;</span>
|
|
<span class="nv">LEVEL_PAREN = </span><span class="mi">2</span> <span class="c1"># (...)</span>
|
|
<span class="nv">LEVEL_LIST = </span><span class="mi">3</span> <span class="c1"># [...]</span>
|
|
<span class="nv">LEVEL_COND = </span><span class="mi">4</span> <span class="c1"># ... ? x : y</span>
|
|
<span class="nv">LEVEL_OP = </span><span class="mi">5</span> <span class="c1"># !...</span>
|
|
<span class="nv">LEVEL_ACCESS = </span><span class="mi">6</span> <span class="c1"># ...[0]</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-138">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-138">¶</a>
|
|
</div>
|
|
|
|
<p>Tabs are two spaces for pretty printing.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre><span class="nv">TAB = </span><span class="s">' '</span>
|
|
|
|
<span class="nv">IDENTIFIER_STR = </span><span class="s">"[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*"</span>
|
|
<span class="nv">IDENTIFIER = </span><span class="sr">/// ^ </span><span class="si">#{</span><span class="nx">IDENTIFIER_STR</span><span class="si">}</span><span class="sr"> $ ///</span>
|
|
<span class="nv">SIMPLENUM = </span><span class="sr">/^[+-]?\d+$/</span>
|
|
<span class="nv">METHOD_DEF = </span><span class="sr">///</span>
|
|
<span class="sr"> ^</span>
|
|
<span class="sr"> (?:</span>
|
|
<span class="sr"> (</span><span class="si">#{</span><span class="nx">IDENTIFIER_STR</span><span class="si">}</span><span class="sr">)</span>
|
|
<span class="sr"> \.prototype</span>
|
|
<span class="sr"> (?:</span>
|
|
<span class="sr"> \.(</span><span class="si">#{</span><span class="nx">IDENTIFIER_STR</span><span class="si">}</span><span class="sr">)</span>
|
|
<span class="sr"> | \[("(?:[^\\"\r\n]|\\.)*"|'(?:[^\\'\r\n]|\\.)*')\]</span>
|
|
<span class="sr"> | \[(0x[\da-fA-F]+ | \d*\.?\d+ (?:[eE][+-]?\d+)?)\]</span>
|
|
<span class="sr"> )</span>
|
|
<span class="sr"> )</span>
|
|
<span class="sr"> |</span>
|
|
<span class="sr"> (</span><span class="si">#{</span><span class="nx">IDENTIFIER_STR</span><span class="si">}</span><span class="sr">)</span>
|
|
<span class="sr"> $</span>
|
|
<span class="sr">///</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-139">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-139">¶</a>
|
|
</div>
|
|
|
|
<p>Is a literal value a string?
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre><span class="nv">IS_STRING = </span><span class="sr">/^['"]/</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-140">
|
|
<div class="annotation">
|
|
<div class="pilwrap">
|
|
<a class="pilcrow" href="#section-140">¶</a>
|
|
</div>
|
|
|
|
<h2>Utility Functions</h2>
|
|
<p>Helper for ensuring that utility functions are assigned at the top level.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class="highlight"><pre><span class="nv">utility = </span><span class="nf">(name) -></span>
|
|
<span class="nv">ref = </span><span class="s">"__</span><span class="si">#{</span><span class="nx">name</span><span class="si">}</span><span class="s">"</span>
|
|
<span class="nx">Scope</span><span class="p">.</span><span class="nx">root</span><span class="p">.</span><span class="nx">assign</span> <span class="nx">ref</span><span class="p">,</span> <span class="nx">UTILITIES</span><span class="p">[</span><span class="nx">name</span><span class="p">]()</span>
|
|
<span class="nx">ref</span>
|
|
|
|
<span class="nv">multident = </span><span class="nf">(code, tab) -></span>
|
|
<span class="nv">code = </span><span class="nx">code</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\n/g</span><span class="p">,</span> <span class="s">'$&'</span> <span class="o">+</span> <span class="nx">tab</span>
|
|
<span class="nx">code</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\s+$/</span><span class="p">,</span> <span class="s">''</span>
|
|
|
|
</pre></div></div>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</div>
|
|
</body>
|
|
</html>
|