<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="97511" data-post-id="97511">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="OvermindDL1" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/OvermindDL1/120/2677_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  OvermindDL1
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="NobbZ" data-post="9" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/nobbz/48/27235_2.png" class="avatar"> NobbZ:</div>
<blockquote>
<p>What you probably mean here is the comma <code>,</code> , which is used to build “sequences”:</p>
</blockquote>
</aside>
<p>Yes I did!  I’ve been doing too much OCaml and got them mixed up, it is <code>,</code>, like in C++ (and in C++ you can even override <code>operator,</code>, lol).  <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<aside class="quote no-group" data-username="tmbb" data-post="11" data-topic="16533" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>I can’t edit my post anymore, so could a nice mod please add something to the effect that semicolons should be replaced by commas?</p>
</blockquote>
</aside>
<p>Edited, it look good?  Sorry for the mis-remembering, the comma is like the comma operator in C++, I need to remember it that way.  ^.^</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="97511" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenixundeadview-lets-discuss-optimization-possibilities-for-something-like-phoenix-liveview/16533/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-97511" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="97511"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #11"></div>
  </section>
</div>
    <div class="postbit" id="98189" data-post-id="98189">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I’ve managed to write a pretty functional proof of concept that doesn’t require AST rewriting of complex quoted expressions. Code is here:</p>
<p>I can generate “full” templates as well as templated containing only the static and dynamic parts of the template, for easier diffing over the network. As a positive side-effect, I my template engines generate code which is much cleaner than the code generated by the engine in Phoenix.HTML, and it might even be slightly faster.</p>
<p>I should benchmark it one of these days.</p>
<p>EDIT: code here: <a href="https://github.com/tmbb/phoenix_undead_view/blob/master/README.md#phoenixundeadview" class="inline-onebox" rel="noopener nofollow ugc">phoenix_undead_view/README.md at master · tmbb/phoenix_undead_view · GitHub</a></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="98189" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenixundeadview-lets-discuss-optimization-possibilities-for-something-like-phoenix-liveview/16533/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-98189" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="98189"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #12"></div>
  </section>
</div>
    <div class="postbit" id="98323" data-post-id="98323">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Link to the relevant engine? I think you have a couple ones around, so I am not sure which one I should look at. <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="98323" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenixundeadview-lets-discuss-optimization-possibilities-for-something-like-phoenix-liveview/16533/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-98323" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="98323"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #13"></div>
  </section>
</div>
    <div class="postbit" id="98339" data-post-id="98339">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>There are <a href="https://github.com/tmbb/phoenix_undead_view/tree/master/lib/phoenix_undead_view/eex_engine/engines" rel="noopener nofollow ugc">4 engines</a>. Only the following 3 are important (the other one is a relic which I keep around for reference purposes):</p>
