summaryrefslogtreecommitdiff
path: root/src/Language/Fiddle/Internal
diff options
context:
space:
mode:
Diffstat (limited to 'src/Language/Fiddle/Internal')
-rw-r--r--src/Language/Fiddle/Internal/Scopes.hs34
1 files changed, 20 insertions, 14 deletions
diff --git a/src/Language/Fiddle/Internal/Scopes.hs b/src/Language/Fiddle/Internal/Scopes.hs
index 280945d..302eab2 100644
--- a/src/Language/Fiddle/Internal/Scopes.hs
+++ b/src/Language/Fiddle/Internal/Scopes.hs
@@ -43,20 +43,26 @@ instance Semigroup (ScopePath k) where
instance Monoid (ScopePath k) where
mempty = ScopePath mempty mempty
--- | 'insertScope' inserts a value 'v' into the scope at the specified
--- key path ('NonEmpty k'). If the key path does not exist, it is created.
-insertScope :: (Ord k) => NonEmpty k -> t -> Scope k t -> Scope k t
-insertScope (s :| []) v (Scope ss sv) = Scope ss (Map.insert s v sv)
-insertScope (s :| (a : as)) v (Scope ss sv) =
- Scope
- ( Map.alter
- ( \case
- (fromMaybe mempty -> mp) -> Just (insertScope (a :| as) v mp)
- )
- s
- ss
- )
- sv
+-- | 'upsertScope' attempts to insert a value 'v' into the 'Scope' at the given
+-- key path ('NonEmpty k'). If the key path already exists, the value at the
+-- final key is replaced, and the original value is returned in the result.
+-- If the key path does not exist, it is created. The function returns a tuple
+-- containing the previous value (if any) and the updated scope.
+--
+-- This function effectively performs an "insert-or-update" operation, allowing
+-- you to upsert values into nested scopes while tracking any existing value
+-- that was replaced.
+upsertScope :: (Ord k) => NonEmpty k -> t -> Scope k t -> (Maybe t, Scope k t)
+upsertScope (s :| []) v (Scope ss sv) =
+ Scope ss <$> Map.insertLookupWithKey (\_ n _ -> n) s v sv
+upsertScope (s :| (a : as)) v (Scope ss sv) =
+ let subscope = fromMaybe mempty (Map.lookup s ss)
+ (replaced, subscope') = upsertScope (a :| as) v subscope
+ in (replaced, Scope (Map.insert s subscope' ss) sv)
+
+-- insertScope :: (Ord k) => NonEmpty k -> t -> Scope k t -> Scope k t
+-- insertScope a b = snd . upsertScope a b
+
-- | 'lookupScope' performs a lookup of a value in the scope using a key path
-- ('NonEmpty k'). It traverses through sub-scopes as defined by the path.