module shape
module lib/shape.mu
import "shape"
shape provides helpers for tagged map values.
A shape is still an ordinary map. The __type field names a recurring data contract so type(value) reports that name instead of "MAP".
Imports
Functions
is#
is reports whether value carries the provided runtime type tag.
Source lib/shape.mu:113
fn is(value, type_name) {
if !typing.is_str(type_name) {
return false
}
return type(value) == type_name
}kind#
kind returns value.kind for map-like values, or nil when no kind is present.
Source lib/shape.mu:154
fn kind(value) {
if !_is_map_like(value) || !_has_key(value, "kind") {
return nil
}
return value["kind"]
}new#
new returns a tagged map by copying fields and optional methods into a fresh value. Method entries must be functions and may not replace fields.
Source lib/shape.mu:84
fn new(type_name, fields, methods...) {
if !typing.is_str(type_name) || type_name == "" {
return error("shape.new expects a non-empty string type name")
}
if !_is_map_like(fields) {
return error("shape.new expects fields map, got " + type(fields))
}
if len(methods) > 1 {
return error("shape.new expects at most one methods map")
}
value := {}
err := _copy_fields(fields, value, "shape.new fields")
if is_error(err) {
return err
}
if len(methods) == 1 && methods[0] != nil {
if !_is_map_like(methods[0]) {
return error("shape.new expects methods map, got " + type(methods[0]))
}
err = _copy_methods(methods[0], value)
if is_error(err) {
return err
}
}
value["__type"] = type_name
return value
}require#
require returns nil when value carries type_name, otherwise an error value.
Source lib/shape.mu:121
fn require(value, type_name) {
if !typing.is_str(type_name) || type_name == "" {
return error("shape.require expects a non-empty string type name")
}
if type(value) != type_name {
return error("shape.require expected " + type_name + ", got " + type(value))
}
return nil
}require_fields#
require_fields verifies that value is a map-like value with all named fields.
Source lib/shape.mu:132
fn require_fields(value, fields) {
if !_is_map_like(value) {
return error("shape.require_fields expects map-like value, got " + type(value))
}
if !typing.is_list(fields) {
return error("shape.require_fields expects list of field names, got " + type(fields))
}
i := 0
while i < len(fields) {
field := fields[i]
if !typing.is_str(field) {
return error("shape.require_fields expects string field names, got " + type(field))
}
if !_has_key(value, field) {
return error("shape.require_fields missing " + field)
}
i = i + 1
}
return nil
}require_kind#
require_kind verifies the conventional kind discriminator on a map-like value.
Source lib/shape.mu:162
fn require_kind(value, expected) {
if !typing.is_str(expected) || expected == "" {
return error("shape.require_kind expects a non-empty string kind")
}
if kind(value) != expected {
return error("shape.require_kind expected " + expected)
}
return nil
}Internal helpers
Underscore-prefixed names are implementation detail. They are listed so the module's source reads without surprises, not as API — they may change at any time.
| _copy_fields(source, target, context) | — |
| _copy_methods(source, target) | — |
| _has_key(value, key) | — |
| _is_map_like(value) | — |
| _keys(value) | — |