<ul>
<li>
<p><a href="https://github.com/tmbb/phoenix_undead_view/blob/master/lib/phoenix_undead_view/eex_engine/engines/undead_engine_full.ex" rel="noopener nofollow ugc">UndeadEngineFull</a> - generates the full webpage/component, for the initial server-side rendering. This is the equivalent to what <a href="https://github.com/phoenixframework/phoenix_html/blob/v2.12.0/lib/phoenix_html/engine.ex#L1" rel="noopener nofollow ugc">Phoenix.HTML.Engine</a> does already (and as you can see, the code was mostly copied from there). This template generates the following code: <a href="https://github.com/tmbb/phoenix_undead_view/blob/master/examples/example-quoted-full.exs" rel="noopener nofollow ugc">quoted expressions</a>; <a href="https://github.com/tmbb/phoenix_undead_view/blob/master/examples/example-code-full.exs" rel="noopener nofollow ugc">code</a>. The result is rendered to a list of alternating static and dynamic elements (i.e. static, dynamic, static, dynamic, …, dynamic, static). The list always starts and ends with a binary (even if it i an empty one <code>""</code>), to make it easier to render the full text from diffs, but this can be optimized away if you don’t need diffing (and normal Phoenix templates don’t need it).</p>
</li>
<li>
<p><a href="https://github.com/tmbb/phoenix_undead_view/blob/master/lib/phoenix_undead_view/eex_engine/engines/undead_engine_dynamic_parts.ex" rel="noopener nofollow ugc">UndeadEngineDynamicParts</a> - This engine renders only the dynamic parts rendered by the above template. The goal would be to render only the parts that change, send them over the network, and join them with the static parts on the client.</p>
</li>
<li>
<p><a href="https://github.com/tmbb/phoenix_undead_view/blob/master/lib/phoenix_undead_view/eex_engine/engines/undead_engine_static_parts.ex" rel="noopener nofollow ugc">UndeadEngineStaticParts</a> - This engine renders only the static parts. The goal is to send these parts to the client only once so that the client knows how to merge the dynamic parts into the DOM. I think of this as a diff of the template (even though we are always diffing agains the static part, and not against the previous version)</p>
</li>
</ul>
<p>A normal page render requires sending the output of the Full engine (as the literal DOM) and the StaticParts engine (compiled into a Javascript function that knows how to concat the dynamic parts it will receive later). Whenever the server wants to change the DOM on the client, it must run the DynamicParts engine (and only this one!) and send the list into the client, which will merge the dynamic parts into the textual HTML and merge it into the DOM.</p>
<p>If all you want is to compare my engine to Phoenix.HTML.Engine, you only need to look at the <a href="https://github.com/tmbb/phoenix_undead_view/blob/master/examples/example-code-full.exs" rel="noopener nofollow ugc">UndeadEngineFull</a> and at its output. The output of the engine is a quoted expression, but you should format it into source code using <code>Macro.to_string()</code> and <code>Code.format_string!()</code> because the quoted expressions are quite unreadable, even for simple templates.</p>
<p>Now, my 3 engines contain some common functionality. In fact, only the <code>handle_body()</code> callback is different for each engine. To simplify things, I always use a <a href="https://github.com/tmbb/phoenix_undead_view/blob/master/lib/phoenix_undead_view/eex_engine/undead_engine.ex" rel="noopener nofollow ugc">UndeadEngine</a>, which contains the implementations of the common callbacks. Because I didn’t want to define a lot of code in the <code>__using__</code> macro, I’ve put the actual implementation of the callbacks in the <a href="https://github.com/tmbb/phoenix_undead_view/blob/master/lib/phoenix_undead_view/eex_engine/undead_engine_impl.ex" rel="noopener nofollow ugc">UndeadEngineImpl</a> module. While these layers of indirections make my project more complex, they’re kinda required if I want to work on 3 similar engines at the same time, but you don’t need any of these if you only want the Full engine.</p>
<p>I haven’t tested this engine on complex templates, so it’s possible you might find a way of breaking it. I’m not sure I’m scoping the inner variables correctly, but that’s <em>very</em> easy to fix by adding the <code>:counter</code> attribute to the variables, changing the variable names according to the nesting level (which is easy because I can keep track of the nesting level if I want) or by wrapping the inner structures in function calls so that variables don’t leak.</p>
<p>You might need to read the <code>Utils</code> and <code>Merger</code> modules, which build and optimize the final AST.</p>
<p>Maybe the code is too unfinished for you to look at, but I think it’s a good proof of concept even if it leaks some variables in highly nested templates.</p>
<p>EDIT: Problems with variable scoping should be solved now!</p>
<p>PS: if you want we can discuss this over private messages, but I think the discussion might be interesting for the community in general.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="98339" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenixundeadview-lets-discuss-optimization-possibilities-for-something-like-phoenix-liveview/16533/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-98339" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="98339"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #14"></div>
  </section>
</div>
    <div class="postbit" id="98354" data-post-id="98354">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>The main thing that’s missing now from the Undead Engines is a way to expand macros and extract the constant and dynamic parts. That sounds really hard, but it’s not as complex as it might seem…</p>
<p>If you look at the code generated by the engines, it follows a very simple pattern (in fact, the pattern is even a little more restricted than that):</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  {:safe,
    (
      var1 = ...
      var2 = ...
      var3 = ...

      ...

      varn = ...

      [var1, var2, ..., varn]
    )}
</code></pre>
<p>If I can recognize this pattern at compile time, I can “lift” it into a lower level and add the new variables to the lower level. Because the format is generated by my own code, it’s trivial to convert this quoted expression into a more manageable format. I’d be rewriting the AST, but a very simple and well-defined AST fragment. This means that the Engines can’t expand <em>every</em> macro, but they can expand every macro that generates a quoted expression as if it were generated by the Engine, which is a useful subset.</p>
<p>There are possibilities that avoid AST rewriting, like choosing to expand macros inside the Engine, instead of expanding them after the template has been compiled. The problem with that approach is that it only works for “wel behaved” macros, which have a return value that only depends on their arguments and the env <em>outside of the quoted expression</em>. If they depend on variables defined inside the quoted expression, they won’t work. Since we want the semantics of these Engines to be exactly equal to the semantics of the Phoenix.HTML.Engine, I should probably support the general case.</p>
<p>Anyway, supporting macro expansions is not a big deal, because the macros will be expanded anyway when the quoted expression is compiled. This is just an optimization. I’m a little short on time to promise I’ll get all of this to work soon…</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="98354" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenixundeadview-lets-discuss-optimization-possibilities-for-something-like-phoenix-liveview/16533/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-98354" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="98354"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #15"></div>
  </section>
</div>
    <div class="postbit" id="98387" data-post-id="98387">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Great job!</p>
