destructuring lets and arrows
This commit is contained in:
3
TODO.md
3
TODO.md
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
- [ ] Add icit to Lam (see `check` for details)
|
- [ ] Add icit to Lam (see `check` for details)
|
||||||
- [ ] TCO? Probably needed in browser, since v8 doesn't do it. bun and JavaScriptCore do support it.
|
- [ ] TCO? Probably needed in browser, since v8 doesn't do it. bun and JavaScriptCore do support it.
|
||||||
- [ ] deconstructing `let`
|
- [x] deconstructing `let` (and do arrows)
|
||||||
- [x] Fix string printing to be js instead of weird Idris strings
|
- [x] Fix string printing to be js instead of weird Idris strings
|
||||||
- [ ] make $ special
|
- [ ] make $ special
|
||||||
- Makes inference easier, cleaner output, and allows `foo $ \ x => ...`
|
- Makes inference easier, cleaner output, and allows `foo $ \ x => ...`
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
- Idris needs help with the case tree to keep code size down, do it in stages, one dcon at a time.
|
- Idris needs help with the case tree to keep code size down, do it in stages, one dcon at a time.
|
||||||
- [ ] Strategy to avoid three copies of `Prelude.newt` in this source tree
|
- [ ] Strategy to avoid three copies of `Prelude.newt` in this source tree
|
||||||
- [ ] `mapM` needs inference help when scrutinee (see Day2.newt)
|
- [ ] `mapM` needs inference help when scrutinee (see Day2.newt)
|
||||||
|
- Meta hasn't been solved yet. It's Normal, but maybe our delayed solving of Auto plays into it. Idris will peek at LHS of CaseAlts to guess the type if it doesn't have one.
|
||||||
- [ ] Can't skip an auto. We need `{{_}}` to be auto or `%search` syntax.
|
- [ ] Can't skip an auto. We need `{{_}}` to be auto or `%search` syntax.
|
||||||
- [x] add filenames to FC
|
- [x] add filenames to FC
|
||||||
- [x] maybe use backtick for javascript so we don't highlight strings as JS
|
- [x] maybe use backtick for javascript so we don't highlight strings as JS
|
||||||
|
|||||||
@@ -6,11 +6,9 @@ import Node
|
|||||||
digits1 : List Char -> List Int
|
digits1 : List Char -> List Int
|
||||||
digits1 Nil = Nil
|
digits1 Nil = Nil
|
||||||
digits1 (c :: cs) = let x = ord c in
|
digits1 (c :: cs) = let x = ord c in
|
||||||
case x < 58 of
|
if 48 < x && x < 58
|
||||||
True => case 48 < x of
|
then x - 48 :: digits1 cs
|
||||||
True => x - 48 :: digits1 cs
|
else digits1 cs
|
||||||
False => digits1 cs
|
|
||||||
False => digits1 cs
|
|
||||||
|
|
||||||
tail : {a : U} -> List a -> List a
|
tail : {a : U} -> List a -> List a
|
||||||
tail Nil = Nil
|
tail Nil = Nil
|
||||||
|
|||||||
@@ -43,43 +43,38 @@ parseDraw line =
|
|||||||
|
|
||||||
parseGame : String -> Either String Game
|
parseGame : String -> Either String Game
|
||||||
parseGame line =
|
parseGame line =
|
||||||
-- Need the Idris | sugar...
|
let (a :: b :: Nil) = split line ": "
|
||||||
case split line ": " of
|
| _ => Left $ "No colon in " ++ line in
|
||||||
-- this is splitting on the Nil instead of the a
|
let ("Game" :: ns :: Nil) = split a " "
|
||||||
(a :: b :: Nil) => case split a " " of
|
| _ => Left $ "No Game" in
|
||||||
("Game" :: ns :: Nil) =>
|
let (Right parts) = mapM {Either String} parseDraw $ split b "; "
|
||||||
let num = toInt ns in
|
| Left err => Left err in
|
||||||
case mapM {Either String} parseDraw $ split b "; " of
|
Right $ MkGame (toInt ns) parts
|
||||||
Right parts => Right $ MkGame num parts
|
|
||||||
Left err => Left err
|
|
||||||
_ => Left "No Game"
|
|
||||||
_ => Left $ "No colon in " ++ line
|
|
||||||
|
|
||||||
part1 : List Game -> Int
|
part1 : List Game -> Int
|
||||||
part1 Nil = 0
|
part1 Nil = 0
|
||||||
part1 (MkGame n parts :: rest) =
|
part1 (MkGame n parts :: rest) =
|
||||||
let total = foldl maxd (0,0,0) parts in
|
let total = foldl maxd (0,0,0) parts in
|
||||||
case lte total (12,13,14) of
|
if lte total (12,13,14)
|
||||||
True => n + part1 rest
|
then n + part1 rest
|
||||||
False => part1 rest
|
else part1 rest
|
||||||
|
|
||||||
part2 : List Game -> Int
|
part2 : List Game -> Int
|
||||||
part2 Nil = 0
|
part2 Nil = 0
|
||||||
part2 (MkGame n parts :: rest) =
|
part2 (MkGame n parts :: rest) =
|
||||||
case foldl maxd (0,0,0) parts of
|
let (a,b,c) = foldl maxd (0,0,0) parts
|
||||||
(a,b,c) => a * b * c + part2 rest
|
in a * b * c + part2 rest
|
||||||
|
|
||||||
run : String -> IO Unit
|
run : String -> IO Unit
|
||||||
run fn = do
|
run fn = do
|
||||||
putStrLn fn
|
putStrLn fn
|
||||||
text <- readFile fn
|
text <- readFile fn
|
||||||
case mapM {Either String} parseGame (split (trim text) "\n") of
|
let (Right games) = mapM {Either String} parseGame (split (trim text) "\n")
|
||||||
Left err => putStrLn $ "fail " ++ err
|
| Left err => putStrLn $ "fail " ++ err
|
||||||
Right games => do
|
putStrLn "part1"
|
||||||
putStrLn "part1"
|
printLn (part1 games)
|
||||||
printLn (part1 games)
|
putStrLn "part2"
|
||||||
putStrLn "part2"
|
printLn (part2 games)
|
||||||
printLn (part2 games)
|
|
||||||
|
|
||||||
main : IO Unit
|
main : IO Unit
|
||||||
main = do
|
main = do
|
||||||
|
|||||||
@@ -8,11 +8,9 @@ Round = List Int × List Int
|
|||||||
|
|
||||||
parseRound : String → Maybe Round
|
parseRound : String → Maybe Round
|
||||||
parseRound s =
|
parseRound s =
|
||||||
case split s ": " of
|
let (a :: b :: Nil) = split s ": " | _ => Nothing in
|
||||||
(a :: b :: Nil) => case split b " | " of
|
let (l :: r :: Nil) = split b " | " | _ => Nothing in
|
||||||
(l :: r :: Nil) => Just (nums l, nums r)
|
Just (nums l, nums r)
|
||||||
_ => Nothing
|
|
||||||
_ => Nothing
|
|
||||||
where
|
where
|
||||||
-- Nat or Int here?
|
-- Nat or Int here?
|
||||||
nums : String → List Int
|
nums : String → List Int
|
||||||
@@ -50,14 +48,12 @@ run : String -> IO Unit
|
|||||||
run fn = do
|
run fn = do
|
||||||
putStrLn fn
|
putStrLn fn
|
||||||
text <- readFile fn
|
text <- readFile fn
|
||||||
|
let (Just cards) = parse text
|
||||||
case parse text of
|
| _ => putStrLn "fail"
|
||||||
Nothing => putStrLn "fail"
|
putStrLn "part1"
|
||||||
Just cards => do
|
printLn (part1 cards)
|
||||||
putStrLn "part1"
|
putStrLn "part2"
|
||||||
printLn (part1 cards)
|
printLn (part2 cards)
|
||||||
putStrLn "part2"
|
|
||||||
printLn (part2 cards)
|
|
||||||
|
|
||||||
-- 13/30
|
-- 13/30
|
||||||
-- 25004/14427616
|
-- 25004/14427616
|
||||||
|
|||||||
@@ -33,14 +33,14 @@ parseFile : String → Either String Problem
|
|||||||
parseFile content = do
|
parseFile content = do
|
||||||
let parts = split (trim content) "\n\n"
|
let parts = split (trim content) "\n\n"
|
||||||
-- TODO deconstructing let
|
-- TODO deconstructing let
|
||||||
case parts of
|
let (first :: rest) = parts
|
||||||
(first :: rest) => case split first ": " of
|
| _ => Left "expected some parts"
|
||||||
(_ :: x :: Nil) => do
|
let (_ :: x :: Nil) = split first ": "
|
||||||
let seeds = nums x
|
| _ => Left $ "expected ': ' in " ++ first
|
||||||
maps <- mapA (λ part => parseMap (split part "\n")) rest
|
|
||||||
Right $ MkProb seeds maps
|
let seeds = nums x
|
||||||
_ => Left $ "expected ': ' in " ++ first
|
maps <- mapA (λ part => parseMap (split part "\n")) rest
|
||||||
_ => Left $ "expected some parts"
|
Right $ MkProb seeds maps
|
||||||
|
|
||||||
applyEntry : Int → MapEntry → Int
|
applyEntry : Int → MapEntry → Int
|
||||||
applyEntry n (MkEntry dest src len) =
|
applyEntry n (MkEntry dest src len) =
|
||||||
@@ -96,26 +96,23 @@ mkRanges Nil = Just Nil
|
|||||||
mkRanges _ = Nothing
|
mkRanges _ = Nothing
|
||||||
|
|
||||||
part2 : Problem → IO Unit
|
part2 : Problem → IO Unit
|
||||||
part2 (MkProb seeds maps) =
|
part2 (MkProb seeds maps) = do
|
||||||
case mkRanges seeds of
|
let (Just ranges) = mkRanges seeds
|
||||||
Nothing => printLn "odd seeds!"
|
| Nothing => printLn "odd seeds!"
|
||||||
Just ranges => do
|
let results = foldl apply ranges maps
|
||||||
let results = foldl apply ranges maps
|
-- putStrLn $ debugStr results
|
||||||
-- putStrLn $ debugStr results
|
let answer = foldl min 99999999 $ map fst results
|
||||||
let answer = foldl min 99999999 $ map fst results
|
putStrLn $ "part2 " ++ show answer
|
||||||
putStrLn $ "part2 " ++ show answer
|
|
||||||
|
|
||||||
run : String -> IO Unit
|
run : String -> IO Unit
|
||||||
run fn = do
|
run fn = do
|
||||||
putStrLn fn
|
putStrLn fn
|
||||||
text <- readFile fn
|
text <- readFile fn
|
||||||
case parseFile text of
|
let (Right prob) = parseFile text
|
||||||
Left err => putStrLn err
|
| Left err => putStrLn err
|
||||||
Right prob => do
|
putStrLn $ debugStr prob
|
||||||
putStrLn $ debugStr prob
|
part1 prob
|
||||||
part1 prob
|
part2 prob
|
||||||
-- putStrLn "part2"
|
|
||||||
part2 prob
|
|
||||||
|
|
||||||
-- 35 / 46
|
-- 35 / 46
|
||||||
-- 282277027 / 11554135
|
-- 282277027 / 11554135
|
||||||
|
|||||||
@@ -901,7 +901,18 @@ undo ((DoExpr fc tm) :: Nil) = pure tm
|
|||||||
undo ((DoExpr fc tm) :: xs) = pure $ RApp fc (RApp fc (RVar fc "_>>=_") tm Explicit) (RLam fc (BI fc "_" Explicit Many) !(undo xs)) Explicit
|
undo ((DoExpr fc tm) :: xs) = pure $ RApp fc (RApp fc (RVar fc "_>>=_") tm Explicit) (RLam fc (BI fc "_" Explicit Many) !(undo xs)) Explicit
|
||||||
-- undo ((DoExpr fc tm) :: xs) = pure $ RApp fc (RApp fc (RVar fc "_>>_") tm 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 ((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 (BI fc nm Explicit Many) !(undo xs)) Explicit
|
undo ((DoArrow fc (RVar fc' nm) right []) :: xs) =
|
||||||
|
case lookup nm !get of
|
||||||
|
Just _ => ?todo
|
||||||
|
Nothing =>
|
||||||
|
pure $ RApp fc (RApp fc (RVar fc "_>>=_") right Explicit)
|
||||||
|
(RLam fc (BI fc' nm Explicit Many) !(undo xs)) Explicit
|
||||||
|
|
||||||
|
undo ((DoArrow fc left right alts) :: xs) = do
|
||||||
|
let nm = "$sc"
|
||||||
|
rest <- pure $ RCase fc (RVar fc nm) (MkAlt left !(undo xs) :: alts)
|
||||||
|
pure $ RApp fc (RApp fc (RVar fc "_>>=_") right Explicit)
|
||||||
|
(RLam fc (BI fc nm Explicit Many) rest) Explicit
|
||||||
|
|
||||||
check ctx tm ty = case (tm, !(forceType ctx.env ty)) of
|
check ctx tm ty = case (tm, !(forceType ctx.env ty)) of
|
||||||
(RWhere fc decls body, ty) => checkWhere ctx (collectDecl decls) body ty
|
(RWhere fc decls body, ty) => checkWhere ctx (collectDecl decls) body ty
|
||||||
|
|||||||
@@ -154,6 +154,9 @@ parseOp = do
|
|||||||
| _ => fail "extra stuff"
|
| _ => fail "extra stuff"
|
||||||
pure res
|
pure res
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export
|
export
|
||||||
letExpr : Parser Raw
|
letExpr : Parser Raw
|
||||||
letExpr = do
|
letExpr = do
|
||||||
@@ -232,13 +235,54 @@ caseExpr = do
|
|||||||
alts <- startBlock $ someSame $ caseAlt
|
alts <- startBlock $ someSame $ caseAlt
|
||||||
pure $ RCase fc sc alts
|
pure $ RCase fc sc alts
|
||||||
|
|
||||||
doStmt : Parser DoStmt
|
|
||||||
doStmt
|
|
||||||
= DoArrow <$> getPos <*> (try $ ident <* keyword "<-") <*> term
|
|
||||||
<|> DoLet <$> getPos <* keyword "let" <*> ident <* keyword "=" <*> term
|
|
||||||
<|> DoExpr <$> getPos <*> term
|
|
||||||
|
|
||||||
doExpr : Parser Raw
|
doExpr : Parser Raw
|
||||||
|
doStmt : Parser DoStmt
|
||||||
|
|
||||||
|
caseLet : Parser Raw
|
||||||
|
caseLet = do
|
||||||
|
-- look ahead so we can fall back to normal let
|
||||||
|
fc <- getPos
|
||||||
|
try (keyword "let" >> sym "(")
|
||||||
|
pat <- typeExpr
|
||||||
|
sym ")"
|
||||||
|
keyword "="
|
||||||
|
sc <- typeExpr
|
||||||
|
alts <- startBlock $ manySame $ sym "|" *> caseAlt
|
||||||
|
keyword "in"
|
||||||
|
body <- term
|
||||||
|
pure $ RCase fc sc (MkAlt pat body :: alts)
|
||||||
|
|
||||||
|
doCaseLet : Parser DoStmt
|
||||||
|
doCaseLet = do
|
||||||
|
-- look ahead so we can fall back to normal let
|
||||||
|
-- Maybe make it work like arrow?
|
||||||
|
fc <- getPos
|
||||||
|
try (keyword "let" >> sym "(")
|
||||||
|
pat <- typeExpr
|
||||||
|
sym ")"
|
||||||
|
keyword "="
|
||||||
|
-- arrow <- (False <$ keyword "=" <|> True <$ keyword "<-")
|
||||||
|
sc <- typeExpr
|
||||||
|
alts <- startBlock $ manySame $ sym "|" *> caseAlt
|
||||||
|
bodyFC <- getPos
|
||||||
|
body <- RDo <$> getPos <*> someSame doStmt
|
||||||
|
pure $ DoExpr fc (RCase fc sc (MkAlt pat body :: alts))
|
||||||
|
|
||||||
|
doArrow : Parser DoStmt
|
||||||
|
doArrow = do
|
||||||
|
fc <- getPos
|
||||||
|
left <- typeExpr
|
||||||
|
Just _ <- optional $ keyword "<-"
|
||||||
|
| _ => pure $ DoExpr fc left
|
||||||
|
right <- term
|
||||||
|
alts <- startBlock $ manySame $ sym "|" *> caseAlt
|
||||||
|
pure $ DoArrow fc left right alts
|
||||||
|
|
||||||
|
doStmt
|
||||||
|
= doCaseLet
|
||||||
|
<|> DoLet <$> getPos <* keyword "let" <*> ident <* keyword "=" <*> term
|
||||||
|
<|> doArrow
|
||||||
|
|
||||||
doExpr = RDo <$> getPos <* keyword "do" <*> (startBlock $ someSame doStmt)
|
doExpr = RDo <$> getPos <* keyword "do" <*> (startBlock $ someSame doStmt)
|
||||||
|
|
||||||
ifThenElse : Parser Raw
|
ifThenElse : Parser Raw
|
||||||
@@ -254,6 +298,7 @@ ifThenElse = do
|
|||||||
|
|
||||||
-- 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
|
||||||
|
<|> caseLet
|
||||||
<|> letExpr
|
<|> letExpr
|
||||||
<|> lamExpr
|
<|> lamExpr
|
||||||
<|> doExpr
|
<|> doExpr
|
||||||
|
|||||||
@@ -60,8 +60,7 @@ public export
|
|||||||
data DoStmt : Type where
|
data DoStmt : Type where
|
||||||
DoExpr : (fc : FC) -> Raw -> DoStmt
|
DoExpr : (fc : FC) -> Raw -> DoStmt
|
||||||
DoLet : (fc : FC) -> String -> Raw -> DoStmt
|
DoLet : (fc : FC) -> String -> Raw -> DoStmt
|
||||||
DoArrow : (fc: FC) -> String -> Raw -> DoStmt
|
DoArrow : (fc: FC) -> Raw -> Raw -> List RCaseAlt -> DoStmt
|
||||||
|
|
||||||
|
|
||||||
data Decl : Type
|
data Decl : Type
|
||||||
data Raw : Type where
|
data Raw : Type where
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ keywords = ["let", "in", "where", "case", "of", "data", "U", "do",
|
|||||||
"∀", "forall",
|
"∀", "forall",
|
||||||
"class", "instance",
|
"class", "instance",
|
||||||
"if", "then", "else",
|
"if", "then", "else",
|
||||||
"->", "→", ":", "=>", ":=", "=", "<-", "\\", "_"]
|
"->", "→", ":", "=>", ":=", "=", "<-", "\\", "_", "|"]
|
||||||
|
|
||||||
checkKW : String -> Token Kind
|
checkKW : String -> Token Kind
|
||||||
checkKW s =
|
checkKW s =
|
||||||
|
|||||||
Reference in New Issue
Block a user