Skip to main content

Phase 7.11. omap

FieldValue
MEPMEP-54
StatusLANDED
Started2026-05-29 (GMT+7)
Landed2026-05-29 (GMT+7)
Tracking PR#22608
Commitaf82c4243c

Gate

8 fixtures: omap_literal, omap_get, omap_has, omap_len, omap_set, omap_overwrite, omap_int_keys, omap_put_stmt. 253 transpiler3/go fixtures green (was 245).

Lowering decisions

omap<K, V> lowers to *mochiOMap[K, V], a small generic struct in the emitted helpers:

type mochiOMap[K comparable, V any] struct {
m map[K]V
keys []K
}

The pointer form lets OMapPutStmt mutate the receiver in place, matching Mochi's mutable-ordered-map semantics. The C lowerer rebinds via orddict:store (functional update + reassignment); the Go path mutates through the pointer directly so no re-assignment is needed at the call site.

Six aotir nodes lower in Phase 7.11:

  • OMapLiteralExpr -> IIFE: mochiOMapNew[K, V]() followed by sequential mochiOMapSet(o, k, v) calls, preserving insertion order across both first-write and overwrite.
  • OMapGetExpr -> mochiOMapGet(o, k) returning the value (zero value if missing).
  • OMapHasExpr -> mochiOMapHas(o, k) returning a bool.
  • OMapLenExpr -> int64(mochiOMapLen(o)) keeping the int pin.
  • OMapSetExpr (value form) -> IIFE matching the literal pattern that returns the receiver, though the C lowerer typically prefers the statement form.
  • OMapPutStmt -> mochiOMapSet(o, k, v) (statement form).

TypeOMap is added to letTypeText, paramTypeText, and returnTypeText, all of which return *mochiOMap[K, V] and register the mochiOMap helper.

Files changed

FilePurpose
transpiler3/go/lower/types.golowerOMapType(K, V) -> *mochiOMap[K, V]
transpiler3/go/lower/expr.goOMapLiteralExpr, OMapGetExpr, OMapHasExpr, OMapLenExpr, OMapSetExpr
transpiler3/go/lower/stmt.goOMapPutStmt -> mochiOMapSet(o, k, v)
transpiler3/go/lower/lower.gomochiOMap[K, V], mochiOMapNew, mochiOMapGet, mochiOMapHas, mochiOMapSet, mochiOMapLen helper texts
tests/transpiler3/go/fixtures/omap_*/8 fixtures

Test set

  • 8 TestPhase1Hello/omap_* subtests covering literal construction, read, has, len, mutation, overwrite-preserves-order, int keys, and statement-form put.

Closeout notes

Choosing the (map + keys slice) representation over Go's stdlib container/list was a soundness call: container/list would give O(1) ordered insertion but turn Get and Has into O(N). The hybrid representation costs one extra word per key (the slice entry) and a small append on insert, but keeps every operation at the expected complexity. The pointer-typed *mochiOMap[K, V] matters because Go's struct values would be copied at every assignment, breaking the mutate-through-binding semantics every fixture relies on.