<p>I think we should only have the <code>UndeadEngineFull</code> and we can assume that it will always return something in the shape of <code>{:safe, {:__block__, [], [..., ..., [static, dyamic, ...]}}</code>. This way we can extract static and dynamic out whenever we feel like it.</p>
<p>About macro expansion, I need to put a bit more thought into that. <img src="https://forum.elixirforum.com/images/emoji/apple/frowning.png?v=15" title=":frowning:" class="emoji" alt=":frowning:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="98387" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenixundeadview-lets-discuss-optimization-possibilities-for-something-like-phoenix-liveview/16533/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-98387" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="98387"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #16"></div>
  </section>
</div>
    <div class="postbit" id="98394" data-post-id="98394">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="17" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>This way we can extract static and dynamic out whenever we feel like it.</p>
</blockquote>
</aside>
<p>Yes, that’s totally possible. Having the three engines was mostly an optimization. The <code>UndeadEngineDynamicParts</code> engine was mostly an optimization. Depending on how the BEAM represents static binaries in list having this version might save some memory and time copying the binaries into the list.</p>
<p>Because most of the time templates are mostly large static binaries with small dynamic parts, if you’re copying those binaries into a list you’re wasting <em>a lot</em> of memory.</p>
<p>But you’re more familiar with the BEAM internals than I am.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="98394" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenixundeadview-lets-discuss-optimization-possibilities-for-something-like-phoenix-liveview/16533/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-98394" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="98394"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #17"></div>
  </section>
</div>
    <div class="postbit" id="98397" data-post-id="98397">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="17" data-topic="16533">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>About macro expansion, I need to put a bit more thought into that. <img src="https://forum.elixirforum.com/images/emoji/apple/frowning.png?v=15" title=":frowning:" class="emoji" alt=":frowning:" loading="lazy" width="20" height="20"></p>
</blockquote>
</aside>
<p>Of course. This pet project of mine has always been more about thinking than writing code. You need to understand pretty well what’s happening and where you eant to go before starting to type the code, or you might code your way into a dead end… When you think your way through, the actual code is often obvious.</p>
<p>Anyway, did you understand the basic idea in my explanation? The defails are a little bit involved, but the basics are simple:</p>
<ol>
<li>
<p>“Compile” the text into an abstract list of variable assignments in a format convenient for further transformation, not as literal AST nodes. That’s what my code does currently, as you have probably noticed.</p>
</li>
<li>
<p>Convert the abstract assignments into a quoted expression with (possibly nested) concrete assignments (i.e. literal AST nodes).</p>
</li>
<li>
<p>Expand the macros</p>
</li>
<li>
<p>Convert the quoted expression into the standard abstract format. This is not that hard because the AST was generated by us.</p>
</li>
<li>
<p>Recursively lift expressions matching the <code>{:safe, block}</code> format from lower levels into the upper levels</p>
</li>
<li>
<p>Optimize the resultant abstract lists</p>
</li>
<li>
<p>Compile them into quoted expressions again</p>
</li>
</ol>
<p>This is mostly a repetition of what I said earlier, but, splt into easy understandable steps. The inly tricky step is 4. This is easy to understand conceptually and easy to describe in pseudocode, but not that trivial to implement. Not that it requires anything more clever than tree manipulation, though.</p>
<p>Just to be clear, this is NOT what I’m doing. This is what I’d like to do.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="98397" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenixundeadview-lets-discuss-optimization-possibilities-for-something-like-phoenix-liveview/16533/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-98397" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="98397"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #18"></div>
  </section>
</div>
    <div class="postbit" id="98398" data-post-id="98398">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Bonus (if you can still follow my ramblings):</p>
<p>One “problem” of expanding macros inside the template is that the interesting expressions are “trapped” inside case expressions:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">case(expression_to_macroexpand) do
  {:safe, ...} -&gt; ...
  ...
end
</code></pre>
<p>These expressions are easy to find, but I’m planning on compiling into an intermediate form such as:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">{:__dynamic_expression__, expression_to_macroexpand}
</code></pre>
<p>This is easier to analyze statically than a case statement. Then, when generating the final quoted expression, I can compile these tuples into proper case statements.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="98398" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenixundeadview-lets-discuss-optimization-possibilities-for-something-like-phoenix-liveview/16533/20">Post #19</a>
	                </div>
	            </div>
              <div id="likers-container-98398" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="98398"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #19"></div>
  </section>
</div>
    <div class="postbit" id="98399" data-post-id="98399">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Yup, I do follow everything up. But since you are in experiment land, I would like to suggest for you to finally implement this all directly in the engine instead of doing traversals. Then you only need to look at expressions in the format of <code>{:safe, {:__block__, _, _}}</code> for further inlining.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="98399" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/phoenixundeadview-lets-discuss-optimization-possibilities-for-something-like-phoenix-liveview/16533/21">Post #20</a>
	                </div>
	            </div>
              <div id="likers-container-98399" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="98399"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #20"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/16533/load_more?page=3">Load more posts (121 remaining)</a>
</div></template></turbo-stream>