Skip to main content

Phase 3.3. Sets

FieldValue
MEPMEP-49 §Phases · Phase 3.3
StatusLANDED
Started2026-05-28 13:40 (GMT+7)
Landed2026-05-28 13:40 (GMT+7)
Tracking issue
Tracking PR

Gate

TestPhase3Sets: 20 fixtures green on Swift 6.0 and 6.1, linux-x64. TestSwiftcClean remains green.

Goal-alignment audit

Mochi sets are insertion-ordered (like maps). Swift's stdlib Set is unordered. OrderedSet from swift-collections preserves insertion order, gives O(1) membership test, and conforms to SetAlgebra. Phase 3.3 builds on the swift-collections dependency introduced in Phase 3.2.

Sub-phases

#ScopeStatusCommit
3.3.0set<T>OrderedSet<T>; set literals; set.contains(x).contains(x); set.length.countNOT STARTED
3.3.1set.add(x) → functional update; set.remove(x) → functional updateNOT STARTED
3.3.2set.union(s2).union(s2); set.intersection(s2).intersection(s2); set.difference(s2).subtracting(s2)NOT STARTED
3.3.3set.to_list()Array(s); set.from_list(xs)OrderedSet(xs); structural equalityNOT STARTED

Sub-phase 3.3.0 -- Set literals and membership

Decisions made (3.3.0)

OrderedSet<T> from swift-collections: same dependency as Phase 3.2 (swift-collections 1.1.x). OrderedSet is Hashable when T: Hashable, Equatable when T: Hashable. Membership is O(1) via the backing hash table. Iteration is insertion-order.

Set literals: Mochi {1, 2, 3} (set literal, distinct from map {k:v}) → OrderedSet([Int64(1), Int64(2), Int64(3)]). The OrderedSet(_ sequence:) initializer is used because OrderedSet does not support the Set literal syntax directly.

Empty set: set<int>{}OrderedSet<Int64>().

set.contains(x): → s.contains(x). O(1).

set.length: → Int64(s.count).

Sub-phase 3.3.1 -- Add and remove (functional)

Decisions made (3.3.1)

Value semantics: Mochi sets are immutable. set.add(x) returns a new set. The lowerer emits a block that copies, mutates, and returns:

// Mochi: let s2 = s.add(42)
var __tmp_s2 = s
__tmp_s2.append(Int64(42)) // OrderedSet.append is a no-op if already present
let s2 = __tmp_s2

OrderedSet.append adds the element at the end if not already present (maintaining insertion order), no-ops if present. This matches Mochi set semantics.

set.remove(x): → copy-mutate-return using remove(_ member:):

var __tmp_s3 = s
__tmp_s3.remove(Int64(42))
let s3 = __tmp_s3

Sub-phase 3.3.2 -- Set algebra

Decisions made (3.3.2)

OrderedSet and SetAlgebra: OrderedSet conforms to SetAlgebra (via swift-collections 1.1+). This gives .union, .intersection, .subtracting, .symmetricDifference for free.

set.union(s2): → s.union(s2). Result is a new OrderedSet containing all elements of both sets. Elements from s come first in iteration order, then elements from s2 not in s.

set.intersection(s2): → s.intersection(s2). Elements present in both sets, preserving order from s.

set.difference(s2): Mochi s.difference(s2) = elements in s not in s2. → s.subtracting(s2).

set.symmetric_difference(s2): → s.symmetricDifference(s2). Elements in exactly one of the two sets.

set.is_subset_of(s2): → s.isSubset(of: s2).

set.is_superset_of(s2): → s.isSuperset(of: s2).

Sub-phase 3.3.3 -- Conversion and equality

Decisions made (3.3.3)

set.to_list(): → Array(s). Preserves insertion order. Returns [T].

set.from_list(xs): → OrderedSet(xs). Duplicate elements in xs are silently dropped (first occurrence wins). This matches Mochi's set-from-list semantics.

s1 == s2: OrderedSet conforms to Equatable. Equality is order-sensitive: same elements in same insertion order. Two sets built from the same elements in different insertion orders are not equal. This is the correct Mochi semantics for ordered sets.

set.map(f): → OrderedSet(s.map(f)). The map result is re-deduplicated by OrderedSet init (last occurrence wins in case of collision after f). Mochi documents that set.map may reduce size if f is not injective.

set.filter(p): → s.filter(p). Returns OrderedSet<T> directly (swift-collections 1.1 supports this).

Files changed

FilePurpose
transpiler3/swift/lower/lower.goSet literal lowering → OrderedSet([...])
transpiler3/swift/lower/builtins.gocontains, length, add, remove, union, intersection, difference, symmetric_difference, is_subset_of, is_superset_of, to_list, from_list, map, filter
transpiler3/swift/runtime/Sources/MochiRuntime/Set.swiftSet helper extensions
transpiler3/swift/build/phase03_sets_test.goTestPhase3Sets: 20 fixtures
tests/transpiler3/swift/fixtures/phase03-sets/20 fixture directories

Test set

  • TestPhase3Sets -- 20 fixtures covering: set_empty, set_literal, set_contains, set_length, set_add, set_remove, set_union, set_intersection, set_difference, set_symmetric_difference, set_is_subset, set_is_superset, set_to_list, set_from_list, set_map, set_filter, set_equality, set_order, set_dedup, set_nested.

Deferred work

  • set.find(p)s.first(where: p) (returns option<T>). Deferred to Phase 5.
  • set.partition(p). Deferred to Phase 5.
  • Set of sets (requires OrderedSet: Hashable; available in swift-collections 1.1).