on master help sign in
Added nested record access syntax

record { a->b->c } x is equivalent to c (b (a x)) It's longer, but symmetric wrt the update syntax. Also added a test.

commit9aa90bec74bea8abf60d0f54e43f4a50aa33df84 authorEdwin Brady <ecb10@st-andrews.ac.uk> dateFri 2 May 2014, 08:58 (12 years ago) parent1df6fa9
5 files changed+100−14
idris.cabal+3 src/Idris/ParseExpr.hs+39−14 test/records003/expected+6 test/records003/records003.idr+48 test/records003/run+4
idris.cabal+3
@@ -410,6 +410,9 @@ Extra-source-files:
410410 test/records002/run
411411 test/records002/*.idr
412412 test/records002/expected
413+ test/records003/run
414+ test/records003/*.idr
415+ test/records003/expected
413416
414417 test/sugar001/run
415418 test/sugar001/*.idr
src/Idris/ParseExpr.hs+39−14
@@ -605,25 +605,45 @@ FieldType ::=
605605@
606606-}
607607recordType :: SyntaxInfo -> IdrisParser PTerm
608−recordType syn
609− = do reserved "record"
608+recordType syn =
609+ do reserved "record"
610610 lchar '{'
611− fields <- sepBy1 fieldType (lchar ',')
611+ fgs <- fieldGetOrSet
612612 lchar '}'
613613 fc <- getFC
614614 rec <- optional (simpleExpr syn)
615− case rec of
616− Nothing ->
617− return (PLam (sMN 0 "fldx") Placeholder
618− (applyAll fc fields (PRef fc (sMN 0 "fldx"))))
619− Just v -> return (applyAll fc fields v)
615+ case fgs of
616+ Left fields ->
617+ case rec of
618+ Nothing ->
619+ return (PLam (sMN 0 "fldx") Placeholder
620+ (applyAll fc fields (PRef fc (sMN 0 "fldx"))))
621+ Just v -> return (applyAll fc fields v)
622+ Right fields ->
623+ case rec of
624+ Nothing ->
625+ return (PLam (sMN 0 "fldx") Placeholder
626+ (getAll fc (reverse fields)
627+ (PRef fc (sMN 0 "fldx"))))
628+ Just v -> return (getAll fc (reverse fields) v)
629+
620630 <?> "record setting expression"
621− where fieldType :: IdrisParser ([Name], PTerm)
622− fieldType = do n <- sepBy1 fnName (symbol "->")
623− lchar '='
624− e <- expr syn
625− return (n, e)
626− <?> "field setter"
631+ where fieldSet :: IdrisParser ([Name], PTerm)
632+ fieldSet = do ns <- fieldGet
633+ lchar '='
634+ e <- expr syn
635+ return (ns, e)
636+ <?> "field setter"
637+
638+ fieldGet :: IdrisParser [Name]
639+ fieldGet = sepBy1 fnName (symbol "->")
640+
641+ fieldGetOrSet :: IdrisParser (Either [([Name], PTerm)] [Name])
642+ fieldGetOrSet = try (do fs <- sepBy1 fieldSet (lchar ',')
643+ return (Left fs))
644+ <|> do f <- fieldGet
645+ return (Right f)
646+
627647 applyAll :: FC -> [([Name], PTerm)] -> PTerm -> PTerm
628648 applyAll fc [] x = x
629649 applyAll fc ((ns, e) : es) x
@@ -636,6 +656,11 @@ recordType syn
636656 [pexp (doUpdate fc ns e (PApp fc (PRef fc n) [pexp get])),
637657 pexp get]
638658
659+ getAll :: FC -> [Name] -> PTerm -> PTerm
660+ getAll fc [n] e = PApp fc (PRef fc n) [pexp e]
661+ getAll fc (n:ns) e = PApp fc (PRef fc n) [pexp (getAll fc ns e)]
662+
663+
639664-- | Creates setters for record types on necessary functions
640665mkType :: Name -> Name
641666mkType (UN n) = sUN ("set_" ++ str n)
test/records003/expectednew file+6
@@ -0,0 +1,6 @@
1+"Fred"
2+21
3+20
4+30
5+29
6+2014
test/records003/records003.idrnew file+48
@@ -0,0 +1,48 @@
1+record Person : Nat -> Type where
2+ MkPerson : (name : String) ->
3+ (age : Nat) ->
4+ Person age
5+
6+record Event : Type where
7+ MkEvent : (name : String) -> (organiser : Person a) -> Event
8+
9+record Meeting : Int -> Type where
10+ MkMeeting : (event : Event) ->
11+ (organiser : Person a) ->
12+ (year : Int) ->
13+ Meeting year
14+
15+new_organiser : String -> List (Meeting x) -> List (Meeting x)
16+new_organiser n = map (record { event->organiser->name = n })
17+
18+next_year : Meeting x -> Meeting (x+1)
19+next_year m = record { organiser->age
20+ = record { organiser->age } m + 1,
21+ event->organiser->age
22+ = record { event->organiser->age } m + 1,
23+ year = _ } m
24+
25+fred : Person 20
26+fred = MkPerson "Fred" _
27+
28+jim : Person 29
29+jim = MkPerson "Jim" 29
30+
31+idm : Event
32+idm = MkEvent "Idris Developers Meeting" fred
33+
34+idm_gbg : Meeting 2014
35+idm_gbg = MkMeeting idm jim _
36+
37+test : Meeting 2015
38+test = next_year idm_gbg
39+
40+main : IO ()
41+main = do print (record { event->organiser->name } test)
42+ print (record { event->organiser->age } test)
43+ print (record { event->organiser->age } idm_gbg)
44+ print (record { organiser->age } test)
45+ print (record { organiser->age } idm_gbg)
46+ print (record { year } idm_gbg)
47+
48+
test/records003/runnew file+4
@@ -0,0 +1,4 @@
1+#!/usr/bin/env bash
2+idris $@ records003.idr -o records003
3+./records003
4+rm -f records003 *.ibc