Skip to content

Commit

Permalink
Mutual Recursion, Ready to do termination check
Browse files Browse the repository at this point in the history
  • Loading branch information
KonjacSource committed Oct 5, 2024
1 parent 0992597 commit 4059719
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 8 deletions.
16 changes: 16 additions & 0 deletions Draft.shitt
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,19 @@ data Void : U where

fun nomatchTest (n : N) (_: Id (succ (succ n)) (succ n)) : N where
| n k !@ k


mutual
fun even (_ : N) : Bool
fun odd (_ : N) : Bool
begin

fun even
| zero = true
| (succ n) = odd n

fun odd
| zero = false
| (succ n) = even n

end
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ ghci> run "Eaxmple.shitt"
- [x] [Syntax Highlight](https://github.com/KonjacSource/shitt-highlight)
- [x] REPL
- [x] Module system (very naive)
- [x] Mutual recursion

## TODO

Expand All @@ -45,7 +46,7 @@ ghci> run "Eaxmple.shitt"
- [ ] IO
- [ ] Code generator
- [ ] Type classes
- [ ] Mutual recursion
- [ ] Better Module system

## Use REPL

Expand Down Expand Up @@ -175,6 +176,27 @@ fun invf {A B : U} (f : A -> B) (y : B) (_ : Imf f y) : A where

Here `y` is restricted by `imf x`.

### Mutual Recursion

Only mutual functions for now. The syntax is pretty Pascal style.

```haskell
mutual
fun even (_ : N) : Bool
fun odd (_ : N) : Bool
begin

fun even
| zero = true
| (succ n) = odd n

fun odd
| zero = false
| (succ n) = even n

end
```

### ~~HIT~~

```haskell
Expand Down
2 changes: 1 addition & 1 deletion WithoutKTest.shitt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fun K {A : U} {a : A} (P : Id a a -> U) (p : P (refl _)) (e : Id a a) : P e wher

-- OK
fun J {A : U} {a : A} (P : (b : A) -> Id a b -> U) (p : P a (refl _)) (b : A) (e : Id a b) : P b e
| P p a (refl _) = p
| P p b (refl _) = p

-- not OK
fun K1 {A : U} {a : A} (P : Id a a -> U) (p : P (refl _)) (e : Id a a) : P e where
Expand Down
1 change: 0 additions & 1 deletion src/ShiTT/CheckFunction.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import Control.Monad (forM, when, join, guard)
import Data.Maybe (fromJust, isJust, isNothing)
import ShiTT.Meta
import Data.IORef (readIORef)
import Data.Foldable (forM_)
import Debug.Trace (trace)
import Control.Applicative (Alternative(empty))
import Data.List (nub)
Expand Down
46 changes: 41 additions & 5 deletions src/ShiTT/Parser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ keywords = [ "U", "let", "in", "fun", "λ"
, "data", "where", "def", "fun"
, "nomatch", "auto", "traceContext"
, "inductive", "higher", "when"
, "unmatchable", "axiom" ]
, "unmatchable", "axiom", "mutual", "begin", "end" ]

pIdent :: Parser Name
pIdent = do
Expand Down Expand Up @@ -559,11 +559,10 @@ putLn = liftIO . putStrLn
checkFunction :: Parser ()
checkFunction = do
isAxiom <- (symbol "axiom" >> pure True) <|> pure False
let checker = checkFun
fun <- pFun
ctx <- getCtx
pos <- getSourcePos
checked_fun <- liftIO $ checker ctx (not isAxiom) fun
checked_fun <- liftIO $ checkFun ctx (not isAxiom) fun
`catch` \e -> putStrLn ("In function " ++ fun.funName ++ ":" ++ sourcePosPretty pos) >> case e of
PMErr pm -> error (show pm)
UnifyE u v -> error ("(PatternMatch) Can't unify " ++ show u ++ " with " ++ show v)
Expand All @@ -572,11 +571,48 @@ checkFunction = do
ConflictName n -> error $ "Don't use the name: " ++ n
addFun checked_fun

pMutualBody :: [D.Fun] -> Parser ()
pMutualBody [] = pure ()
pMutualBody header = do
fun_name <- symbol "fun" >> pIdent
let lookup :: [D.Fun] -> [D.Fun] -> Maybe (D.Fun, [D.Fun])
lookup _ [] = Nothing
lookup fore (f:fs)
| f.funName == fun_name = Just (f, fore ++ fs)
| otherwise = lookup (fore ++ [f]) fs
case lookup [] header of
Nothing -> error $ "The funcion " ++ fun_name ++ " should not define in mutual block."
Just (fun_header, rest_headers) -> do

clauses <- many (pClause (D.funPara fun_header))
let raw_fun = fun_header { D.clauses = clauses }
ctx <- getCtx
pos <- getSourcePos
checked_fun <- liftIO $ checkFun ctx True raw_fun
`catch` \e -> putStrLn ("In function " ++ raw_fun.funName ++ ":" ++ sourcePosPretty pos) >> case e of
PMErr pm -> error (show pm)
UnifyE u v -> error ("(PatternMatch) Can't unify " ++ show u ++ " with " ++ show v)
UsedK -> error "Are you using K?"
BoundaryMismatch fun_name sp -> error "Boundary Mismatch."
ConflictName n -> error $ "Don't use the name: " ++ n
addFun checked_fun
pMutualBody rest_headers

pMutual :: Parser ()
pMutual = undefined
pMutual = do
raw_headers <- symbol "mutual" >> many pFunHeader <* symbol "begin"
let mkFun fun = Fun
{ funName = fun.funName
, funPara = fun.funPara
, funRetType = fun.funRetType
, funClauses = Nothing
}
let headers = mkFun <$> raw_headers
mapM_ addFun headers
pMutualBody raw_headers <* symbol "end"

pTopLevel :: Parser ()
pTopLevel = choice [data_type, checkFunction, command] where
pTopLevel = choice [data_type, checkFunction, pMutual, command] where

data_type = do
dat <- pData
Expand Down

0 comments on commit 4059719

Please sign in to comment.