From 3d9ec28bfc7cdc67377ce2d9a7276cfe6e488686 Mon Sep 17 00:00:00 2001 From: Emile Clark-Boman Date: Thu, 18 Dec 2025 11:26:47 +1000 Subject: [PATCH] bleeding: typesystem --- nib/default.nix | 10 +++++++-- nib/enforce.nix | 14 +++++++++++++ nib/panic.nix | 4 ++-- nib/patterns.nix | 47 +++++++++++++++++++++++++++++++++++++++++++ nib/types/default.nix | 8 ++++++++ nib/typesystem.nix | 9 +++++++++ 6 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 nib/enforce.nix create mode 100644 nib/patterns.nix create mode 100644 nib/typesystem.nix diff --git a/nib/default.nix b/nib/default.nix index a6448a6..04ae032 100644 --- a/nib/default.nix +++ b/nib/default.nix @@ -4,9 +4,13 @@ mkMod = mkMod' {inherit systems nib;}; std = mkMod ./std; - types = mkMod ./types; - parse = mkMod ./parse; panic = mkMod ./panic.nix; + parse = mkMod ./parse; + patterns = mkMod ./patterns.nix; + + types = mkMod ./types; + typesystem = mkMod ./typesystem.nix; + sys = mkMod ./sys.nix; nib = std.mergeAttrsList [ @@ -15,6 +19,8 @@ {inherit std types panic parse;} # submodule content accessible directly (ie self.myFunc) + patterns + typesystem sys ]; in diff --git a/nib/enforce.nix b/nib/enforce.nix new file mode 100644 index 0000000..d6801aa --- /dev/null +++ b/nib/enforce.nix @@ -0,0 +1,14 @@ +{nib, ...}: rec { + enfType = type: T: + assert (nib.isType type T + || nib.panic.badType (nib.typeName type)); true; + + enfSameType = T1: T2: enfType (nib.typeOf T1) T2; + + enfAttrs = enfType (nib.typeOf {}); + enfList = enfType (nib.typeOf []); + enfListOf = type: L: + assert (enfList L + && builtins.all (T: nib.isType type T) L + || nib.panic.badType "List ${nib.typeName type}" L); true; +} diff --git a/nib/panic.nix b/nib/panic.nix index eb73ca8..5fb63b0 100644 --- a/nib/panic.nix +++ b/nib/panic.nix @@ -1,4 +1,4 @@ -{...}: { +{nib, ...}: { badType = expect: x: - throw "Expected type ${expect} but got ${builtins.typeOf x}."; + throw "Expected type ${expect} but got ${nib.typeOf x}."; } diff --git a/nib/patterns.nix b/nib/patterns.nix new file mode 100644 index 0000000..b78e927 --- /dev/null +++ b/nib/patterns.nix @@ -0,0 +1,47 @@ +{nib, ...}: let + # Rust inspired pattern matching syntax: + # resultA = match [platform arch] [ + # (Pattern ["darwin" Any] darwin_package) + # (Pattern ["openbsd" "x86_64"] openbsd_x86_64_package) + # (Pattern [(x: x == "linux") (y: y == "x86_64")] linux_x86_64_package) + # (Pattern (x: y: x == "linux" && y == "aarch64") linux_aarch64_package) + # (Pattern Any default_package) + # ]; + # resultB = match [platform arch] [ + # (["darwin" Any] |> case darwin_package) + # (["openbsd" "x86_64"] |> case openbsd_x86_64_package) + # ([(x: x == "linux") (y: y == "x86_64")] |> case linux_x86_64_package) + # ((x: y: x == "linux" && y == "aarch64") |> case linux_aarch64_package) + # (Any |> case default_package) + # ]; + types = nib.types; +in rec { + Pattern = pattern: return: throw "not implemented"; + case = return: pattern: Pattern pattern return; + + matchesPattern' = pattern: subject: let + recurse = p: s: + nib.isSameType p s + && ( + if nib.isList p + then builtins.all (map (p: recurse p)) (nib.std.zipLists) + else if nib.isAttrs p + then builtins.all () + else nib.eq p s + ); + in + recurse pattern subject; + + # maybe' :: TList a b -> TList [TPattern c d] -> TMaybe d + match' = subject: patterns: + nib.enfType (types.TList types.TPattern) patterns + && builtins.foldl' ( + fix: p: + if types.isNone fix + # maintain None as a fixed value + then fix + else matchesPattern' p + ) + types.Some + patterns; +} diff --git a/nib/types/default.nix b/nib/types/default.nix index 06fdace..eb2e71c 100644 --- a/nib/types/default.nix +++ b/nib/types/default.nix @@ -10,4 +10,12 @@ in maybe res terminal + + rec { + # TODO + isAlgebraic = T: false; + + isList = T: !isAlgebraic T && builtins.isList T; + isAttrs = T: !isAlgebraic T && builtins.isAttrs T; + } ] diff --git a/nib/typesystem.nix b/nib/typesystem.nix new file mode 100644 index 0000000..7f2d2e2 --- /dev/null +++ b/nib/typesystem.nix @@ -0,0 +1,9 @@ +{...}: rec { + isType = type: T: type == typeOf T; + isSameType = T1: T2: typeOf T1 == typeOf T2; + + # TODO + typeOf = builtins.typeOf; + # TODO + typeName = typeOf; +}