parsing and desugaring of do blocks. (Some inference issues remain.)

This commit is contained in:
2024-10-29 20:20:05 -07:00
parent e8de2d4ccd
commit b844d0b676
6 changed files with 91 additions and 23 deletions

View File

@@ -3,6 +3,7 @@ module TypeClass
data Monad : (U -> U) -> U where data Monad : (U -> U) -> U where
MkMonad : { M : U -> U } -> MkMonad : { M : U -> U } ->
(bind : {A B : U} -> (M A) -> (A -> M B) -> M B) -> (bind : {A B : U} -> (M A) -> (A -> M B) -> M B) ->
(pure : {A : U} -> A -> M A) ->
Monad M Monad M
data Maybe : U -> U where data Maybe : U -> U where
@@ -18,21 +19,36 @@ bindEither (Left a) amb = Left a
bindEither (Right b) amb = amb b bindEither (Right b) amb = amb b
EitherMonad : {A : U} -> Monad (Either A) EitherMonad : {A : U} -> Monad (Either A)
EitherMonad = MkMonad {Either A} bindEither EitherMonad = MkMonad {Either A} bindEither Right
bindMaybe : {A B : U} -> Maybe A -> (A -> Maybe B) -> Maybe B bindMaybe : {A B : U} -> Maybe A -> (A -> Maybe B) -> Maybe B
bindMaybe Nothing amb = Nothing bindMaybe Nothing amb = Nothing
bindMaybe (Just a) amb = amb a bindMaybe (Just a) amb = amb a
MaybeMonad : Monad Maybe MaybeMonad : Monad Maybe
MaybeMonad = MkMonad bindMaybe MaybeMonad = MkMonad bindMaybe Just
_>>=_ : {a b : U} -> {m : U -> U} -> {{x : Monad m}} -> (m a) -> (a -> m b) -> m b _>>=_ : {a b : U} -> {m : U -> U} -> {{x : Monad m}} -> (m a) -> (a -> m b) -> m b
_>>=_ {a} {b} {m} {{MkMonad bind'}} ma amb = bind' {a} {b} ma amb _>>=_ {a} {b} {m} {{MkMonad bind' _}} ma amb = bind' {a} {b} ma amb
infixl 1 _>>=_ pure : {a : U} {m : U -> U} {{_ : Monad m}} -> a -> m a
pure {_} {_} {{MkMonad _ pure'}} a = pure' a
infixl 1 _>>=_ _>>_
_>>_ : {a b : U} -> {m : U -> U} -> {{x : Monad m}} -> m a -> m b -> m b
ptype Int ptype Int
test : Maybe Int
test = pure 10
foo : Int -> Maybe Int foo : Int -> Maybe Int
foo x = (Just x) >>= (\ x => Just 10) foo x = Just 42 >> Just x >>= (\ x => pure {_} {Maybe} 10)
bar : Int -> Maybe Int
bar x = do
let y = x
z <- Just x
-- This is not sorting out the Maybe...
pure {_} {_} z

View File

@@ -257,9 +257,13 @@ parameters (ctx: Context)
debug "env \{show ctx.env}" debug "env \{show ctx.env}"
debug "types \{show $ ctx.types}" debug "types \{show $ ctx.types}"
case (t',u') of case (t',u') of
-- flex/flex
(VMeta fc k sp, VMeta fc' k' sp' ) => (VMeta fc k sp, VMeta fc' k' sp' ) =>
if k == k' then unifySpine l (k == k') sp sp' if k == k' then unifySpine l (k == k') sp sp'
-- TODO, might want to try the other way, too. -- TODO, might want to try the other way, too.
else if length sp < length sp'
then solve l k' sp' (VMeta fc k sp) >> pure neutral
else solve l k sp (VMeta fc' k' sp') >> pure neutral else solve l k sp (VMeta fc' k' sp') >> pure neutral
(t, VMeta fc' i' sp') => solve l i' sp' t >> pure neutral (t, VMeta fc' i' sp') => solve l i' sp' t >> pure neutral
(VMeta fc i sp, t' ) => solve l i sp t' >> pure neutral (VMeta fc i sp, t' ) => solve l i sp t' >> pure neutral
@@ -612,7 +616,8 @@ buildCase ctx prob scnm scty (dcName, arity, ty) = do
makeConstr [] (pat :: pats) = ?extra_patterns makeConstr [] (pat :: pats) = ?extra_patterns
makeConstr ((MkBind nm Implicit x) :: xs) [] = (nm, PatWild emptyFC Implicit) :: makeConstr xs [] makeConstr ((MkBind nm Implicit x) :: xs) [] = (nm, PatWild emptyFC Implicit) :: makeConstr xs []
makeConstr ((MkBind nm Auto x) :: xs) [] = (nm, PatWild emptyFC Auto) :: makeConstr xs [] makeConstr ((MkBind nm Auto x) :: xs) [] = (nm, PatWild emptyFC Auto) :: makeConstr xs []
makeConstr ((MkBind nm Explicit x) :: xs) [] = ?extra_binders_2 -- FIXME need a proper error, but requires wiring M three levels down
makeConstr ((MkBind nm Explicit x) :: xs) [] = ?insufficient_patterns
makeConstr ((MkBind nm Explicit x) :: xs) (pat :: pats) = makeConstr ((MkBind nm Explicit x) :: xs) (pat :: pats) =
if getIcit pat == Explicit if getIcit pat == Explicit
then (nm, pat) :: makeConstr xs pats then (nm, pat) :: makeConstr xs pats
@@ -822,7 +827,18 @@ showDef : Context -> List String -> Nat -> Val -> M String
showDef ctx names n v@(VVar _ n' [<]) = if n == n' then pure "" else pure "= \{pprint names !(quote ctx.lvl v)}" showDef ctx names n v@(VVar _ n' [<]) = if n == n' then pure "" else pure "= \{pprint names !(quote ctx.lvl v)}"
showDef ctx names n v = pure "= \{pprint names !(quote ctx.lvl v)}" showDef ctx names n v = pure "= \{pprint names !(quote ctx.lvl v)}"
undo : List DoStmt -> M Raw
undo [] = error emptyFC "do block must end in expression"
undo ((DoExpr fc tm) :: Nil) = pure tm
-- TODO decide if we want to use >> or just >>=
undo ((DoExpr fc tm) :: xs) = pure $ RApp fc (RApp fc (RVar fc "_>>=_") tm Explicit) (RLam fc "_" Explicit !(undo xs)) Explicit
-- undo ((DoExpr fc tm) :: xs) = pure $ RApp fc (RApp fc (RVar fc "_>>_") tm Explicit) !(undo xs) Explicit
undo ((DoLet fc nm tm) :: xs) = RLet fc nm (RImplicit fc) tm <$> undo xs
undo ((DoArrow fc nm tm) :: xs) = pure $ RApp fc (RApp fc (RVar fc "_>>=_") tm Explicit) (RLam fc nm Explicit !(undo xs)) Explicit
check ctx tm ty = case (tm, !(forceType ty)) of check ctx tm ty = case (tm, !(forceType ty)) of
(RDo fc stmts, ty) => check ctx !(undo stmts) ty
(RCase fc rsc alts, ty) => do (RCase fc rsc alts, ty) => do
(sc, scty) <- infer ctx rsc (sc, scty) <- infer ctx rsc
scty <- forceMeta scty scty <- forceMeta scty
@@ -989,7 +1005,3 @@ infer ctx (RLit fc (LString str)) = pure (Lit fc (LString str), !(primType fc "S
infer ctx (RLit fc (LInt i)) = pure (Lit fc (LInt i), !(primType fc "Int")) infer ctx (RLit fc (LInt i)) = pure (Lit fc (LInt i), !(primType fc "Int"))
infer ctx tm = error (getFC tm) "Implement infer \{show tm}" infer ctx tm = error (getFC tm) "Implement infer \{show tm}"
-- The idea here is to insert a hole for a parse error
-- but the parser doesn't emit this yet.
-- infer ctx (RParseError str) = ?todo_insert_meta

View File

@@ -203,10 +203,28 @@ caseExpr = do
alts <- startBlock $ someSame $ caseAlt alts <- startBlock $ someSame $ caseAlt
pure $ RCase fc sc alts pure $ RCase fc sc alts
doArrow : Parser DoStmt
doArrow = do
fc <- getPos
name <- try $ ident <* keyword "<-"
expr <- term
pure $ DoArrow fc name expr
doStmt : Parser DoStmt
doStmt
= DoArrow <$> getPos <*> (try $ ident <* keyword "<-") <*> term
<|> DoLet <$> getPos <* keyword "let" <*> ident <* keyword "=" <*> term
<|> DoExpr <$> getPos <*> term
doExpr : Parser Raw
doExpr = RDo <$> getPos <* keyword "do" <*> (startBlock $ someSame doStmt)
-- This hits an idris codegen bug if parseOp is last and Lazy -- This hits an idris codegen bug if parseOp is last and Lazy
term = caseExpr term = caseExpr
<|> letExpr <|> letExpr
<|> lamExpr <|> lamExpr
<|> doExpr
<|> parseOp <|> parseOp
varname : Parser String varname : Parser String

View File

@@ -59,6 +59,12 @@ record Clause where
public export public export
data RCaseAlt = MkAlt Raw Raw data RCaseAlt = MkAlt Raw Raw
public export
data DoStmt : Type where
DoExpr : (fc : FC) -> Raw -> DoStmt
DoLet : (fc : FC) -> String -> Raw -> DoStmt
DoArrow : (fc: FC) -> String -> Raw -> DoStmt
data Raw : Type where data Raw : Type where
RVar : (fc : FC) -> (nm : Name) -> Raw RVar : (fc : FC) -> (nm : Name) -> Raw
RLam : (fc : FC) -> (nm : String) -> (icit : Icit) -> (ty : Raw) -> Raw RLam : (fc : FC) -> (nm : String) -> (icit : Icit) -> (ty : Raw) -> Raw
@@ -71,8 +77,8 @@ data Raw : Type where
RCase : (fc : FC) -> (scrut : Raw) -> (alts : List RCaseAlt) -> Raw RCase : (fc : FC) -> (scrut : Raw) -> (alts : List RCaseAlt) -> Raw
RImplicit : (fc : FC) -> Raw RImplicit : (fc : FC) -> Raw
RHole : (fc : FC) -> Raw RHole : (fc : FC) -> Raw
-- not used, but intended to allow error recovery RDo : (fc : FC) -> List DoStmt -> Raw
RParseError : (fc : FC) -> String -> Raw
%name Raw tm %name Raw tm
@@ -89,7 +95,7 @@ HasFC Raw where
getFC (RCase fc scrut alts) = fc getFC (RCase fc scrut alts) = fc
getFC (RImplicit fc) = fc getFC (RImplicit fc) = fc
getFC (RHole fc) = fc getFC (RHole fc) = fc
getFC (RParseError fc str) = fc getFC (RDo fc stmts) = fc
-- derive some stuff - I'd like json, eq, show, ... -- derive some stuff - I'd like json, eq, show, ...
@@ -181,7 +187,7 @@ Show Raw where
show (RApp _ x y z) = foo [ "App", show x, show y, show z] show (RApp _ x y z) = foo [ "App", show x, show y, show z]
show (RLam _ x i y) = foo [ "Lam", show x, show i, show y] show (RLam _ x i y) = foo [ "Lam", show x, show i, show y]
show (RCase _ x xs) = foo [ "Case", show x, show xs] show (RCase _ x xs) = foo [ "Case", show x, show xs]
show (RParseError _ str) = foo [ "ParseError", "str"] show (RDo _ stmts) = foo [ "DO", "FIXME"]
show (RU _) = "U" show (RU _) = "U"
export export
@@ -233,7 +239,7 @@ Pretty Raw where
asDoc p (RCase _ x xs) = text "TODO - RCase" asDoc p (RCase _ x xs) = text "TODO - RCase"
asDoc p (RImplicit _) = text "_" asDoc p (RImplicit _) = text "_"
asDoc p (RHole _) = text "?" asDoc p (RHole _) = text "?"
asDoc p (RParseError _ str) = text "ParseError \{str}" asDoc p (RDo _ stmts) = text "TODO - RDo"
export export
Pretty Module where Pretty Module where

View File

@@ -5,11 +5,11 @@ import Text.Lexer.Tokenizer
import Lib.Token import Lib.Token
keywords : List String keywords : List String
keywords = ["let", "in", "where", "case", "of", "data", "U", keywords = ["let", "in", "where", "case", "of", "data", "U", "do",
"ptype", "pfunc", "module", "infixl", "infixr", "infix"] "ptype", "pfunc", "module", "infixl", "infixr", "infix"]
specialOps : List String specialOps : List String
specialOps = ["->", ":", "=>", ":=", "="] specialOps = ["->", ":", "=>", ":=", "=", "<-"]
checkKW : String -> Token Kind checkKW : String -> Token Kind
checkKW s = if elem s keywords then Tok Keyword s else Tok Ident s checkKW s = if elem s keywords then Tok Keyword s else Tok Ident s

View File

@@ -3,6 +3,7 @@ module TypeClass
data Monad : (U -> U) -> U where data Monad : (U -> U) -> U where
MkMonad : { M : U -> U } -> MkMonad : { M : U -> U } ->
(bind : {A B : U} -> (M A) -> (A -> M B) -> M B) -> (bind : {A B : U} -> (M A) -> (A -> M B) -> M B) ->
(pure : {A : U} -> A -> M A) ->
Monad M Monad M
data Maybe : U -> U where data Maybe : U -> U where
@@ -18,21 +19,36 @@ bindEither (Left a) amb = Left a
bindEither (Right b) amb = amb b bindEither (Right b) amb = amb b
EitherMonad : {A : U} -> Monad (Either A) EitherMonad : {A : U} -> Monad (Either A)
EitherMonad = MkMonad {Either A} bindEither EitherMonad = MkMonad {Either A} bindEither Right
bindMaybe : {A B : U} -> Maybe A -> (A -> Maybe B) -> Maybe B bindMaybe : {A B : U} -> Maybe A -> (A -> Maybe B) -> Maybe B
bindMaybe Nothing amb = Nothing bindMaybe Nothing amb = Nothing
bindMaybe (Just a) amb = amb a bindMaybe (Just a) amb = amb a
MaybeMonad : Monad Maybe MaybeMonad : Monad Maybe
MaybeMonad = MkMonad bindMaybe MaybeMonad = MkMonad bindMaybe Just
_>>=_ : {a b : U} -> {m : U -> U} -> {{x : Monad m}} -> (m a) -> (a -> m b) -> m b _>>=_ : {a b : U} -> {m : U -> U} -> {{x : Monad m}} -> (m a) -> (a -> m b) -> m b
_>>=_ {a} {b} {m} {{MkMonad bind'}} ma amb = bind' {a} {b} ma amb _>>=_ {a} {b} {m} {{MkMonad bind' _}} ma amb = bind' {a} {b} ma amb
infixl 1 _>>=_ pure : {a : U} {m : U -> U} {{_ : Monad m}} -> a -> m a
pure {_} {_} {{MkMonad _ pure'}} a = pure' a
infixl 1 _>>=_ _>>_
_>>_ : {a b : U} -> {m : U -> U} -> {{x : Monad m}} -> m a -> m b -> m b
ptype Int ptype Int
test : Maybe Int
test = pure 10
foo : Int -> Maybe Int foo : Int -> Maybe Int
foo x = (Just x) >>= (\ x => Just 10) foo x = Just 42 >> Just x >>= (\ x => pure {_} {Maybe} 10)
bar : Int -> Maybe Int
bar x = do
let y = x
z <- Just x
-- NOW each of these implicits is a different error, fix them
pure {_} {Maybe} z