Add syntactic holes
This commit is contained in:
parent
f3970d49b9
commit
28ab983408
|
@ -41,6 +41,7 @@ import Nix.Utils
|
|||
|
||||
class (Show v, Monad m) => MonadEval v m where
|
||||
freeVariable :: Text -> m v
|
||||
synHole :: Text -> m v
|
||||
attrMissing :: NonEmpty Text -> Maybe v -> m v
|
||||
evaledSym :: Text -> v -> m v
|
||||
evalCurPos :: m v
|
||||
|
@ -91,10 +92,18 @@ data EvalFrame m v
|
|||
= EvaluatingExpr (Scopes m v) NExprLoc
|
||||
| ForcingExpr (Scopes m v) NExprLoc
|
||||
| Calling String SrcSpan
|
||||
| SynHole (SynHoleInfo m v)
|
||||
deriving (Show, Typeable)
|
||||
|
||||
instance (Typeable m, Typeable v) => Exception (EvalFrame m v)
|
||||
|
||||
data SynHoleInfo m t = SynHoleInfo
|
||||
{ _synHoleInfo_expr :: NExprLoc
|
||||
, _synHoleInfo_scope :: Scopes m t
|
||||
} deriving (Show, Typeable)
|
||||
|
||||
instance (Typeable m, Typeable t) => Exception (SynHoleInfo m t)
|
||||
|
||||
eval :: forall v t m. MonadNixEval v t m => NExprF (m v) -> m v
|
||||
|
||||
eval (NSym "__curPos") = evalCurPos
|
||||
|
@ -148,6 +157,8 @@ eval (NAbs params body) = do
|
|||
args <- buildArgument params arg
|
||||
pushScope args (k (M.map (`force` pure) args) body)
|
||||
|
||||
eval (NSynHole name) = synHole name
|
||||
|
||||
-- | If you know that the 'scope' action will result in an 'AttrSet t', then
|
||||
-- this implementation may be used as an implementation for 'evalWith'.
|
||||
evalWithAttrSet :: forall v t m. MonadNixEval v t m => m v -> m v -> m v
|
||||
|
|
|
@ -151,6 +151,14 @@ instance MonadNix e m => MonadEval (NValue m) m where
|
|||
freeVariable var =
|
||||
nverr $ ErrorCall $ "Undefined variable '" ++ Text.unpack var ++ "'"
|
||||
|
||||
synHole name = do
|
||||
span <- currentPos
|
||||
scope <- currentScopes @_ @(NThunk m)
|
||||
evalError @(NValue m) $ SynHole $ SynHoleInfo
|
||||
{ _synHoleInfo_expr = Fix $ NSynHole_ span name
|
||||
, _synHoleInfo_scope = scope
|
||||
}
|
||||
|
||||
attrMissing ks Nothing =
|
||||
evalError @(NValue m) $ ErrorCall $
|
||||
"Inheriting unknown attribute: "
|
||||
|
|
|
@ -70,6 +70,12 @@ mkSym = Fix . mkSymF
|
|||
mkSymF :: Text -> NExprF a
|
||||
mkSymF = NSym
|
||||
|
||||
mkSynHole :: Text -> NExpr
|
||||
mkSynHole = Fix . mkSynHoleF
|
||||
|
||||
mkSynHoleF :: Text -> NExprF a
|
||||
mkSynHoleF = NSynHole
|
||||
|
||||
mkSelector :: Text -> NAttrPath NExpr
|
||||
mkSelector = (:| []) . StaticKey
|
||||
|
||||
|
|
|
@ -134,6 +134,8 @@ data NExprF r
|
|||
-- evaluate the second argument.
|
||||
| NAssert !r !r
|
||||
-- ^ Assert that the first returns true before evaluating the second.
|
||||
| NSynHole !VarName
|
||||
-- ^ Syntactic hole, e.g. @^foo@ , @^hole_name@
|
||||
deriving (Ord, Eq, Generic, Generic1, Typeable, Data, Functor,
|
||||
Foldable, Traversable, Show, NFData, Hashable)
|
||||
|
||||
|
|
|
@ -190,6 +190,9 @@ nullSpan = SrcSpan nullPos nullPos
|
|||
pattern NSym_ :: SrcSpan -> VarName -> NExprLocF r
|
||||
pattern NSym_ ann x = Compose (Ann ann (NSym x))
|
||||
|
||||
pattern NSynHole_ :: SrcSpan -> Text -> NExprLocF r
|
||||
pattern NSynHole_ ann x = Compose (Ann ann (NSynHole x))
|
||||
|
||||
pattern NConstant_ :: SrcSpan -> NAtom -> NExprLocF r
|
||||
pattern NConstant_ ann x = Compose (Ann ann (NConstant x))
|
||||
|
||||
|
|
|
@ -129,7 +129,8 @@ nixTerm = do
|
|||
x == '<' ||
|
||||
x == '/' ||
|
||||
x == '"' ||
|
||||
x == '\''
|
||||
x == '\''||
|
||||
x == '^'
|
||||
case c of
|
||||
'(' -> nixSelect nixParens
|
||||
'{' -> nixSelect nixSet
|
||||
|
@ -138,6 +139,7 @@ nixTerm = do
|
|||
'/' -> nixPath
|
||||
'"' -> nixString
|
||||
'\'' -> nixString
|
||||
'^' -> nixSynHole
|
||||
_ -> msum $
|
||||
[ nixSelect nixSet | c == 'r' ] ++
|
||||
[ nixPath | pathChar c ] ++
|
||||
|
@ -157,6 +159,9 @@ nixToplevelForm = keywords <+> nixLambda <+> nixExpr
|
|||
nixSym :: Parser NExprLoc
|
||||
nixSym = annotateLocation1 $ mkSymF <$> identifier
|
||||
|
||||
nixSynHole :: Parser NExprLoc
|
||||
nixSynHole = annotateLocation1 $ mkSynHoleF <$> (char '^' >> identifier)
|
||||
|
||||
nixInt :: Parser NExprLoc
|
||||
nixInt = annotateLocation1 (mkIntF <$> integer <?> "integer")
|
||||
|
||||
|
|
|
@ -256,6 +256,7 @@ exprFNixDoc = \case
|
|||
[ "assert" <+> withoutParens cond <> semi
|
||||
, align $ withoutParens body
|
||||
]
|
||||
NSynHole name -> simpleExpr $ pretty ("^" <> unpack name)
|
||||
where
|
||||
recPrefix = "rec" <> space
|
||||
|
||||
|
|
|
@ -75,12 +75,13 @@ renderFrame :: forall v e m ann.
|
|||
MonadFile m, Typeable m, Typeable v)
|
||||
=> NixFrame -> m [Doc ann]
|
||||
renderFrame (NixFrame level f)
|
||||
| Just (e :: EvalFrame m v) <- fromException f = renderEvalFrame level e
|
||||
| Just (e :: ThunkLoop) <- fromException f = renderThunkLoop level e
|
||||
| Just (e :: ValueFrame m) <- fromException f = renderValueFrame level e
|
||||
| Just (e :: NormalLoop m) <- fromException f = renderNormalLoop level e
|
||||
| Just (e :: ExecFrame m) <- fromException f = renderExecFrame level e
|
||||
| Just (e :: ErrorCall) <- fromException f = pure [pretty (show e)]
|
||||
| Just (e :: EvalFrame m v) <- fromException f = renderEvalFrame level e
|
||||
| Just (e :: ThunkLoop) <- fromException f = renderThunkLoop level e
|
||||
| Just (e :: ValueFrame m) <- fromException f = renderValueFrame level e
|
||||
| Just (e :: NormalLoop m) <- fromException f = renderNormalLoop level e
|
||||
| Just (e :: ExecFrame m) <- fromException f = renderExecFrame level e
|
||||
| Just (e :: ErrorCall) <- fromException f = pure [pretty (show e)]
|
||||
| Just (e :: SynHoleInfo m v) <- fromException f = pure [text (show e)]
|
||||
| otherwise = error $ "Unrecognized frame: " ++ show f
|
||||
|
||||
wrapExpr :: NExprF r -> NExpr
|
||||
|
@ -107,7 +108,15 @@ renderEvalFrame level f = do
|
|||
fmap (:[]) $ renderLocation ann $
|
||||
"While calling builtins." <> pretty name
|
||||
|
||||
_ -> pure []
|
||||
SynHole synfo -> sequence $
|
||||
let e@(Fix (Compose (Ann ann _))) = _synHoleInfo_expr synfo
|
||||
in [ renderLocation ann =<<
|
||||
renderExpr level "While evaluating" "Syntactic Hole" e
|
||||
, pure $ text $ show (_synHoleInfo_scope synfo)
|
||||
]
|
||||
|
||||
ForcingExpr _ _ -> pure []
|
||||
|
||||
|
||||
renderExpr :: (MonadReader e m, Has e Options, MonadFile m)
|
||||
=> NixLevel -> String -> String -> NExprLoc -> m (Doc ann)
|
||||
|
|
|
@ -61,6 +61,7 @@ freeVars e = case unFix e of
|
|||
-- This also makes sense because its value can be overridden by `x: with y; x`
|
||||
(NWith set expr) -> freeVars set `Set.union` freeVars expr
|
||||
(NAssert assertion expr) -> freeVars assertion `Set.union` freeVars expr
|
||||
(NSynHole _) -> Set.empty
|
||||
|
||||
where
|
||||
|
||||
|
|
|
@ -369,6 +369,10 @@ instance ( MonadFreshId Int m
|
|||
tv <- fresh
|
||||
return $ Judgment (As.singleton var tv) [] tv
|
||||
|
||||
synHole var = do
|
||||
tv <- fresh
|
||||
return $ Judgment (As.singleton var tv) [] tv
|
||||
|
||||
-- If we fail to look up an attribute, we just don't know the type.
|
||||
attrMissing _ _ = Judgment As.empty [] <$> fresh
|
||||
|
||||
|
|
Loading…
Reference in a new issue