<p>While implementing <a href="https://github.com/tyr-lang/test.conformance/blob/master/0.7.0/accept/enumTyped/mar.tyr" rel="nofollow noreferrer">enums</a> in Tyr, I just realized that enum constants are the only form of literal-like entity that is not represented like a literal in the intermediate representation.</p>
<p>The enum concept is pretty much that of C++. I doubt that it really matters for the question.
The question is, are there any benefits from having enum members as literals in the IR?</p>
<p>My current approach is essentially treating them like global constants that are somewhat equal to the literal values they correspond to.
There are some places in the compiler with special rules projecting the enum types away.</p>
<p>At the moment, I'd expect that the answer doesn't even depend on the representation of the enum concept or if instances are flat values or <code>String</code> literals or arbitrary <code>Objects</code>.</p>
<p>EDIT: The question is if a literal type distinct from the literal type of the enum's base type should be introduced. In contrast to projecting the instances to the base type which wasn't the intention, but is apparently a sane interpretation of the original question.</p>
<p>EDIT2: The IR is used to build libraries that can be linked, compiled against and executed like JAR files in Java. The question is if a dedicated EnumLiteral expression subclass akin to an IntLiteral has any obvious advantage or disadvantage over a combination of StaticUse Expression with an EnumInstance Declaration target. Both options would bear an access path to the enum type and the underlying IntLiteral.</p>

<compilers><implementation><design-choice-comparison>
Are enum members literals or constants in an IR?
CC BY-SA 4.0
2023-09-24T12:40:27.670Z
I am not sure this question makes sense. A constant is a kind of value or variable; a literal is a kind of node in an AST. Is 123 a constant or a literal? That depends if you are talking about the integer value 123, or the source token 123. On the other hand, it really sounds like your question is not about what an enum member "is", but how it *should* be represented in an IR, and the answer to that depends on what you mean by "should", and what the IR is for.
kaya3
CC BY-SA 4.0
2023-09-24T14:53:06.950Z
It depends on how high-level the IR is. If the IR supports reflection or analysis like exhaustiveness checking, they will probably be represented as explicit instances of the enum datatype. Otherwise, and in lower-level IRs like LLVM, they are plain numbers or strings depending on / of the backing type (e.g. `int32`)
tarzh
CC BY-SA 4.0
2023-09-25T10:47:48.683Z
Interfacing with a debugger may be valuable to you?
Pseudonym
CC BY-SA 4.0
2023-09-25T16:30:03.517Z
The debugger likely won't interact with my IR directly. I consider the IR low level and it is not the AST or the parse tree. In the IR, all literals are unified, i.e. two uses of 123 in the source code result in a pointer to the same 123 representing object. For integers, this is an IntegerLiteral. For enums, this is a use of an EnumInstanceDecl which seemed strange to me. Hence the question. The EnumInstance itself isn't a value as it behaves like a member which is a Declaration and therefore not an Expression.
feldentm
CC BY-SA 4.0
2023-09-25T18:02:06.580Z
I think this question is unanswerable in its current form, because you haven't said what you need to use this IR for. An IR used for type-checking probably needs to know the difference between `Colour.RED` and `0`, for example, but an IR used for x86 code generation does not. Likewise, if your enum members might have other underlying values depending on context, then at some compilation stages this context might not be fully known yet and hence replacing them would be impossible; consider e.g. `Result<Colour, ErrorCode>` which might be implemented by renumbering one enum to prevent overlap.
kaya3
CC BY-SA 4.0
2023-09-28T13:50:30.550Z
I tried to address your concerns. Honestly, I do not understand what kind of language would allow to defer value binding for enum constants after the freezing of the library the enum is defined in. It seems that we have complete different compilation concepts in mind; would your example work if the use crosses a library boundary?
feldentm
CC BY-SA 4.0
2023-09-28T17:48:13.773Z
Hello. Could you please assume that your audience is not used to the same acronyms as you are? It's ***always*** a good assumption to make. What is IR? Infrared ? Incidence rate? Insulin resistance? The Wikipedia disambiguation page lists well over a hundred meanings of "IR", among which 10 in the "Computing" section.
Stef
<p>If your enum members are backed by simple immutable integers or strings, and are used as simple names in lieu of these simple integers/strings, they can be represented as simple literals or constants anywhere, even in IR.</p>
<p>But if these enums defines a closed set of possible values or exhaustiveness checking, they are very distinct of simple literals, and should be represented differently:</p>
<pre><code>enum mixed {
  zero,
  one,
  two
}

type T {
  with mixed.zero
  with mixed.one
  with mixed.two

  test &quot;use&quot; {
   
    val c = one + two   // compiler accepts or fails?

    switch c {
      if zero true
      if one true
      if two true
      else false        // compiler complains can never happen?
    }
  }
}
</code></pre>
<p>On an IR very close to code generation, <em>after all type checking is already done</em>, is possible to replace enums members by their direct literal values, as in this level these substitutions do not generate invalid effects.</p>
<p>At a very low level, code folding and constant propagation don't care if an <em>immutable value</em> is a member of an enum, a class constant, or a source code literal.</p>

