Skip to content

Commit cc479aa

Browse files
authored
Add pattern matching for character literals (#322)
* Added pattern matching for character literals, plus a few tests for character literal patterns in function definitions and case statements * Fixed CBV pattern-matching for characters
1 parent cc3a6f4 commit cc479aa

16 files changed

Lines changed: 93 additions & 3 deletions

File tree

compiler/src/Language/Granule/Compiler/HSCodegen.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ cgPat (GrPat.PInt _ _ _ n) =
104104
return $ PLit () (Signless ()) $ Int () (fromIntegral n) (show n)
105105
cgPat (GrPat.PFloat _ _ _ n) =
106106
return $ PLit () (Signless ()) $ Frac () (toRational n) (show n)
107+
cgPat (GrPat.PChar _ _ _ ch) =
108+
return $ PLit () (Signless ()) $ Char () ch (show ch)
107109
cgPat (GrPat.PConstr _ _ _ i _ l_pt)
108110
| i == Id "," "," = do
109111
pts <- mapM cgPat l_pt

frontend/src/Language/Granule/Checker/Patterns.hs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,13 @@ ctxtFromTypedPattern' outerCoeff s pos ty@(TyCon c) (PFloat s' _ rf n) _
162162
let elabP = PFloat s' ty rf n
163163
return ([], [], [], elabP, Full)
164164

165+
ctxtFromTypedPattern' outerCoeff s pos ty@(TyCon c) (PChar s' _ rf ch) _
166+
| internalName c == "Char" = do
167+
definiteUnification s pos outerCoeff ty
168+
169+
let elabP = PChar s' ty rf ch
170+
return ([], [], [], elabP, Full)
171+
165172
-- Pattern match on a modal box
166173
ctxtFromTypedPattern' outerCoeffAndTy s pos t@(Box coeff ty) (PBox sp _ rf p) _ = do
167174
(innerCoeffTy, subst0, _) <- synthKind s coeff
@@ -476,4 +483,5 @@ duplicateBinderCheck s ps = case duplicateBinders of
476483
(\_ _ _ bs -> bs)
477484
(\_ _ _ _ -> [])
478485
(\_ _ _ _ -> [])
486+
(\_ _ _ _ -> [])
479487
(\_ _ _ _ _ bss -> concat bss)

