Overview of Transformer Part 2 
I split it because it got a bit long, but here's the continuation.
 Although it's called an overview, before I realized it, I was reading the details of the specific implementation, but well, perhaps it's a good natural introduction (laughs).
Up to the previous page, we looked at the implementation that generates the template string passed as an argument to the template function.
 Here, we'll look at index management of Block and so on.
registerTemplate 
There is a function called registerTemplate in TransformContext.
131  registerTemplate(): number {
132    if (!this.template) return -1
133    const id = this.pushTemplate(this.template)
134    return (this.dynamic.template = id)
135  }This registerTemplate calls a function called pushTemplate.
123  pushTemplate(content: string): number {
124    const existing = this.ir.template.findIndex(
125      template => template === content,
126    )
127    if (existing !== -1) return existing
128    this.ir.template.push(content)
129    return this.ir.template.length - 1
130  }Templates (strings) are registered into this.ir.template (array).
this.ir is a RootIRNode.
87  constructor(
88    public ir: RootIRNode,That is, here.
56export interface RootIRNode {
57  type: IRNodeTypes.ROOT
58  node: RootNode
59  source: string
60  template: string[]And, this registerTemplate is called in three places.
- At the end of transformNode(only when root)
264  if (context.node.type === NodeTypes.ROOT) {
265    context.registerTemplate()
266  }- After processing children in transformChildren(only when it's a Fragment)
22    if (isFragment) {
23      childContext.reference()
24      childContext.registerTemplate()- When context.enterBlockis called (onExit)
104    return () => {
105      // exit
106      this.registerTemplate()
107      this.block = block
108      this.template = template
109      this.dynamic = dynamic
110      this.childrenTemplate = childrenTemplate
111      this.slots = slots
112      isVFor && this.inVFor--
113    }context.enterBlock is a function called when entering a Block in transformVFor or transformVIf.
 We'll look at this when we see the implementation of compiling v-for and v-if, but for now, it's fine to just grasp 1 and 2.
Regarding 1, there's nothing special, I think.
 In the small component we're reading now, the template is registered here.
 In other words, at this point, this.ir.template is in the state of ["<p>Hello, Vapor!</p>"].
If we have this, we know the index of the template, so,
const t0 = template("<p>Hello, Vapor!</p>");It seems we can generate such code. (We'll actually see this again during codegen.)
In the case of 2, the Fragment, it's when we write a template like:
<template>
  <p>Hello, Vapor 1</p>
  <p>Hello, Vapor 2</p>
  <p>Hello, Vapor 3</p>
</template>In this case, three templates are registered at timing 2.
// this.ir.template
["<p>Hello, Vapor 1</p>", "<p>Hello, Vapor 2</p>", "<p>Hello, Vapor 3</p>"];
const t0 = template("<p>Hello, Vapor 1</p>");
const t1 = template("<p>Hello, Vapor 2</p>");
const t2 = template("<p>Hello, Vapor 3</p>");Return Value of the render Function 
Returning to the discussion about
<template>
  <p>Hello, Vapor!</p>
</template>Let's look back again at the IR obtained from this.
 (Unnecessary parts are omitted)
{
  "type": "RootIRNode",
  "template": ["<p>Hello, Vapor!</p>"],
  "block": {
    "type": "BlockIRNode",
    "returns": [0]
  }
}Looking closely, there's something rather suspicious called "returns": [0].
 From this information, we can understand that the node at index 0 seems to be the return value of the render function.
This is done in transformChildren.
26      if (
27        !(childContext.dynamic.flags & DynamicFlag.NON_TEMPLATE) ||
28        childContext.dynamic.flags & DynamicFlag.INSERT
29      ) {
30        context.block.returns.push(childContext.dynamic.id!)
31      }Under certain conditions, the id of that node is pushed into block.returns.
 This id is calculated from the length when pushTemplate is called.
123  pushTemplate(content: string): number {
124    const existing = this.ir.template.findIndex(
125      template => template === content,
126    )
127    if (existing !== -1) return existing
128    this.ir.template.push(content)
129    return this.ir.template.length - 1
130  }
131  registerTemplate(): number {
132    if (!this.template) return -1
133    const id = this.pushTemplate(this.template)
134    return (this.dynamic.template = id)
135  }And,
Under certain conditions
As to what these conditions are, the first condition is when isFragment is true.
 This is when the node executing transformChildren is one of Root, Element, Template, or Component.
10  const isFragment =
11    node.type === NodeTypes.ROOT ||
12    (node.type === NodeTypes.ELEMENT &&
13      (node.tagType === ElementTypes.TEMPLATE ||
14        node.tagType === ElementTypes.COMPONENT))The second condition is when dynamic.flags is not NON_TEMPLATE or is INSERT.
 (Note: It might look a bit confusing at first glance, but since it's a bitmask, each flag is not exclusive.)
27        !(childContext.dynamic.flags & DynamicFlag.NON_TEMPLATE) ||
28        childContext.dynamic.flags & DynamicFlag.INSERTWhen these two conditions are met, id is pushed into block.returns.
 I think the first condition is fine.
 Regarding the second condition, about dynamic.flags.
dynamic.flags 
dynamic is a property of TransformContext.
74  dynamic: IRDynamicInfo = this.ir.block.dynamic246export interface IRDynamicInfo {
247  id?: number
248  flags: DynamicFlag
249  anchor?: number
250  children: IRDynamicInfo[]
251  template?: number
252}Since context.ir holds this information, its reference is held in TransformContext.
 In particular, this time, the information called DynamicFlag that IRDynamicInfo holds is important, so let's focus on that.
DynamicFlag is a flag that represents what kind of properties a node has.
 The properties are as described in the comments.
230export enum DynamicFlag {
231  NONE = 0,
232  /**
233   * This node is referenced and needs to be saved as a variable.
234   */
235  REFERENCED = 1,
236  /**
237   * This node is not generated from template, but is generated dynamically.
238   */
239  NON_TEMPLATE = 1 << 1,
240  /**
241   * This node needs to be inserted back into the template.
242   */
243  INSERT = 1 << 2,
244}Since it's expressed with bitmasking, each property can coexist.
Let's see when each flag is marked.
DynamicFlag.REFERENCED 
This node is referenced and needs to be saved as a variable.
As stated.
There are two places where DynamicFlag.REFERENCED is set.
- When context.referenceis called.
117  reference(): number {
118    if (this.dynamic.id !== undefined) return this.dynamic.id
119    this.dynamic.flags |= DynamicFlag.REFERENCED
120    return (this.dynamic.id = this.increaseId())
121  }- When IRDynamicInfois generated vianewDynamic(as a default value)
20export const newDynamic = (): IRDynamicInfo => ({
21  flags: DynamicFlag.REFERENCED,
22  children: [],
23})First, in case 1, context.reference is called in quite a few places.
 For example, it's called in the conditional branch when isFragment is true in transformChildren we looked at earlier.
22    if (isFragment) {
23      childContext.reference()
24      childContext.registerTemplate()Then, as for what this flag is used for, it's to generate id when generating code.
 We'll look at this in detail later when we see the implementation of codegen, but nodes with this flag set will generate an id and store it in a variable.
needs to be saved as a variable.
As stated.
It's understandable that this flag is set in isFragment in transformChildren.
 By doing this,
const n0 = t0();
const n1 = t1();
const n2 = t2();We can output code that holds in variables like n${id}.
 Conversely, nodes that don't need to be stored in variables don't have this flag set.
In this case,
const t0 = template("<p>Hello, Vapor!</p>");
function _sfc_render(_ctx) {
  const n0 = t0(); // here
  return n0;
}Since we need to hold n0 in a variable, this flag is set.
DynamicFlag.NON_TEMPLATE 
Next is DynamicFlag.NON_TEMPLATE.
 Whether this flag is set is quite important; if it's not set, id will be pushed into block.returns.
26      if (
27        !(childContext.dynamic.flags & DynamicFlag.NON_TEMPLATE) ||
28        childContext.dynamic.flags & DynamicFlag.INSERT
29      ) {
30        context.block.returns.push(childContext.dynamic.id!)
31      }This node is not generated from template, but is generated dynamically.
As stated, it seems this flag is set for nodes that are not generated from templates but are generated dynamically.
For example, this flag is set in transformComponentElement, transformSlotOutlet, transformVFor, etc.
96  context.dynamic.flags |= DynamicFlag.NON_TEMPLATE | DynamicFlag.INSERT31  context.dynamic.flags |= DynamicFlag.INSERT | DynamicFlag.NON_TEMPLATE50  context.dynamic.flags |= DynamicFlag.NON_TEMPLATE | DynamicFlag.INSERTSkipping a bit, an important point used in combination with this flag is DynamicFlag.INSERT.
DynamicFlag.INSERT 
Whether to push the id into returns is first determined by checking whether DynamicFlag.NON_TEMPLATE is not set.
 If it's not set, it is pushed into returns at this point.
If it is set, we check whether DynamicFlag.INSERT is set.
Looking at
96  context.dynamic.flags |= DynamicFlag.NON_TEMPLATE | DynamicFlag.INSERT31  context.dynamic.flags |= DynamicFlag.INSERT | DynamicFlag.NON_TEMPLATE50  context.dynamic.flags |= DynamicFlag.NON_TEMPLATE | DynamicFlag.INSERTyou can see that Component, SlotOutlet, and v-for have this flag set from the start.
However,
40  context.dynamic.flags |= DynamicFlag.NON_TEMPLATE115  context.dynamic.flags |= DynamicFlag.NON_TEMPLATEdo not have this flag set at this point.
Regarding if, in the case of v-if (not v-else-if or v-else), this flag is set.
41  if (dir.name === 'if') {
42    const id = context.reference()
43    context.dynamic.flags |= DynamicFlag.INSERTAnd in the case of inserted slots like <template #foo>, this flag is not set.
110function transformTemplateSlot(
111  node: ElementNode,
112  dir: VaporDirectiveNode,
113  context: TransformContext<ElementNode>,
114) {
115  context.dynamic.flags |= DynamicFlag.NON_TEMPLATEIn this way, they select what to push into block.returns and what not to.
In the case of our small component, since the DynamicFlag.NON_TEMPLATE flag is not set, id is pushed into block.returns. With this, we've generated (transformed) all the IR that seems necessary for codegen!
Next, let's look at the implementation of codegen!

