feat: Add enum support
This commit is contained in:
parent
2e576e10ab
commit
661e09daac
2 changed files with 22 additions and 15 deletions
37
yants.nix
37
yants.nix
|
@ -2,13 +2,10 @@
|
||||||
# polymorphic types as well as the ability to define & check records.
|
# polymorphic types as well as the ability to define & check records.
|
||||||
#
|
#
|
||||||
# All types (should) compose as expected.
|
# All types (should) compose as expected.
|
||||||
#
|
|
||||||
# TODO(tazjin): enums?
|
|
||||||
|
|
||||||
{ toPretty ? ((import <nixpkgs> {}).lib.generators.toPretty {}) }:
|
{ toPretty ? ((import <nixpkgs> {}).lib.generators.toPretty {}) }:
|
||||||
|
|
||||||
with builtins; let
|
with builtins; let
|
||||||
# Internal utilities:
|
|
||||||
typeError = type: val:
|
typeError = type: val:
|
||||||
throw "Expected type '${type}', but value '${toPretty val}' is of type '${typeOf val}'";
|
throw "Expected type '${type}', but value '${toPretty val}' is of type '${typeOf val}'";
|
||||||
|
|
||||||
|
@ -49,18 +46,30 @@ with builtins; let
|
||||||
struct' = name: def: {
|
struct' = name: def: {
|
||||||
inherit name def;
|
inherit name def;
|
||||||
check = value:
|
check = value:
|
||||||
let
|
let fieldMatch = foldl' (checkField def value) true (attrNames def);
|
||||||
fieldMatch = foldl' (checkField def value) true (attrNames def);
|
noExtras = checkExtraneous name def (attrNames value);
|
||||||
noExtras = checkExtraneous name def (attrNames value);
|
|
||||||
in (isAttrs value && fieldMatch && noExtras);
|
in (isAttrs value && fieldMatch && noExtras);
|
||||||
|
|
||||||
__functor = self: value: if self.check value
|
__functor = self: value: if self.check value then value
|
||||||
then value
|
|
||||||
else (throw "Expected '${self.name}'-struct, but ${toPretty value} is of type ${typeOf value}");
|
else (throw "Expected '${self.name}'-struct, but ${toPretty value} is of type ${typeOf value}");
|
||||||
};
|
};
|
||||||
|
|
||||||
struct = arg: if isString arg then (struct' arg)
|
struct = arg: if isString arg then (struct' arg)
|
||||||
else (struct' "anonymous" arg);
|
else (struct' "anonymous" arg);
|
||||||
|
|
||||||
|
enum = name: values: rec {
|
||||||
|
inherit name values;
|
||||||
|
check = (x: elem x values);
|
||||||
|
__functor = self: x: if self.check x then x
|
||||||
|
else (throw "'${x}' is not a member of enum '${self.name}'");
|
||||||
|
match = x: actions: let
|
||||||
|
actionKeys = map (__functor { inherit name check; }) (attrNames actions);
|
||||||
|
missing = foldl' (m: k: if (elem k actionKeys) then m else m ++ [ k ]) [] values;
|
||||||
|
in if (length missing) > 0
|
||||||
|
then throw "Missing match action for members: ${toPretty missing}"
|
||||||
|
else actions."${__functor { inherit name check; } x}";
|
||||||
|
};
|
||||||
|
|
||||||
in (typeSet [
|
in (typeSet [
|
||||||
# Primitive types
|
# Primitive types
|
||||||
(typedef "any" (_: true))
|
(typedef "any" (_: true))
|
||||||
|
@ -79,12 +88,10 @@ in (typeSet [
|
||||||
else throw "Expected list element of type '${t.name}', but '${toPretty e}' is of type '${typeOf e}'"
|
else throw "Expected list element of type '${t.name}', but '${toPretty e}' is of type '${typeOf e}'"
|
||||||
)) true v)))
|
)) true v)))
|
||||||
|
|
||||||
(poly "attrs" (t: v:
|
(poly "attrs" (t: v: isAttrs v && (foldl' (s: e: s && (
|
||||||
isAttrs v && (foldl' (s: e: s && (
|
if t.check e then true
|
||||||
if t.check e then true
|
else throw "Expected attribute set element of type '${t.name}', but '${toPretty e}' is of type '${typeOf e}'"
|
||||||
else throw "Expected attribute set element of type '${t.name}', but '${toPretty e}' is of type '${typeOf e}'"
|
)) true (attrValues v))))
|
||||||
)) true (attrValues v))
|
|
||||||
))
|
|
||||||
|
|
||||||
(poly2 "either" (t1: t2: v: t1.check v || t2.check v))
|
(poly2 "either" (t1: t2: v: t1.check v || t2.check v))
|
||||||
]) // { inherit struct; }
|
]) // { inherit struct enum; }
|
||||||
|
|
BIN
z-enums.png
Normal file
BIN
z-enums.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 40 KiB |
Loading…
Reference in a new issue