summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2024-09-28 17:23:32 -0600
committerJosh Rahm <joshuarahm@gmail.com>2024-09-28 17:23:32 -0600
commit719c8f8ed3d1e6337f27d3b9d5a033a4b63726b8 (patch)
tree80008d173d549ff3a347b1614d41adfb12e3e8bf
parent35b7ae9561b3dc312b857cadb3e99e14594d29a6 (diff)
downloadfiddle-719c8f8ed3d1e6337f27d3b9d5a033a4b63726b8.tar.gz
fiddle-719c8f8ed3d1e6337f27d3b9d5a033a4b63726b8.tar.bz2
fiddle-719c8f8ed3d1e6337f27d3b9d5a033a4b63726b8.zip
wip
-rw-r--r--goal.fiddle2
-rw-r--r--src/Language/Fiddle/Ast/Internal/Instances.hs18
-rw-r--r--src/Language/Fiddle/Ast/Internal/Instances/Walk.hs78
-rw-r--r--src/Language/Fiddle/Ast/Internal/SyntaxTree.hs74
-rw-r--r--src/Language/Fiddle/Compiler/ConsistencyCheck.hs19
-rw-r--r--src/Language/Fiddle/Compiler/ImportResolution.hs30
-rw-r--r--src/Language/Fiddle/Internal/Scopes.hs7
7 files changed, 180 insertions, 48 deletions
diff --git a/goal.fiddle b/goal.fiddle
index 708a44d..e6e6a28 100644
--- a/goal.fiddle
+++ b/goal.fiddle
@@ -22,6 +22,8 @@ package stm32l4.gpio {
location gpio_b_base = 0x4800_0400;
location gpio_c_base = 0x4800_0800;
+ import "/usr/fiddle/import/other_import.fdl";
+
using stm32l432;
/**
diff --git a/src/Language/Fiddle/Ast/Internal/Instances.hs b/src/Language/Fiddle/Ast/Internal/Instances.hs
index b8f6072..c9c3455 100644
--- a/src/Language/Fiddle/Ast/Internal/Instances.hs
+++ b/src/Language/Fiddle/Ast/Internal/Instances.hs
@@ -1,6 +1,14 @@
{-# LANGUAGE FunctionalDependencies #-}
-module Language.Fiddle.Ast.Internal.Instances where
+module Language.Fiddle.Ast.Internal.Instances
+ ( module X,
+ Alter (..),
+ AdvanceStage (..),
+ CompilationStage (..),
+ Annotated (..),
+ GAnnot (..)
+ )
+where
import Data.Functor.Identity
import Data.Kind
@@ -10,6 +18,7 @@ import Data.Typeable
import GHC.Generics
import GHC.TypeError as TypeError
import GHC.TypeLits
+import Language.Fiddle.Ast.Internal.Instances.Walk as X
import Language.Fiddle.Ast.Internal.Kinds
import Language.Fiddle.Ast.Internal.Stage
@@ -40,13 +49,6 @@ class Alter (t :: SynTree) where
m (t f2 a2)
alter ffn fn t = to <$> galter (proxyOf t) ffn fn (from t)
-class (Typeable t) => Visit (t :: SynTree) where
- visit ::
- (Typeable f, Typeable a, Monad m) =>
- (forall t'. (Typeable t') => t' f a -> m ()) ->
- t f a ->
- m ()
-
-- | 'CompilationStage' is a type class representing a stage in the compiler
-- pipeline. Each 'stage' has associated types that define how it transforms
-- syntax trees, manages state, and handles annotations.
diff --git a/src/Language/Fiddle/Ast/Internal/Instances/Walk.hs b/src/Language/Fiddle/Ast/Internal/Instances/Walk.hs
new file mode 100644
index 0000000..6feaff3
--- /dev/null
+++ b/src/Language/Fiddle/Ast/Internal/Instances/Walk.hs
@@ -0,0 +1,78 @@
+module Language.Fiddle.Ast.Internal.Instances.Walk (Walk (..), GWalk (..)) where
+
+import Data.Foldable (foldlM)
+import Data.Typeable
+import GHC.Generics
+
+class (Typeable t) => Walk t where
+ walk ::
+ (Monad m, Traversable f, Typeable f, Typeable a) =>
+ (forall t'. (Walk t', Typeable t', Typeable f, Typeable a) => t' f a -> s -> m s) ->
+ t f a ->
+ s ->
+ m ()
+ default walk ::
+ (GWalk (Rep (t f a)) f a, Generic (t f a), Monad m, Traversable f, Typeable f, Typeable a) =>
+ (forall t'. (Walk t', Typeable t', Typeable f, Typeable a) => t' f a -> s -> m s) ->
+ t f a ->
+ s ->
+ m ()
+ walk fn = gwalk fn . from
+
+class GWalk r f a where
+ gwalk ::
+ (Monad m, Typeable f, Typeable a, Traversable f) =>
+ (forall t'. (Walk t', Typeable t') => t' f a -> s -> m s) ->
+ r x ->
+ s ->
+ m ()
+
+instance (Traversable f, GWalk t f a) => (GWalk (M1 i c t) f a) where
+ gwalk fn (M1 a) = gwalk fn a
+
+instance
+ ( Traversable f,
+ GWalk l f a,
+ GWalk r f a
+ ) =>
+ (GWalk (l :+: r) f a)
+ where
+ gwalk fn (L1 l) = gwalk fn l
+ gwalk fn (R1 l) = gwalk fn l
+
+instance
+ ( Traversable f,
+ GWalk l f a,
+ GWalk r f a
+ ) =>
+ (GWalk (l :*: r) f a)
+ where
+ gwalk fn (l :*: r) s = gwalk fn l s >> gwalk fn r s
+
+instance
+ ( Traversable f,
+ Walk t
+ ) =>
+ GWalk (Rec0 (t f a)) f a
+ where
+ gwalk fn (K1 k) s = do
+ s' <- fn k s
+ walk fn k s'
+
+instance
+ ( Traversable f,
+ Traversable func,
+ Walk t
+ ) =>
+ GWalk (Rec0 (func (t f a))) f a
+ where
+ gwalk fn (K1 fk) s = do
+ mapM_
+ ( \tfa -> do
+ s' <- fn tfa s
+ walk fn tfa s'
+ )
+ fk
+
+instance GWalk (Rec0 q) f a where
+ gwalk _ _ _ = return ()
diff --git a/src/Language/Fiddle/Ast/Internal/SyntaxTree.hs b/src/Language/Fiddle/Ast/Internal/SyntaxTree.hs
index c37be87..706a178 100644
--- a/src/Language/Fiddle/Ast/Internal/SyntaxTree.hs
+++ b/src/Language/Fiddle/Ast/Internal/SyntaxTree.hs
@@ -51,6 +51,7 @@ module Language.Fiddle.Ast.Internal.SyntaxTree
)
where
+import Control.Monad (forM_)
import Data.Coerce
import Data.Functor.Identity
import Data.Kind (Type)
@@ -70,6 +71,9 @@ import Language.Fiddle.Ast.Internal.Kinds
import Language.Fiddle.Ast.Internal.Stage
import Language.Fiddle.Internal.UnitInterface (UnitInterface)
+type family FiddleUnitInterface (s :: Stage) :: Type where
+ FiddleUnitInterface s = If (s < Checked) () UnitInterface
+
-- | The Type of number during each stage of compilation. When in the first stage,
-- numbers are just strings like anything else. In later stages, numbers get
-- parsed into actual integers. This makes it easier to process later.
@@ -103,7 +107,7 @@ type family WitnessType (s :: Bool) where
-- to different packages.
data Name :: SynTree where
Name :: NonEmpty (Identifier f a) -> a -> Name f a
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | Represents a directive in the Fiddle language. A directive provides
-- additional metadata or instructions that the compiler can use during
@@ -117,7 +121,7 @@ data Directive :: SynTree where
directiveAnnot :: a
} ->
Directive f a
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | Represents the body of a directive, which consists of multiple elements.
data DirectiveBody :: SynTree where
@@ -128,7 +132,7 @@ data DirectiveBody :: SynTree where
directiveBodyAnnot :: a
} ->
DirectiveBody f a
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | Represents an element in a directive. Can be either a key or a key-value
-- pair.
@@ -157,7 +161,7 @@ data DirectiveElement :: SynTree where
directiveKeyValueAnnot :: a
} ->
DirectiveElement f a
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | Represents expressions that can be used within a directive, either a
-- string or a number.
@@ -176,7 +180,7 @@ data DirectiveExpression f a where
directiveNumberAnnot :: a
} ->
DirectiveExpression f a
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | A type that wraps another syntax tree and applies a list of directives to
-- it.
@@ -192,6 +196,18 @@ data Directed t stage f a where
Directed t stage f a
deriving (Generic, Annotated, Alter, Typeable)
+instance
+ (Typeable (Directed t stage), Walk (t stage)) =>
+ Walk (Directed t stage)
+ where
+ walk fn (Directed directives subtree _) s = do
+ s' <- fn subtree s
+ walk fn subtree s'
+
+ forM_ directives $ \d -> do
+ s' <- fn d s
+ walk fn d s'
+
-- | Apply a function to the underlying subtree in a 'Directed' type.
mapDirected :: (t s f a -> t' s' f a) -> Directed t s f a -> Directed t' s' f a
mapDirected fn (Directed dr tfa a) = Directed dr (fn tfa) a
@@ -219,11 +235,14 @@ data FiddleUnit (stage :: Stage) (f :: Type -> Type) a where
FiddleUnit ::
{ -- | List of declarations.
fiddleDecls :: [Directed FiddleDecl stage f a],
+ -- | The interface for this FiddleUnit. Early on, this is just () because
+ -- not enough information is provided to determine the interface..
+ fiddleUnitInterface :: FiddleUnitInterface stage,
-- | Annotation for the 'FiddleUnit'.
fiddleUnitAnnot :: a
} ->
FiddleUnit stage f a
- deriving (Generic, Annotated, Typeable, Alter)
+ deriving (Generic, Annotated, Typeable, Alter, Walk)
-- | Represents an identifier with an associated annotation.
data Identifier f a = Identifier
@@ -232,7 +251,7 @@ data Identifier f a = Identifier
-- | Annotation for the identifier.
identifierAnnot :: a
}
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | Expressions used within Fiddle, including literals and variables.
data Expression (s :: Stage) :: SynTree where
@@ -252,7 +271,7 @@ data Expression (s :: Stage) :: SynTree where
varAnnot :: a
} ->
Expression stage f a
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | Represents an import statement in the Fiddle language.
data ImportStatement stage f a where
@@ -261,14 +280,12 @@ data ImportStatement stage f a where
importPath :: Text,
-- | Optional list of imported items.
importList :: Maybe (ImportList f a),
-
importInterface :: ImportInterface stage,
-
-- | Annotation for the import statement.
importStatementAnnot :: a
} ->
ImportStatement stage f a
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | A list of imported identifiers.
data ImportList f a where
@@ -279,7 +296,7 @@ data ImportList f a where
importListAnnot :: a
} ->
ImportList f a
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | Represents top-level declarations in Fiddle.
data FiddleDecl :: StagedSynTree where
@@ -297,12 +314,11 @@ data FiddleDecl :: StagedSynTree where
ImportDecl ::
{ -- | The imported type.
importStatement :: ImportStatement stage f a,
+ -- \| Annotation for the import declaration.
-- | The interface for this imported file. This type depends on the stage
-- of compilation. Initially it's just '()', but will eventually be resolved
-- into a 'UnitInterface'.
-
- -- | Annotation for the import declaration.
importDeclAnnot :: a
} ->
FiddleDecl stage f a
@@ -366,7 +382,7 @@ data FiddleDecl :: StagedSynTree where
objectAnnot :: a
} ->
FiddleDecl stage f a
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | Represents the body of an object type, containing a body type (struct or
-- union), a list of object declarations, and an annotation.
@@ -380,7 +396,7 @@ data ObjTypeBody (stage :: Stage) (f :: Type -> Type) a where
objBodyAnnot :: a
} ->
ObjTypeBody stage f a
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | Represents an object type, which can be anonymous, an array, or a
-- reference to another type.
@@ -413,7 +429,7 @@ data ObjType stage f a where
refAnnot :: a
} ->
ObjType stage f a
- deriving (Typeable, Generic, Alter, Annotated, Typeable)
+ deriving (Typeable, Generic, Alter, Annotated, Typeable, Walk)
-- | Represents a declaration inside an object type, such as a register, an
-- assertion, or a substructure.
@@ -460,7 +476,7 @@ data ObjTypeDecl stage f a where
subStructureAnnot :: a
} ->
ObjTypeDecl stage f a
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | Represents a modifier for registers (e.g., read-only, read-write).
data Modifier f a where
@@ -471,7 +487,7 @@ data Modifier f a where
modifierAnnot :: a
} ->
Modifier f a
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | Enumerates the different types of register modifiers.
data ModifierKeyword = Rw | Ro | Wo
@@ -487,7 +503,7 @@ data DeferredRegisterBody stage f a where
deferredAnnot :: a
} ->
DeferredRegisterBody stage f a
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | Represents the body type (struct or union) in an object.
data BodyType (f :: Type -> Type) a where
@@ -501,7 +517,7 @@ data BodyType (f :: Type -> Type) a where
structAnnot :: a
} ->
BodyType f a
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | Represents a register body with a body type and deferred bit declarations.
data RegisterBody stage f a where
@@ -514,7 +530,7 @@ data RegisterBody stage f a where
regBodyAnnot :: a
} ->
RegisterBody stage f a
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | Represents declarations within a register, such as defined bits,
-- reserved bits, or substructures.
@@ -549,7 +565,7 @@ data RegisterBitsDecl stage f a where
bitsSubAnnot :: a
} ->
RegisterBitsDecl stage f a
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | Represents different ways to refer to register bits, either as an array,
-- a reference to a type, an anonymous type, or just bits.
@@ -590,7 +606,7 @@ data RegisterBitsTypeRef stage f a where
justBitsAnnot :: a
} ->
RegisterBitsTypeRef stage f a
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | Represents an anonymous bit type, such as an enum, used in Parsed.
data AnonymousBitsType stage f a where
@@ -603,7 +619,7 @@ data AnonymousBitsType stage f a where
anonEnumAnnot :: a
} ->
AnonymousBitsType stage f a
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | Represents a bit type, either an enumeration or raw bits.
data BitType (stage :: Stage) (f :: Type -> Type) a where
@@ -625,7 +641,7 @@ data BitType (stage :: Stage) (f :: Type -> Type) a where
rawBitsAnnot :: a
} ->
BitType stage f a
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | Represents the body of an enumeration.
data EnumBody (stage :: Stage) (f :: Type -> Type) a where
@@ -636,7 +652,7 @@ data EnumBody (stage :: Stage) (f :: Type -> Type) a where
enumBodyAnnot :: a
} ->
EnumBody stage f a
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | Represents a declaration for an enumeration constant.
data EnumConstantDecl stage f a where
@@ -658,7 +674,7 @@ data EnumConstantDecl stage f a where
enumReservedAnnot :: a
} ->
EnumConstantDecl stage f a
- deriving (Generic, Annotated, Alter, Typeable)
+ deriving (Generic, Annotated, Alter, Typeable, Walk)
-- | Represents the body of a package, containing a list of declarations.
data PackageBody (stage :: Stage) (f :: Type -> Type) a where
@@ -669,7 +685,7 @@ data PackageBody (stage :: Stage) (f :: Type -> Type) a where
packageBodyAnnot :: a
} ->
PackageBody stage f a
- deriving (Generic, Annotated, Typeable, Alter)
+ deriving (Generic, Annotated, Typeable, Alter, Walk)
squeeze :: (Alter t, Traversable f, Monad f) => t f a -> f (t Identity a)
squeeze = alter (fmap Identity) return
diff --git a/src/Language/Fiddle/Compiler/ConsistencyCheck.hs b/src/Language/Fiddle/Compiler/ConsistencyCheck.hs
index 5c7b399..908db52 100644
--- a/src/Language/Fiddle/Compiler/ConsistencyCheck.hs
+++ b/src/Language/Fiddle/Compiler/ConsistencyCheck.hs
@@ -33,12 +33,15 @@ import GHC.TypeLits
import Language.Fiddle.Ast
import Language.Fiddle.Compiler
import Language.Fiddle.Internal.Scopes
+import Language.Fiddle.Internal.UnitInterface
import Language.Fiddle.Types (Commented (unCommented), SourceSpan)
import Text.Printf (printf)
import Prelude hiding (unzip)
-newtype GlobalState = GlobalState
- { globalScope :: Scope String (Either SizeBits SizeBytes)
+data GlobalState = GlobalState
+ { globalScope :: Scope String (Either SizeBits SizeBytes),
+ fileDependencies :: [FilePath],
+ unitInterface :: UnitInterface
}
newtype LocalState = LocalState (ScopePath String)
@@ -61,7 +64,7 @@ checkConsistency ::
Compile () (FiddleUnit Checked I Annot)
checkConsistency =
fmap snd
- . subCompile (GlobalState mempty)
+ . subCompile (GlobalState mempty mempty)
. advanceStage (LocalState mempty)
instance CompilationStage Checked where
@@ -78,7 +81,11 @@ instance CompilationStage Expanded where
type StageFunctor Expanded = Identity
type StageAnnotation Expanded = Commented SourceSpan
-deriving instance AdvanceStage Expanded FiddleUnit
+instance AdvanceStage Expanded FiddleUnit
+
+-- advanceStage localState (FiddleUnit decls _ annot) = do
+
+-- decls' <- mapM (advanceStage localState) decls
deriving instance AdvanceStage Expanded Expression
@@ -528,7 +535,7 @@ insertTypeSize ::
Compile GlobalState ()
insertTypeSize (LocalState scopePath) (Identifier s annot) size = do
modifyM $
- \(GlobalState globalScope) ->
+ \state@GlobalState {globalScope = globalScope} ->
let fullName =
NonEmpty.prependList
(currentScope scopePath)
@@ -537,7 +544,7 @@ insertTypeSize (LocalState scopePath) (Identifier s annot) size = do
(Just _, _) -> do
diagnosticError (printf "Duplicate type %s" s) annot
compilationFailure
- (Nothing, n) -> return $ GlobalState n
+ (Nothing, n) -> return $ state {globalScope = n}
where
modifyM fn = do
s <- get
diff --git a/src/Language/Fiddle/Compiler/ImportResolution.hs b/src/Language/Fiddle/Compiler/ImportResolution.hs
index 90a11d5..47eec72 100644
--- a/src/Language/Fiddle/Compiler/ImportResolution.hs
+++ b/src/Language/Fiddle/Compiler/ImportResolution.hs
@@ -1,3 +1,6 @@
+{-# LANGUAGE DerivingStrategies #-}
+{-# LANGUAGE GeneralisedNewtypeDeriving #-}
+
module Language.Fiddle.Compiler.ImportResolution
( resolveImports,
getImportResolutionState,
@@ -6,11 +9,12 @@ module Language.Fiddle.Compiler.ImportResolution
where
import Control.Monad.Identity (Identity)
-import Control.Monad.Writer.Lazy (MonadWriter (tell))
+import Control.Monad.Writer.Lazy (MonadTrans (lift), MonadWriter (tell), WriterT (WriterT), execWriterT)
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Text (Text)
import qualified Data.Text as Text
+import Data.Typeable
import Language.Fiddle.Ast
import Language.Fiddle.Ast.FileInterface (ResolvedImport)
import Language.Fiddle.Compiler
@@ -18,6 +22,7 @@ import Language.Fiddle.Compiler.Expansion
import Language.Fiddle.Internal.UnitInterface
import Language.Fiddle.Types
import Options.Applicative
+import System.IO (hPutStrLn, stderr)
import Text.Printf (printf)
newtype Flags = Flags
@@ -55,6 +60,7 @@ data ImportError = ImportError Text (Maybe SourceSpan)
newtype ResolvedImports = ResolvedImports
{ importMap :: Map Text (Either ImportError UnitInterface)
}
+ deriving newtype (Semigroup, Monoid)
type CurrentStage = Parsed
@@ -129,4 +135,24 @@ getImportResolutionState ::
Flags ->
FiddleUnit CurrentStage Identity Annot ->
IO ResolvedImports
-getImportResolutionState _ _ = return (ResolvedImports mempty)
+getImportResolutionState flags unit =
+ execWriterT $
+ walk doWalk unit ()
+ where
+ -- doWalk :: forall t'. (Walk t', Typeable t') => t' Identity Annot -> () -> WriterT ResolvedImports IO ()
+ doWalk u () =
+ case () of
+ () | Just (ImportStatement {importPath = path}) <- castTS u -> do
+ lift $ hPutStrLn stderr $ "Import path: " ++ show path
+ (return () :: WriterT ResolvedImports IO ())
+ _ -> return ()
+
+ castTS ::
+ ( Typeable t',
+ Typeable t,
+ Typeable f,
+ Typeable a
+ ) =>
+ t' f a ->
+ Maybe (t CurrentStage f a)
+ castTS = cast
diff --git a/src/Language/Fiddle/Internal/Scopes.hs b/src/Language/Fiddle/Internal/Scopes.hs
index 83ea144..eea4c6f 100644
--- a/src/Language/Fiddle/Internal/Scopes.hs
+++ b/src/Language/Fiddle/Internal/Scopes.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE DeriveFoldable #-}
+
module Language.Fiddle.Internal.Scopes where
import Control.Monad (forM)
@@ -14,7 +16,7 @@ data Scope k v = Scope
{ subScopes :: Map k (Scope k v), -- Nested sub-scopes
scopeValues :: Map k v -- Values stored in the current scope
}
- deriving (Eq, Ord, Show, Read)
+ deriving (Eq, Ord, Show, Read, Functor, Foldable)
-- | 'ScopePath' keeps track of the current scope path as a list of keys,
-- and also includes any additional paths (like imported modules or
@@ -50,7 +52,7 @@ instance Monoid (ScopePath k) where
-- 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.
@@ -65,7 +67,6 @@ upsertScope (s :| (a : as)) v (Scope 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.
lookupScope :: (Ord k) => NonEmpty k -> Scope k t -> Maybe t