frontend/src/Language/Granule/Checker/Substitution.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,9 @@ instance Substitutable a => Substitutable (Pattern a) where
433433
(\sp ann rf doub -> do
434434
ann' <- substitute ctxt ann
435435
return $ PFloat sp ann' rf doub)
436+
(\sp ann rf char -> do
437+
ann' <- substitute ctxt ann
438+
return $ PChar sp ann' rf char)
436439
(\sp ann rf nm tyVarBindsRequested pats -> do
437440
ann' <- substitute ctxt ann
438441
return $ PConstr sp ann' rf nm tyVarBindsRequested pats)

frontend/src/Language/Granule/Syntax/Parser.y

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,9 @@ PAtom :: { Pattern () }
310310
| FLOAT
311311
{% (mkSpan $ getPosToSpan $1) >>= \sp -> return $ let TokenFloat _ x = $1 in PFloat sp () False $ read x }
312312
313+
| CHAR
314+
{% (mkSpan $ getPosToSpan $1) >>= \sp -> return $ let TokenCharLiteral _ x = $1 in PChar sp () False x }
315+
313316
| CONSTR
314317
{% (mkSpan $ getPosToSpan $1) >>= \sp -> return $ let TokenConstr _ x = $1 in PConstr sp () False (mkId x) [] [] }
315318

frontend/src/Language/Granule/Syntax/Pattern.hs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ data Pattern a
2626
| PWild Span a Bool -- ^ Wildcard (underscore) pattern
2727
| PBox Span a Bool (Pattern a) -- ^ Box patterns
2828
| PInt Span a Bool Int -- ^ Numeric patterns
29+
| PChar Span a Bool Char
2930
| PFloat Span a Bool Double -- ^ Float pattern
3031
| PConstr Span a Bool Id [Id] [Pattern a] -- ^ Constructor pattern
3132
deriving (Eq, Show, Generic, Functor, Typeable, Data)
@@ -50,17 +51,19 @@ patternFold
5051
-> (Span -> ann -> Bool -> b -> b)
5152
-> (Span -> ann -> Bool -> Int -> b)
5253
-> (Span -> ann -> Bool -> Double -> b)
54+
-> (Span -> ann -> Bool -> Char -> b)
5355
-> (Span -> ann -> Bool -> Id -> [Id] -> [b] -> b)
5456
-> Pattern ann
5557
-> b
56-
patternFold v w b i f c = go
58+
patternFold v w b i f ch c = go
5759
where
5860
go = \case
5961
PVar sp ann rf nm -> v sp ann rf nm
6062
PWild sp ann rf -> w sp ann rf
6163
PBox sp ann rf pat -> b sp ann rf (go pat)
6264
PInt sp ann rf int -> i sp ann rf int
6365
PFloat sp ann rf doub -> f sp ann rf doub
66+
PChar sp ann rf char -> ch sp ann rf char
6467
PConstr sp ann rf nm tyVarBindsRequested pats -> c sp ann rf nm tyVarBindsRequested (go <$> pats)
6568

6669
patternFoldM
@@ -70,10 +73,11 @@ patternFoldM
7073
-> (Span -> ann -> Bool -> b -> m b)
7174
-> (Span -> ann -> Bool -> Int -> m b)
7275
-> (Span -> ann -> Bool -> Double -> m b)
76+
-> (Span -> ann -> Bool -> Char -> m b)
7377
-> (Span -> ann -> Bool -> Id -> [Id] -> [b] -> m b)
7478
-> Pattern ann
7579
-> m b
76-
patternFoldM v w b i f c = go
80+
patternFoldM v w b i f ch c = go
7781
where
7882
go = \case
7983
PVar sp ann rf nm -> v sp ann rf nm
@@ -84,6 +88,7 @@ patternFoldM v w b i f c = go
8488
b sp ann rf pat'
8589
PInt sp ann rf int -> i sp ann rf int
8690
PFloat sp ann rf doub -> f sp ann rf doub
91+
PChar sp ann rf char -> ch sp ann rf char
8792
PConstr sp ann rf nm tyVarBindsRequested pats ->
8893
do
8994
pats' <- mapM go pats
@@ -96,16 +101,18 @@ boundVars PWild {} = []
96101
boundVars (PBox _ _ _ p) = boundVars p
97102
boundVars PInt {} = []
98103
boundVars PFloat {} = []
104+
boundVars PChar {} = []
99105
boundVars (PConstr _ _ _ _ _ ps) = concatMap boundVars ps
100106

101107
boundVarsAndAnnotations :: Pattern a -> [(a, Id)]
102108
boundVarsAndAnnotations =
103-
patternFold var wild box int flt cstr
109+
patternFold var wild box int flt char cstr
104110
where var _ ty _ ident = [(ty, ident)]
105111
wild _ _ _ = []
106112
box _ _ _ pat = pat
107113
int _ _ _ _ = []
108114
flt _ _ _ _ = []
115+
char _ _ _ _ = []
109116
cstr _ _ _ _ _ = concat
110117

111118
ppair :: Span
@@ -138,13 +145,15 @@ instance Freshenable m (Pattern a) where
138145
freshen p@PWild {} = return p
139146
freshen p@PInt {} = return p
140147
freshen p@PFloat {} = return p
148+
freshen p@PChar {} = return p
141149

142150
patRefactored :: Pattern a -> Bool
143151
patRefactored (PVar _ _ rf _) = rf
144152
patRefactored (PWild _ _ rf) = rf
145153
patRefactored (PBox _ _ rf _) = rf
146154
patRefactored (PInt _ _ rf _) = rf
147155
patRefactored (PFloat _ _ rf _) = rf
156+
patRefactored (PChar _ _ rf _) = rf
148157
patRefactored (PConstr _ _ rf _ _ _) = rf
149158

150159
instance Rp.Refactorable (Pattern a) where

frontend/src/Language/Granule/Syntax/Pretty.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ instance Pretty (Pattern a) where
346346
wlpretty (PBox _ _ _ p) = P.brackets $ prettyNestedNew p
347347
wlpretty (PInt _ _ _ n) = P.pretty (show n)
348348
wlpretty (PFloat _ _ _ n) = P.pretty (show n)
349+
wlpretty (PChar _ _ _ n) = P.pretty (show n)
349350
wlpretty (PConstr _ _ _ name _ args) | internalName name == "," = P.parens $ mconcat $ P.punctuate ", " (map prettyNestedNew args)
350351
wlpretty (PConstr _ _ _ name tyVarBindsRequested args) =
351352
P.sep (wlpretty name : (map tyvarbinds tyVarBindsRequested ++ map prettyNestedNew args))

frontend/src/Language/Granule/Synthesis/LinearHaskell.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,7 @@ patternToHaskell (GrPat.PWild{}) = PWildCard noSrcSpan
569569
patternToHaskell (GrPat.PBox _ _ _ pt) = patternToHaskell pt
570570
patternToHaskell (GrPat.PInt _ _ _ n) = PLit noSrcSpan (Signless noSrcSpan) $ Int noSrcSpan (fromIntegral n) (show n)
571571
patternToHaskell (GrPat.PFloat _ _ _ n) = PLit noSrcSpan (Signless noSrcSpan) $ Frac noSrcSpan (toRational n) (show n)
572+
patternToHaskell (GrPat.PChar _ _ _ ch) = PLit noSrcSpan (Signless noSrcSpan) $ Char noSrcSpan ch (show ch)
572573
patternToHaskell (GrPat.PConstr _ _ _ id@(GrId.Id _ i) _ l_pt)
573574
| ',' `elem` i = PTuple noSrcSpan Boxed $ map patternToHaskell (reverse l_pt)
574575
| otherwise = PApp noSrcSpan (UnQual noSrcSpan $ idToHaskell id) $ map patternToHaskell (reverse l_pt)

frontend/src/Language/Granule/Synthesis/Refactor.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ refactorPattern (PBox sp a b p) id' subpat =
9696
in PBox sp a (patRefactored p') p'
9797
refactorPattern p@PInt {} _ _ = p
9898
refactorPattern p@PFloat {} _ _ = p
99+
refactorPattern p@PChar {} _ _ = p
99100
refactorPattern (PConstr sp a _ id names ps) id' subpat =
100101
let ps' = map (\p -> refactorPattern p id' subpat) ps
101102
in PConstr sp a (any patRefactored ps') id names ps'

frontend/src/Language/Granule/Synthesis/Synth.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ synthesiseLinearBase hints index unrComps rComps defId ctxt constructors goalTy
341341
unannotatePat (PBox s a rf p) = PBox s () rf $ unannotatePat p
342342
unannotatePat (PInt s a rf int) = PInt s () rf int
343343
unannotatePat (PFloat s a rf doub) = PFloat s () rf doub
344+
unannotatePat (PChar s a rf ch) = PChar s () rf ch
344345
unannotatePat (PConstr s a rf nm names pats) = PConstr s () rf nm names $ map unannotatePat pats
345346

346347

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import Bool
2+
-- Small example of case expressions in Granule
3+
constId : Int → Int
4+
constId x = case 'a' of 'a' → x
5+
6+
constId2 : Int → Int
7+
constId2 x =
8+
case '\n' of
9+
'\n' → x;
10+
'\t' → x
11+
12+
main : Int
13+
main = constId 10 + constId2 20

0 commit comments

Comments
 (0)