Enumerations
Implementation status: simple enums / associated values / generic enums / switch exhaustiveness / if case are all Implemented; automatic Int raw values Partially implemented; indirect enum Not implemented
An enumeration defines a group of related values. SYX enums are Swift-style "algebraic data types (ADT)": each case may be a simple identifier or may carry associated values.
Simple Enumerations
enum Status {
case ok
case err
case pending
}
let s = Status.ok
print(s.tag) // 0 (internal tag)The
casekeyword: SYX simple enums must writecase(consistent with early Swift 1.x style;enum Status { ok, err, pending }is not legal).
Source: crates/syx-driver/tests/fixtures/lang/enum_associated.sy
Associated Values
enum NetworkResult {
case success(String)
case failure(code: Int, message: String)
}
let r1 = NetworkResult.success("OK")
let r2 = NetworkResult.failure(code: 404, message: "Not Found")- Associated values may be named (
code:,message:) or anonymous (positional) - One enum may have several case shapes (discriminated union)
- The standard library
Result<T, E>is defined inpackages/core/builtins/result.sy
Source: crates/syx-driver/tests/fixtures/lang/enum_associated.sy
switch Matching
func describe(_ r: NetworkResult) -> String {
switch (r) {
case .success(let data) {
return "ok: \(data)"
}
case .failure(code: let c, message: let m) {
return "fail code=\(c) msg=\(m)"
}
default { // An enum may omit default; an open domain needs one
return "?"
}
}
}Braces: a SYX
casemust be followed by a{ }block. See Chapter 6, Control Flow.
Destructuring Named Associated Values
case .failure(code: let c, message: let m) { … } // Named
case .failure(let c, let m) { … } // Positional
case let .success(data) { … } // Single-parameter shorthandwhere Guards
case .success(let data) where (data.count > 0) { … }
case .failure(let m) where (m.hasPrefix("5")) { … }if case
enum NetworkResult {
case success(String)
case failure(String)
}
let result = NetworkResult.success("ok")
if case .success(let data) = result {
print(data)
} else {
print("not success")
}if case is a convenient single-branch form of switch. The patterns after case are the same as in a switch case.
Generic Enumerations
enum Optional<T> {
case some(T)
case none
}
enum Result<T, E> {
case ok(T)
case err(E)
}- Generic parameters come after the enum name
- Monomorphization generates concrete instances such as
Optional<Int>/Optional<String> - The standard
OptionalandResultare pre-declared (you need not write them yourself)
Implemented (fixtures/lang/enum_associated.sy)
Nested Types
enum Tree {
case leaf(Int)
case branch(left: Tree, right: Tree)
}Recursive nesting: a single level of recursion compiles to an object reference; deep recursion needs
indirect enum(Not implemented, planned). Wrap it in aclassfor now.
Raw Values (Partially Implemented)
enum Direction: Int {
case north = 0
case east = 1
case south = 2
case west = 3
}| Capability | Status |
|---|---|
: Int raw value | Partially implemented (Phase 50 basics) |
: String raw value | Not implemented |
| Implicit raw values | Not implemented (assignment must be explicit) |
Alternative: a simple enum can use ordinary cases plus an explicit
Intconversion. Full raw value support → later Phases.
Enum Methods
enum Status {
case ok, err, pending
func isFinal() -> Bool {
switch (self) {
case .ok { return true }
case .err { return true }
case .pending { return false }
}
}
func description() -> String {
switch (self) {
case .ok { return "ok" }
case .err { return "err" }
case .pending { return "..." }
}
}
}
print(Status.ok.isFinal()) // true
print(Status.pending.description()) // "..."
self: inside an enum method,selfis the current case (already bound to the case plus its associated values).
Enums and Protocols
Enums may adopt protocols (Equatable / Hashable / Codable and others):
@Equatable
enum Status {
case ok
case err
case pending
}
print(Status.ok == Status.err) // falseManual implementation:
==for an associated-value enum is generated by the compiler from case + associated values (Implemented,Equatablesynthesis).
For @Hashable / @Codable, see Chapter 19, Macros.
Codable L2 (Associated-Value Enums)
Since Phase 129, enums with associated values get encode / decode fully automatically (fingerprint macro-codable-l2:associated-enum-auto):
@Codable
enum WireStatus {
case ok(code: Int)
case err(message: String)
}
func main() {
let w = WireStatus.ok(code: 7)
let text = w.encode()
let back = WireStatus.decode(text: text)
}Limits: the full set of generic associated values / arbitrary nesting / custom coding keys → later Phases.
Exhaustiveness
Enums and final class closed domains get automatic exhaustiveness checking in switch; incomplete case coverage → S007.
enum Color { case red, green, blue }
func describe(_ c: Color) -> String {
switch (c) {
case .red { return "red" }
case .green { return "green" }
case .blue { return "blue" }
} // ✅ Fully covered
}
func incomplete(_ c: Color) -> String {
switch (c) {
case .red { return "red" }
} // ❌ S007: missing cases
}Choosing Between Enums and final class
| Need | Choose |
|---|---|
| One shared case structure, pattern matching | enum |
| Methods with fields, or inheritance | class / final class |
| Cross-process / deserialization | enum (smaller, purer) |
| Associated values with named parameters | enum case (case failure(code:, message:)) |
| Variants need extra methods or a shared base class | class (polymorphic) or final class (closed) |
Note: the lexer has no
sealedkeyword; useenumfor ADTs andfinal classto forbid subclassing.
Complete Example
import JSON
enum ApiResponse {
case ok(data: String)
case unauthorized
case serverError(status: Int, body: String)
}
func handle(_ r: ApiResponse) -> String {
switch (r) {
case .ok(let data) where (data.count > 0) {
return "OK: \(data)"
}
case .ok {
return "OK (empty)"
}
case .unauthorized {
return "401"
}
case .serverError(status: let s, body: let b) where (s >= 500) {
return "5xx: \(b)"
}
case .serverError(status: let s, body: let b) {
return "4xx[\(s)]: \(b)"
}
}
}
func main() {
let r1 = ApiResponse.ok(data: "hello")
let r2 = ApiResponse.serverError(status: 503, body: "down")
print(handle(r1)) // "OK: hello"
print(handle(r2)) // "5xx: down"
}Diagnostics
| Code | Trigger | Fix |
|---|---|---|
| S007 | Non-exhaustive switch (not all cases covered) | Add the missing cases or a default |
| S010 | Associated-value destructuring mismatch | Check the enum definition |
| P001 | case missing its brace block | Add { } |
Differences from Swift
| Swift | SYX |
|---|---|
case ok, err (without the case keyword) | Must write case ok / case err |
Recursive indirect enum | Not implemented (wrap in a class) |
String / character raw values | Not implemented (only Int, partially) |
Default CustomStringConvertible implementation | An explicit func description() -> String is needed |
@Codable associated-value enums | Partial GA (L2 fully automatic, Phase 129) |
if case let | if case .variant(let x) = expr (slightly different syntax) |
Next chapter → Structures and Classes
See also → Language Reference: Declarations · Chapter 6, Control Flow · Chapter 19, Macros · Chapter 10, Structures and Classes