Skip to main content

Phase 3.3. set<T> for scalar T

FieldValue
MEPMEP-54
StatusLANDED
Started2026-05-28 (GMT+7)
Landed2026-05-28 (GMT+7)
Tracking PR#22501
Commit87eed650a6

Gate

10 fixtures cover the scalar set surface: set_lit, set_has, set_len, set_add, set_for_each, set_strings, set_dedup, set_empty, set_floats, set_count_unique. Run: go test ./transpiler3/go/build/... -run TestPhase1Hello/set_.

Lowering decisions

Mochi set<T> lowers to Go's idiomatic set encoding map[T]struct{}. Set literals emit an IIFE so duplicate input elements collapse via idempotent s[k] = struct{}{} assignments: func() map[T]struct{} { s := make(map[T]struct{}); s[a] = struct{}{}; s[b] = struct{}{}; return s }(). Choosing map[T]struct{} over map[T]bool is the standard Go memory-saving trick: a struct{} value is zero-sized, so the underlying hashtable allocates only for keys, not values.

SetHasExpr lowers via the same two-value-index IIFE as MapHasExpr. SetLenExpr wraps len(s) with int64(...). SetAddStmt lowers to s[k] = struct{}{}. ForEachStmt over a set iterates via slices.Sorted(maps.Keys(s)) to preserve Mochi's sorted-iteration semantics; without the sort, Go's runtime randomisation would surface in fixture goldens. The slices and maps stdlib imports are registered on demand.

lowerSetType returns map[Elem]struct{} and is threaded into letTypeText, paramTypeText (Phase 6.0), and returnTypeText (Phase 6.0) so set values can be locals, function arguments, and return values uniformly.

Files changed

FilePurpose
transpiler3/go/lower/types.golowerSetType(elem) -> map[Elem]struct{}
transpiler3/go/lower/expr.goSetLit IIFE; SetHasExpr; SetLenExpr
transpiler3/go/lower/stmt.goSetAddStmt -> s[k] = struct{}{}; ForEachStmt over a set sorts keys
tests/transpiler3/go/fixtures/set_*/10 set fixtures

Test set

  • TestPhase1Hello/set_lit, set_has, set_len, set_add, set_for_each, set_strings, set_dedup, set_empty, set_floats, set_count_unique.

Closeout notes

The IIFE-on-literal pattern was preferred over a runtime helper because each fixture's literal is small and inlined construction keeps the dependency graph simpler. The set's sorted iteration mirrors the map decision in Phase 3.2; both are essential for the reproducibility pin in Phase 16 to make any sense.