open dict - mvx-lang/mvx GitHub Wiki
A design note for the portable interchange format that lets dictionaries, the
VOC/MD, and whole accounts survive crossing between MultiValue platforms through
git β so an account committed on MVX clones/rebuilds correctly on UniData (and
back). It complements the settled Open account format in DECISIONS.md
(the git-boundary translation, the mvx.openaccount flag); this note pins down
the two schemas that translation moves through: open dict and the
.mv-account open-account descriptor. The mvxβopen round-trip has a working
prototype in tests/opendict.b.
MV dictionaries mean the same thing everywhere β a field's name, source attribute, type, conversion, format, heading, association role β but each platform encodes them differently (mvx's 6-attribute D-item, UniData/UniVerse D/I/PH items with a different attribute order and extra control fields). A raw dictionary committed in one platform's form doesn't load correctly in another. The same holds for the VOC/MD (the verb/pointer catalog) and for an account's file list. The fix is a canonical, self-describing serialization of the semantic content that each platform converts to and from.
An open-dict item is a legible canonical MV record (the record id is the field name). It keeps mvx's native attribute order for 1β6 β mvx is the reference dialect β and appends the derived cross-platform semantics a target needs:
| # | field | notes |
|---|---|---|
| 1 | type |
D data field Β· I derived/computed Β· PH phrase |
| 2 | source | attribute number (D), the expression (I), or phrase text (PH) |
| 3 | conv | conversion code (MD2, D2/, MT, β¦) β largely shared across dialects |
| 4 | heading | column heading / display name |
| 5 | format | display format (12L, 8R) |
| 6 | assoc | association name (empty = unassociated) |
| 7 | single/multi |
S single-valued Β· M multi-valued β derived
|
| 8 | role |
C controlling Β· D dependent Β· empty β derived
|
Fields 7β8 are derived on export and advisory for the importer: M when the
field is in an association; role = C for the association's controlling member
(the one with the lowest source attribute number) else D. Import needs only
1β6, so native β open β native round-trips exactly. Records serialize with
the record-git legible hybrid (marks β newlines), so they diff on GitHub.
Near-identity: mvx's D-item 1=D/I 2=attr#/expr 3=conv 4=heading 5=format 6=assoc is open fields 1β6. Export copies 1β6 and computes 7β8 from the
association context; import drops 7β8 and writes 1β6 back. Lossless β the
prototype asserts it over a dictionary that includes an association (INV:
QTY controlling, PRICE/DESC dependent) and a derived I item.
UniData dictionaries carry the same semantics in a different shape (a D item's
attributes are location / conversion / name / format / single-multi / assoc,
with I/V for derived and PH for phrases). udt-git's converter maps
UniData's attribute order and control fields onto the canonical 1β8 above and
back. Divergences to resolve there (not on MVX): conversion-code spelling
differences, association encoding (UniData names controlling/dependent
explicitly via S;assoc β open field 8 captures it), and I-type expression
syntax. Because open dict is dialect-neutral, adding a field in UniData β
committing β cloning in mvx yields a correct mvx dictionary, and vice versa.
The VOC/MD splits into portable and local entries:
-
Portable (travel in open form):
F/Qfile pointers (attr 1 the abstract classDIR/hash, attr 2 data, attr 3 dictionary β see CREATE-FILE),PHphrases, and verb/keyword definitions (name, kind, sentence grammar). -
Local (rebuilt on checkout, never committed): executable paths and
cataloged binaries.
BUILDre-catalogs these from the account's source after the portable catalog is in place.
The account-level analogue: a portable descriptor at the account root that both
describes the account and drives the conversion. It is the git-side
counterpart of the on-disk native .mvx (name/version marker); on checkout
.mv-account rebuilds .mvx, and UniData β which has no on-disk descriptor β
reads it transiently to build the account and synthesises it on commit. A
legible key = value descriptor with file lines (same family as .mvx):
# .mv-account β open (portable) account descriptor
name = demo
version = 1
openaccount = 1 # conversion policy: store dict/VOC in open form
hash = lmdb # the account's default hash backend (checkout maps `hash` -> this)
description = MVX demo account
# file <logical-name> <kind: hash|DIR> [dict:<dict-ref>]
file VOC hash dict:VOC
file BP DIR dict:BP
file CUSTOMERS hash dict:CUSTOMERS
-
Identity β
name,version,description. -
Files β each file's logical name, abstract
kind(hash/DIRβ the semantic behind today's%FILE%), and its dictionary reference; never the platform storage details (LMDB paths, driver names β those are local BINDINGS). -
Conversion β
openaccount = <version>(the account-level home for the open-form policy) andhash =(the default backend ahashfile maps to on checkout; the prompt is per-platform, see DECISIONS.md).
Replaces vs complements .mvx. .mv-account is the portable superset; on
MVX the on-disk descriptor stays .mvx (native, minimal) and .mv-account is
the committed open form the engine maps to/from β two files, each with one job
(detection vs interchange). They share the key = value grammar so the mapping
is mechanical.
On checkout the master dictionary is rebuilt first (#59): the VOC/MD F
pointers and the account's dictionaries must exist before data files are created
and indexes rebuilt (%INDEXES% β CREATE-INDEX). Then BUILD re-catalogs the
local verb binaries.
-
Record-git engine (
mv_git) β on commit, translate native dict/VOC/%FILE%β open (guided by.mv-account); on checkout, build the native account directly from open blobs, master dictionary first;status/difftranslate on-disk native up to open before comparing. -
%FILE%normalization βlmdb/any hash backend βhash,dirβDIRin git; reverse on checkout mapshashβ the account'shash =default andDIRβ the directory driver. -
Conversion policy β the
mvx.openaccountgit-config flag (β$MVX_OPENACCOUNT) gates all of the above; without it the engine stores the platform's own legible form (current behaviour).
- Open-dict converter as a reusable subroutine (this note's prototype β
mv_git-callable), both directions, over a whole.DICT. -
%FILE%DIR/hash normalization at the git boundary + thehash =default on checkout (#73 foundation). -
Done (mvx#73): a real conversion, not a rename β the portable form carries identity +.mvxβ.mv-accountconversion.openaccount/hashand drops MVX-localpermit/denypolicy (re-seeded locally, never in git); checkout rebuilds a minimal native.mvx; status/diff compare in open-space so a local policy edit is invisible to git. One schema, shared with udt-git viamv_git_desc_open. - Open VOC/MD translation (portable entries) + master-dictionary-first rebuild.
-
udt-git: the UniData β open converter.