sammine-lang
Loading...
Searching...
No Matches
Enum & Type Alias Support

Keyword

The type keyword serves double duty: enum definitions and type aliases.

Disambiguation rule (in ParseEnumDef()): After type Name =, if next tokens are ID | or ID( → enum path. Otherwise → type alias path.

Syntax

Construct Example
Definition type Color = Red \| Green \| Blue;
Payload variants type Shape = Circle(f64) \| Rect(f64, f64) \| Point;
Integer-backed type Status = OK(0) \| Err(1);
Explicit backing type type Flags: u32 = Read(1) \| Write(2) \| Exec(4);
Generic enum type Option<T> = Some(T) \| None;
Type alias type IntAlias = i32;
Pointer alias type IntPtr = ptr<i32>;
Qualified construction Color::Red, Shape::Circle(3.14)
Unqualified construction Red, Some(42) — rewritten to qualified form by scope generator
Case expression case expr { Color::Red => body, _ => default, }
Bitwise on int-backed Read \| Write&, \|, ^, <<, >> supported

Type Aliases

  • AST node: TypeAliasDefAST (in include/ast/Ast.h)
  • Fields: alias_name (QualifiedName), type_expr (TypeExprAST), resolved_type (Type), is_exported
  • Transparent: resolved at type-check time (Pass 1 of visit(ProgramAST*)). Registered in typename_to_type pointing to the resolved type.
  • No codegen: MLIRGen skips TypeAliasDefAST; CodegenVisitor stubs are empty.
  • Scope: registered in ScopeGeneratorVisitor::preorder_walk(ProgramAST*) like enums/structs.
  • Semantics: GeneralSemanticsVisitor checks for reserved identifiers.

Variant Access

  • Qualified (Color::Red) — always works
  • Unqualified (Red) — scope generator rewrites to qualified form before type checking
  • Scope generator populates variant_to_enum map (variant name → enum name) during preorder_walk(ProgramAST*)
  • postorder_walk(CallExprAST*) rewrites unqualified variant calls → qualified form
  • Invariant: the type checker assumes all variant calls arrive pre-qualified; it does NOT resolve unqualified names
  • Both unit and payload variants parse as CallExprAST with a qualified name (after rewriting)
  • Enums are NOT transitive through imports — file B must directly import file A

LLVM Representation

Layout Description
Tagged union { i32 tag, [N x i8] payload } — N = max payload size across variants
Named type sammine.enum.<Name>
Unit-only enum { i32 } (no payload buffer)
Construction alloca + GEP + store for tag and payload
Pattern extraction alloca + GEP + load from byte buffer at correct offsets

Type System

  • TypeKind::Enum with EnumType class using QualifiedName (nominal equality by mangled name). Has operator== only — no operator<
  • EnumType::backing_type_ (TypeKind) — defaults to I32_t, configurable via : u32/: i64 etc. syntax
  • EnumType::get_backing_type() — used by codegen to select correct integer width
  • Integer-backed enums flow into their backing type via compatible_to_from()
  • Negative discriminant values are rejected at parse time (TokSUB check in ParseEnumDef)
  • variant_constructors map: variant_name → (enum_type, index) — used for generic enum fallback and VariableExprAST unit variant lookup
  • Variant resolution in synthesize(CallExprAST*): look up enum via get_typename_type(qualifier) (uses get_qualifier() for the enum type name), fall back to variant_constructors for generics, then find variant by name
  • See type_checking.md for full enum type checker details (EnumType, variant constructors, case expressions, exhaustiveness)

Scope Generator

  • preorder_walk(ProgramAST*) → registers variant names in scope, populates variant_to_enum
  • postorder_walk(CallExprAST*) → rewrites unqualified variant calls to qualified form, then returns early
  • For already-qualified names → checks if prefix is an enum name in scope, defers to type checker
  • variant_to_enum: std::map<std::string, std::string> in ScopeGeneratorVisitor.h
  • visit(CallExprAST*) has early return for is_enum_constructor

Codegen

See codegen.md for full details. Summary:

Backend Key details
LLVM emitEnumConstructor in FunctionCodegen.cpp; TypeConverter::register_enum_type/get_enum_type; forward declaration pass registers LLVM struct types
MLIR enumTypes map in MLIRGenImpl; emitEnumConstructor in MLIRGenExpr.cpp (LLVM dialect); getTypeSize4 + max_payload_size; convertType looks up enumTypes
Case (LLVM) switch i32 tag + basic blocks per arm + PHI merge; payload via byte-offset GEP
Case (MLIR) Cascading cmpi + cf::CondBranchOp; merge blocks with block arguments

Generic Enums

  • enum Option<T> = Some(T) \| None; — type params parsed same as generic functions
  • Generic enums stored in generic_enum_defs; GenericTypeExprAST triggers instantiation via Monomorphizer::instantiate_enum()
  • Monomorphized enum defs inserted at front of DefinitionVec
  • See type_checking.md for generic enum instantiation details

Exhaustiveness Checking

  • After processing all case arms, collects covered_indices set
  • If no wildcard _ present and covered_indices.size() < variant_count() → error listing missing variants
  • Duplicate variant patterns are warned

Parsing

See lex_and_parse.md for full details. Tokens: TokType, TokCase, TokFatArrow (=>). The type keyword triggers ParseEnumDef(), which disambiguates enum vs type alias. Variants pipe-separated via TokORLogical. Patterns support qualified, unqualified (rewritten), wildcard _, and payload bindings.

Note: TokEnum was removed — the enum keyword no longer exists. All definitions use type.