CC BY-SA 4.0
2023-09-25T00:45:25.940Z
2023-10-14T08:31:14.910Z
2023-10-14T08:31:14.910Z
André L F S Bacci
CC BY-SA 4.0
2023-09-25T16:36:50.110Z
Honestly, I don't know if I should accept the answer or clarify the question. In my case, type checking is never done because compilation is performed against the IR of other modules in contrast to using other module's source. I wasn't aware that this would make a difference. The typing in that case makes a difference because a join between two identical literal values from different enums results in that value whereas two different values from the same enum results in an unknown value from that enum.
feldentm
CC BY-SA 4.0
2023-10-13T13:38:20.267Z
You should accept, as it answer your question. "In my case, type checking is never done" -> "are used as simple names in lieu of these simple integers/strings, they can be represented as simple literals or constants anywhere, even in IR".
André L F S Bacci
# Are enum members literals or constants in an IR?
Posted by: username_0 on 2023-09-24
While implementing [enums](https://github.com/tyr-lang/test.conformance/blob/master/0.7.0/accept/enumTyped/mar.tyr) in Tyr, I just realized that enum constants are the only form of literal-like entity that is not represented like a literal in the intermediate representation.

The enum concept is pretty much that of C++. I doubt that it really matters for the question.
The question is, are there any benefits from having enum members as literals in the IR?

My current approach is essentially treating them like global constants that are somewhat equal to the literal values they correspond to.
There are some places in the compiler with special rules projecting the enum types away.

At the moment, I'd expect that the answer doesn't even depend on the representation of the enum concept or if instances are flat values or `String` literals or arbitrary `Objects`.

EDIT: The question is if a literal type distinct from the literal type of the enum's base type should be introduced. In contrast to projecting the instances to the base type which wasn't the intention, but is apparently a sane interpretation of the original question.

EDIT2: The IR is used to build libraries that can be linked, compiled against and executed like JAR files in Java. The question is if a dedicated EnumLiteral expression subclass akin to an IntLiteral has any obvious advantage or disadvantage over a combination of StaticUse Expression with an EnumInstance Declaration target. Both options would bear an access path to the enum type and the underlying IntLiteral.
**Tags:** compilers implementation design-choice-comparison
> **Comments:**
> **username_1**: I am not sure this question makes sense. A constant is a kind of value or variable; a literal is a kind of node in an AST. Is 123 a constant or a literal? That depends if you are talking about the integer value 123, or the source token 123. On the other hand, it really sounds like your question is not about what an enum member "is", but how it *should* be represented in an IR, and the answer to that depends on what you mean by "should", and what the IR is for.  
> **username_2**: It depends on how high-level the IR is. If the IR supports reflection or analysis like exhaustiveness checking, they will probably be represented as explicit instances of the enum datatype. Otherwise, and in lower-level IRs like LLVM, they are plain numbers or strings depending on / of the backing type (e.g. `int32`)  
> **username_3**: Interfacing with a debugger may be valuable to you?  
> **username_0**: The debugger likely won't interact with my IR directly. I consider the IR low level and it is not the AST or the parse tree. In the IR, all literals are unified, i.e. two uses of 123 in the source code result in a pointer to the same 123 representing object. For integers, this is an IntegerLiteral. For enums, this is a use of an EnumInstanceDecl which seemed strange to me. Hence the question. The EnumInstance itself isn't a value as it behaves like a member which is a Declaration and therefore not an Expression.  
> **username_1**: I think this question is unanswerable in its current form, because you haven't said what you need to use this IR for. An IR used for type-checking probably needs to know the difference between `Colour.RED` and `0`, for example, but an IR used for x86 code generation does not. Likewise, if your enum members might have other underlying values depending on context, then at some compilation stages this context might not be fully known yet and hence replacing them would be impossible; consider e.g. `Result<Colour, ErrorCode>` which might be implemented by renumbering one enum to prevent overlap.  
> **username_0**: I tried to address your concerns. Honestly, I do not understand what kind of language would allow to defer value binding for enum constants after the freezing of the library the enum is defined in. It seems that we have complete different compilation concepts in mind; would your example work if the use crosses a library boundary?  
> **username_4**: Hello. Could you please assume that your audience is not used to the same acronyms as you are? It's ***always*** a good assumption to make. What is IR? Infrared ? Incidence rate? Insulin resistance? The Wikipedia disambiguation page lists well over a hundred meanings of "IR", among which 10 in the "Computing" section.  
---
## 1 answers
### Answer by username_5 on 2023-09-25. Score: 4 | Accepted answer
If your enum members are backed by simple immutable integers or strings, and are used as simple names in lieu of these simple integers/strings, they can be represented as simple literals or constants anywhere, even in IR.
But if these enums defines a closed set of possible values or exhaustiveness checking, they are very distinct of simple literals, and should be represented differently:
enum mixed {
  zero,
  one,
  two
}

type T {
  with mixed.zero
  with mixed.one
  with mixed.two

  test "use" {
   
    val c = one + two   // compiler accepts or fails?

    switch c {
      if zero true
      if one true
      if two true
      else false        // compiler complains can never happen?
    }
  }
}

On an IR very close to code generation, after all type checking is already done, is possible to replace enums members by their direct literal values, as in this level these substitutions do not generate invalid effects.
At a very low level, code folding and constant propagation don't care if an immutable value is a member of an enum, a class constant, or a source code literal.
> **Comments:**
> **username_0** (2023-09-25): Honestly, I don't know if I should accept the answer or clarify the question. In my case, type checking is never done because compilation is performed against the IR of other modules in contrast to using other module's source. I wasn't aware that this would make a difference. The typing in that case makes a difference because a join between two identical literal values from different enums results in that value whereas two different values from the same enum results in an unknown value from that enum.  
> **username_5** (2023-10-13): You should accept, as it answer your question. "In my case, type checking is never done" -> "are used as simple names in lieu of these simple integers/strings, they can be represented as simple literals or constants anywhere, even in IR".  
---
