1
1
mirror of https://github.com/anoma/juvix.git synced 2024-12-01 00:04:58 +03:00

Curly braces are allowed nested in patterns (#1380)

This commit is contained in:
janmasrovira 2022-07-20 11:33:52 +03:00 committed by GitHub
parent 30ae6c76c4
commit a8f4acaca2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 354 additions and 197 deletions

View File

@ -60,7 +60,7 @@ data FunctionDef = FunctionDef
data FunctionClause = FunctionClause
{ _clauseName :: FunctionName,
_clausePatterns :: [Pattern],
_clausePatterns :: [PatternArg],
_clauseBody :: Expression
}
deriving stock (Eq, Show)
@ -152,7 +152,13 @@ instance HasAtomicity Function where
-- | Fully applied constructor in a pattern.
data ConstructorApp = ConstructorApp
{ _constrAppConstructor :: ConstructorRef,
_constrAppParameters :: [Pattern]
_constrAppParameters :: [PatternArg]
}
deriving stock (Eq, Show)
data PatternArg = PatternArg
{ _patternArgIsImplicit :: IsImplicit,
_patternArgPattern :: Pattern
}
deriving stock (Eq, Show)
@ -161,7 +167,6 @@ data Pattern
| PatternConstructorApp ConstructorApp
| PatternWildcard Wildcard
| PatternEmpty
| PatternBraces Pattern
deriving stock (Eq, Show)
data InductiveDef = InductiveDef
@ -187,6 +192,7 @@ data AxiomDef = AxiomDef
deriving stock (Eq, Show)
makeLenses ''Module
makeLenses ''PatternArg
makeLenses ''FunctionParameter
makeLenses ''Function
makeLenses ''FunctionDef

View File

@ -17,16 +17,18 @@ data ApplicationArg = ApplicationArg
makeLenses ''ApplicationArg
patternVariables :: Pattern -> [VarName]
patternVariables = \case
PatternVariable v -> [v]
PatternWildcard {} -> []
PatternEmpty {} -> []
PatternBraces b -> patternVariables b
PatternConstructorApp app -> appVariables app
patternVariables :: Traversal' Pattern VarName
patternVariables f p = case p of
PatternVariable v -> PatternVariable <$> f v
PatternWildcard {} -> pure p
PatternEmpty {} -> pure p
PatternConstructorApp app -> PatternConstructorApp <$> appVariables f app
appVariables :: ConstructorApp -> [VarName]
appVariables (ConstructorApp _ ps) = concatMap patternVariables ps
patternArgVariables :: Traversal' PatternArg VarName
patternArgVariables f = traverseOf patternArgPattern (patternVariables f)
appVariables :: Traversal' ConstructorApp VarName
appVariables f = traverseOf constrAppParameters (traverse (patternArgVariables f))
idenName :: Iden -> Name
idenName = \case
@ -36,25 +38,35 @@ idenName = \case
IdenInductive (InductiveRef i) -> i
IdenAxiom (AxiomRef a) -> a
smallerPatternVariables :: Pattern -> [VarName]
smallerPatternVariables = \case
PatternVariable {} -> []
PatternBraces b -> smallerPatternVariables b
PatternWildcard {} -> []
PatternEmpty {} -> []
PatternConstructorApp app -> appVariables app
smallerPatternVariables :: Traversal' Pattern VarName
smallerPatternVariables f p = case p of
PatternVariable {} -> pure p
PatternWildcard {} -> pure p
PatternEmpty {} -> pure p
PatternConstructorApp app -> PatternConstructorApp <$> appVariables f app
viewApp :: Expression -> (Expression, [Expression])
viewApp e = case e of
ExpressionApplication (Application l r _) ->
second (`snoc` r) (viewApp l)
_ -> (e, [])
viewApp :: Expression -> (Expression, [ApplicationArg])
viewApp e =
case e of
ExpressionApplication (Application l r i) ->
second (`snoc` ApplicationArg i r) (viewApp l)
_ -> (e, [])
viewAppArgAsPattern :: ApplicationArg -> Maybe PatternArg
viewAppArgAsPattern a = do
p' <- viewExpressionAsPattern (a ^. appArg)
return
( PatternArg
{ _patternArgIsImplicit = a ^. appArgIsImplicit,
_patternArgPattern = p'
}
)
viewExpressionAsPattern :: Expression -> Maybe Pattern
viewExpressionAsPattern e = case viewApp e of
(f, args)
| Just c <- getConstructor f -> do
args' <- mapM viewExpressionAsPattern args
args' <- mapM viewAppArgAsPattern args
Just $ PatternConstructorApp (ConstructorApp c args')
(f, [])
| Just v <- getVariable f -> Just (PatternVariable v)
@ -200,13 +212,16 @@ isSmallUniverse' = \case
ExpressionUniverse u -> isSmallUniverse u
_ -> False
toApplicationArg :: Pattern -> ApplicationArg
toApplicationArg = \case
PatternVariable v -> ApplicationArg Explicit (toExpression v)
PatternConstructorApp a -> ApplicationArg Explicit (toExpression a)
PatternEmpty -> impossible
PatternBraces p -> set appArgIsImplicit Implicit (toApplicationArg p)
PatternWildcard _ -> error "TODO"
toApplicationArg :: PatternArg -> ApplicationArg
toApplicationArg p =
set appArgIsImplicit (p ^. patternArgIsImplicit) (helper (p ^. patternArgPattern))
where
helper :: Pattern -> ApplicationArg
helper = \case
PatternVariable v -> ApplicationArg Explicit (toExpression v)
PatternConstructorApp a -> ApplicationArg Explicit (toExpression a)
PatternEmpty -> impossible
PatternWildcard _ -> error "TODO"
clauseLhsAsExpression :: FunctionClause -> Expression
clauseLhsAsExpression cl =

View File

@ -83,7 +83,7 @@ type family ExpressionType s = res | res -> s where
type PatternType :: Stage -> GHC.Type
type family PatternType s = res | res -> s where
PatternType 'Parsed = PatternAtom 'Parsed
PatternType 'Scoped = Pattern
PatternType 'Scoped = PatternArg
type family ImportType (s :: Stage) :: GHC.Type where
ImportType 'Parsed = TopModulePath
@ -257,15 +257,15 @@ deriving stock instance (Ord (ExpressionType s), Ord (SymbolType s)) => Ord (Ind
--------------------------------------------------------------------------------
data PatternApp = PatternApp
{ _patAppLeft :: Pattern,
_patAppRight :: Pattern
{ _patAppLeft :: PatternArg,
_patAppRight :: PatternArg
}
deriving stock (Show, Eq, Ord)
data PatternInfixApp = PatternInfixApp
{ _patInfixLeft :: Pattern,
{ _patInfixLeft :: PatternArg,
_patInfixConstructor :: ConstructorRef,
_patInfixRight :: Pattern
_patInfixRight :: PatternArg
}
deriving stock (Show, Eq, Ord)
@ -273,7 +273,7 @@ instance HasFixity PatternInfixApp where
getFixity (PatternInfixApp _ op _) = fromMaybe impossible (op ^. constructorRefName . S.nameFixity)
data PatternPostfixApp = PatternPostfixApp
{ _patPostfixParameter :: Pattern,
{ _patPostfixParameter :: PatternArg,
_patPostfixConstructor :: ConstructorRef
}
deriving stock (Show, Eq, Ord)
@ -281,13 +281,18 @@ data PatternPostfixApp = PatternPostfixApp
instance HasFixity PatternPostfixApp where
getFixity (PatternPostfixApp _ op) = fromMaybe impossible (op ^. constructorRefName . S.nameFixity)
data PatternArg = PatternArg
{ _patternArgIsImplicit :: IsImplicit,
_patternArgPattern :: Pattern
}
deriving stock (Show, Eq, Ord)
data Pattern
= PatternVariable (SymbolType 'Scoped)
| PatternConstructor ConstructorRef
| PatternApplication PatternApp
| PatternInfixApplication PatternInfixApp
| PatternPostfixApplication PatternPostfixApp
| PatternBraces Pattern
| PatternWildcard Wildcard
| PatternEmpty
deriving stock (Show, Eq, Ord)
@ -300,7 +305,6 @@ instance HasAtomicity Pattern where
PatternInfixApplication a -> Aggregate (getFixity a)
PatternPostfixApplication p -> Aggregate (getFixity p)
PatternWildcard {} -> Atom
PatternBraces {} -> Atom
PatternEmpty -> Atom
--------------------------------------------------------------------------------
@ -887,8 +891,7 @@ data ExpressionAtoms (s :: Stage) = ExpressionAtoms
_expressionAtomsLoc :: Interval
}
--------------------------------------------------------------------------------
makeLenses ''PatternArg
makeLenses ''Function
makeLenses ''InductiveDef
makeLenses ''PostfixApplication
@ -1048,6 +1051,11 @@ instance
--------------------------------------------------------------------------------
instance HasAtomicity PatternArg where
atomicity p
| Implicit <- p ^. patternArgIsImplicit = Atom
| otherwise = atomicity (p ^. patternArgPattern)
idenOverName :: (forall s. S.Name' s -> S.Name' s) -> ScopedIden -> ScopedIden
idenOverName f = \case
ScopedAxiom a -> ScopedAxiom (over axiomRefName f a)

View File

@ -448,6 +448,9 @@ instance PrettyCode QualifiedName where
let symbols = _qualifiedPath ^. pathParts NonEmpty.|> _qualifiedSymbol
dotted <$> mapM ppSymbol symbols
bracesIf :: Bool -> Doc Ann -> Doc Ann
bracesIf t = if t then braces else id
ppName :: forall s r. (SingI s, Members '[Reader Options] r) => IdentifierType s -> Sem r (Doc Ann)
ppName = case sing :: SStage s of
SParsed -> ppCode
@ -652,6 +655,11 @@ instance PrettyCode PatternScopedIden where
PatternScopedVar v -> ppCode v
PatternScopedConstructor c -> ppCode c
instance PrettyCode PatternArg where
ppCode a = do
p <- ppCode (a ^. patternArgPattern)
return (bracesIf (Implicit == a ^. patternArgIsImplicit) p)
instance SingI s => PrettyCode (PatternAtom s) where
ppCode a = case a of
PatternAtomIden n -> case sing :: SStage s of
@ -750,7 +758,6 @@ instance PrettyCode Pattern where
return $ l' <+> r'
PatternWildcard {} -> return kwWildcard
PatternEmpty -> return $ parens mempty
PatternBraces p -> braces <$> ppCode p
PatternConstructor constr -> ppCode constr
PatternInfixApplication i -> ppPatternInfixApp i
PatternPostfixApplication i -> ppPatternPostfixApp i

View File

@ -1198,7 +1198,7 @@ checkParseExpressionAtoms = checkExpressionAtoms >=> parseExpressionAtoms
checkParsePatternAtom ::
Members '[Error ScoperError, State Scope, State ScoperState, InfoTableBuilder, NameIdGen] r =>
PatternAtom 'Parsed ->
Sem r Pattern
Sem r PatternArg
checkParsePatternAtom = checkPatternAtom >=> parsePatternAtom
checkStatement ::
@ -1423,7 +1423,7 @@ parseTerm =
type ParsePat = P.Parsec () [PatternAtom 'Scoped]
makePatternTable ::
PatternAtom 'Scoped -> [[P.Operator ParsePat Pattern]]
PatternAtom 'Scoped -> [[P.Operator ParsePat PatternArg]]
makePatternTable atom = [appOp] : operators
where
getConstructorRef :: PatternAtom 'Scoped -> Maybe ConstructorRef
@ -1437,24 +1437,24 @@ makePatternTable atom = [appOp] : operators
constructorRefs = case atom of
PatternAtomParens (PatternAtoms atoms _) -> mapMaybe getConstructorRef (toList atoms)
_ -> []
mkSymbolTable :: [ConstructorRef] -> [[P.Operator ParsePat Pattern]]
mkSymbolTable :: [ConstructorRef] -> [[P.Operator ParsePat PatternArg]]
mkSymbolTable = reverse . map (map snd) . groupSortOn' fst . mapMaybe unqualifiedSymbolOp
where
unqualifiedSymbolOp :: ConstructorRef -> Maybe (Precedence, P.Operator ParsePat Pattern)
unqualifiedSymbolOp :: ConstructorRef -> Maybe (Precedence, P.Operator ParsePat PatternArg)
unqualifiedSymbolOp (ConstructorRef' S.Name' {..})
| Just Fixity {..} <- _nameFixity,
_nameKind == S.KNameConstructor = Just $
case _fixityArity of
Unary u -> (_fixityPrecedence, P.Postfix (unaryApp <$> parseSymbolId _nameId))
where
unaryApp :: ConstructorRef -> Pattern -> Pattern
unaryApp :: ConstructorRef -> PatternArg -> PatternArg
unaryApp funName = case u of
AssocPostfix -> PatternPostfixApplication . (`PatternPostfixApp` funName)
AssocPostfix -> explicitP . PatternPostfixApplication . (`PatternPostfixApp` funName)
Binary b -> (_fixityPrecedence, infixLRN (binaryInfixApp <$> parseSymbolId _nameId))
where
binaryInfixApp :: ConstructorRef -> Pattern -> Pattern -> Pattern
binaryInfixApp name argLeft = PatternInfixApplication . PatternInfixApp argLeft name
infixLRN :: ParsePat (Pattern -> Pattern -> Pattern) -> P.Operator ParsePat Pattern
binaryInfixApp :: ConstructorRef -> PatternArg -> PatternArg -> PatternArg
binaryInfixApp name argLeft = explicitP . PatternInfixApplication . PatternInfixApp argLeft name
infixLRN :: ParsePat (PatternArg -> PatternArg -> PatternArg) -> P.Operator ParsePat PatternArg
infixLRN = case b of
AssocLeft -> P.InfixL
AssocRight -> P.InfixR
@ -1470,22 +1470,30 @@ makePatternTable atom = [appOp] : operators
return ref
-- Application by juxtaposition.
appOp :: P.Operator ParsePat Pattern
appOp :: P.Operator ParsePat PatternArg
appOp = P.InfixL (return app)
where
app :: Pattern -> Pattern -> Pattern
app :: PatternArg -> PatternArg -> PatternArg
app l r =
PatternApplication
( PatternApp
{ _patAppLeft = l,
_patAppRight = r
}
explicitP
( PatternApplication
( PatternApp
{ _patAppLeft = l,
_patAppRight = r
}
)
)
explicitP :: Pattern -> PatternArg
explicitP = PatternArg Explicit
implicitP :: Pattern -> PatternArg
implicitP = PatternArg Implicit
parsePatternTerm ::
forall r.
Members '[Reader (ParsePat Pattern), Embed ParsePat] r =>
Sem r Pattern
Members '[Reader (ParsePat PatternArg), Embed ParsePat] r =>
Sem r PatternArg
parsePatternTerm = do
pPat <- ask
embed @ParsePat $
@ -1496,9 +1504,9 @@ parsePatternTerm = do
<|> parseWildcard
<|> parseEmpty
where
parseNoInfixConstructor :: ParsePat Pattern
parseNoInfixConstructor :: ParsePat PatternArg
parseNoInfixConstructor =
PatternConstructor
explicitP . PatternConstructor
<$> P.token constructorNoFixity mempty
where
constructorNoFixity :: PatternAtom 'Scoped -> Maybe ConstructorRef
@ -1509,35 +1517,38 @@ parsePatternTerm = do
n = ref ^. constructorRefName
_ -> Nothing
parseWildcard :: ParsePat Pattern
parseWildcard = PatternWildcard <$> P.token isWildcard mempty
parseWildcard :: ParsePat PatternArg
parseWildcard = explicitP . PatternWildcard <$> P.token isWildcard mempty
where
isWildcard :: PatternAtom 'Scoped -> Maybe Wildcard
isWildcard s = case s of
PatternAtomWildcard i -> Just i
_ -> Nothing
parseEmpty :: ParsePat Pattern
parseEmpty = PatternEmpty <$ P.satisfy isEmpty
parseEmpty :: ParsePat PatternArg
parseEmpty = explicitP PatternEmpty <$ P.satisfy isEmpty
where
isEmpty :: PatternAtom 'Scoped -> Bool
isEmpty s = case s of
PatternAtomEmpty -> True
_ -> False
parseVariable :: ParsePat Pattern
parseVariable = PatternVariable <$> P.token var mempty
parseVariable :: ParsePat PatternArg
parseVariable = explicitP . PatternVariable <$> P.token var mempty
where
var :: PatternAtom 'Scoped -> Maybe S.Symbol
var s = case s of
PatternAtomIden (PatternScopedVar sym) -> Just sym
_ -> Nothing
parseBraces :: ParsePat Pattern -> ParsePat Pattern
parseBraces :: ParsePat PatternArg -> ParsePat PatternArg
parseBraces patternParser = do
exprs <- P.token bracesPat mempty
case P.parse patternParser "" exprs of
Right r -> return (PatternBraces r)
Right (PatternArg i p)
-- TODO proper error
| Implicit <- i -> error "nested braces"
| otherwise -> return (implicitP p)
Left {} -> mzero
where
bracesPat :: PatternAtom 'Scoped -> Maybe [PatternAtom 'Scoped]
@ -1545,7 +1556,7 @@ parsePatternTerm = do
PatternAtomBraces (PatternAtoms ss _) -> Just (toList ss)
_ -> Nothing
parseParens :: ParsePat Pattern -> ParsePat Pattern
parseParens :: ParsePat PatternArg -> ParsePat PatternArg
parseParens patternParser = do
exprs <- P.token parenPat mempty
case P.parse patternParser "" exprs of
@ -1560,22 +1571,22 @@ parsePatternTerm = do
mkPatternParser ::
forall r.
Members '[Embed ParsePat] r =>
[[P.Operator ParsePat Pattern]] ->
Sem r Pattern
[[P.Operator ParsePat PatternArg]] ->
Sem r PatternArg
mkPatternParser table = embed @ParsePat pPattern
where
pPattern :: ParsePat Pattern
pPattern :: ParsePat PatternArg
pPattern = P.makeExprParser pTerm table
pTerm :: ParsePat Pattern
pTerm :: ParsePat PatternArg
pTerm = runM parseTermRec
where
parseTermRec :: Sem '[Embed ParsePat] Pattern
parseTermRec :: Sem '[Embed ParsePat] PatternArg
parseTermRec = runReader pPattern parsePatternTerm
parsePatternAtom ::
Members '[Error ScoperError, State Scope] r =>
PatternAtom 'Scoped ->
Sem r Pattern
Sem r PatternArg
parsePatternAtom sec = do
case res of
Left {} -> case sec of
@ -1584,7 +1595,7 @@ parsePatternAtom sec = do
Right r -> return r
where
tbl = makePatternTable sec
parser :: ParsePat Pattern
parser :: ParsePat PatternArg
parser = runM (mkPatternParser tbl) <* P.eof
res = P.parse parser filePath [sec]

View File

@ -1,8 +1,14 @@
module Juvix.Syntax.IsImplicit where
import Juvix.Prelude
import Juvix.Prelude.Pretty
data IsImplicit = Explicit | Implicit
deriving stock (Show, Eq, Ord, Generic)
instance Hashable IsImplicit
instance Pretty IsImplicit where
pretty = \case
Implicit -> "implicit"
Explicit -> "explicit"

View File

@ -163,8 +163,8 @@ checkLhs ::
Interval ->
Maybe Arity ->
Arity ->
[Pattern] ->
Sem r ([Pattern], LocalVars, Arity)
[PatternArg] ->
Sem r ([PatternArg], LocalVars, Arity)
checkLhs loc hint ariSignature pats = do
(locals, (pats', bodyAri)) <- runState emptyLocalVars (goLhs ariSignature pats)
return (pats', locals, bodyAri)
@ -173,7 +173,7 @@ checkLhs loc hint ariSignature pats = do
-- body once all the patterns have been processed).
-- Does not insert holes greedily. I.e. implicit wildcards are only inserted
-- between explicit parameters already in the pattern.
goLhs :: Arity -> [Pattern] -> Sem (State LocalVars ': r) ([Pattern], Arity)
goLhs :: Arity -> [PatternArg] -> Sem (State LocalVars ': r) ([PatternArg], Arity)
goLhs a = \case
[] -> return $ case hint >>= tailHelper a of
Nothing -> ([], a)
@ -192,25 +192,26 @@ checkLhs loc hint ariSignature pats = do
p' <- checkPattern ArityUnknown p
first (p' :) <$> goLhs ArityUnknown ps
ArityFunction (FunctionArity l r) ->
case (getPatternBraces p, l) of
(Just b, ParamImplicit) -> do
b' <- checkPattern (arityParameter l) b
case (p ^. patternArgIsImplicit, l) of
(Implicit, ParamImplicit) -> do
b' <- checkPattern (arityParameter l) p
first (b' :) <$> goLhs r ps
(Just x, ParamExplicit {}) ->
(Implicit, ParamExplicit {}) ->
throw
( ErrExpectedExplicitPattern
ExpectedExplicitPattern
{ _expectedExplicitPattern = x
( ErrWrongPatternIsImplicit
WrongPatternIsImplicit
{ _wrongPatternIsImplicitExpected = Explicit,
_wrongPatternIsImplicitActual = p
}
)
(Nothing, ParamImplicit) ->
(Explicit, ParamImplicit) ->
first (wildcard :) <$> goLhs r lhs
(Nothing, ParamExplicit pa) -> do
(Explicit, ParamExplicit pa) -> do
p' <- checkPattern pa p
first (p' :) <$> goLhs r ps
where
wildcard :: Pattern
wildcard = PatternBraces (PatternWildcard (Wildcard loc))
wildcard :: PatternArg
wildcard = PatternArg Implicit (PatternWildcard (Wildcard loc))
tailHelper :: Arity -> Arity -> Maybe Int
tailHelper a target
@ -220,30 +221,28 @@ checkLhs loc hint ariSignature pats = do
a' = dropSuffix target' (unfoldArity a)
target' = unfoldArity target
getPatternBraces :: Pattern -> Maybe Pattern
getPatternBraces p = case p of
PatternBraces {} -> Just p
_ -> Nothing
checkPattern ::
forall r.
Members '[Reader InfoTable, Error ArityCheckerError, State LocalVars] r =>
Arity ->
Pattern ->
Sem r Pattern
checkPattern ari = \case
PatternBraces p -> checkPattern ari p
PatternVariable v -> addArity v ari $> PatternVariable v
PatternWildcard i -> return (PatternWildcard i)
PatternConstructorApp c -> case ari of
ArityUnit -> PatternConstructorApp <$> checkConstructorApp c
ArityUnknown -> PatternConstructorApp <$> checkConstructorApp c
ArityFunction {} ->
throw
( ErrPatternFunction
PatternFunction
{ _patternFunction = c
}
)
PatternArg ->
Sem r PatternArg
checkPattern ari = traverseOf patternArgPattern helper
where
helper :: Pattern -> Sem r Pattern
helper = \case
PatternVariable v -> addArity v ari $> PatternVariable v
PatternWildcard i -> return (PatternWildcard i)
PatternConstructorApp c -> case ari of
ArityUnit -> PatternConstructorApp <$> checkConstructorApp c
ArityUnknown -> PatternConstructorApp <$> checkConstructorApp c
ArityFunction {} ->
throw
( ErrPatternFunction
PatternFunction
{ _patternFunction = c
}
)
checkConstructorApp ::
forall r.

View File

@ -10,7 +10,7 @@ import Juvix.Syntax.MicroJuvix.ArityChecker.Error.Types
data ArityCheckerError
= ErrWrongConstructorAppLength WrongConstructorAppLength
| ErrLhsTooManyPatterns LhsTooManyPatterns
| ErrExpectedExplicitPattern ExpectedExplicitPattern
| ErrWrongPatternIsImplicit WrongPatternIsImplicit
| ErrExpectedExplicitArgument ExpectedExplicitArgument
| ErrPatternFunction PatternFunction
| ErrTooManyArguments TooManyArguments
@ -21,7 +21,7 @@ instance ToGenericError ArityCheckerError where
genericError = \case
ErrWrongConstructorAppLength e -> genericError e
ErrLhsTooManyPatterns e -> genericError e
ErrExpectedExplicitPattern e -> genericError e
ErrWrongPatternIsImplicit e -> genericError e
ErrExpectedExplicitArgument e -> genericError e
ErrPatternFunction e -> genericError e
ErrTooManyArguments e -> genericError e

View File

@ -40,7 +40,7 @@ instance ToGenericError WrongConstructorAppLength where
| otherwise = pretty n
newtype LhsTooManyPatterns = LhsTooManyPatterns
{ _lhsTooManyPatternsRemaining :: NonEmpty Pattern
{ _lhsTooManyPatternsRemaining :: NonEmpty PatternArg
}
makeLenses ''LhsTooManyPatterns
@ -65,13 +65,14 @@ instance ToGenericError LhsTooManyPatterns where
| n == 1 = "was"
| otherwise = "were"
newtype ExpectedExplicitPattern = ExpectedExplicitPattern
{ _expectedExplicitPattern :: Pattern
data WrongPatternIsImplicit = WrongPatternIsImplicit
{ _wrongPatternIsImplicitExpected :: IsImplicit,
_wrongPatternIsImplicitActual :: PatternArg
}
makeLenses ''ExpectedExplicitPattern
makeLenses ''WrongPatternIsImplicit
instance ToGenericError ExpectedExplicitPattern where
instance ToGenericError WrongPatternIsImplicit where
genericError e =
GenericError
{ _genericErrorLoc = i,
@ -79,10 +80,17 @@ instance ToGenericError ExpectedExplicitPattern where
_genericErrorIntervals = [i]
}
where
i = getLoc (e ^. expectedExplicitPattern)
i = getLoc (e ^. wrongPatternIsImplicitActual)
expec = e ^. wrongPatternIsImplicitExpected
found = e ^. wrongPatternIsImplicitActual . patternArgIsImplicit
pat = e ^. wrongPatternIsImplicitActual
msg =
"Expected an explicit pattern but found an implicit pattern"
<+> ppCode (e ^. expectedExplicitPattern)
"Expected an"
<+> pretty expec
<+> "pattern but found an"
<+> pretty found
<+> "pattern:"
<+> ppCode pat
data ExpectedExplicitArgument = ExpectedExplicitArgument
{ _expectedExplicitArgumentApp :: (Expression, [(IsImplicit, Expression)]),

View File

@ -57,7 +57,7 @@ data FunctionDef = FunctionDef
data FunctionClause = FunctionClause
{ _clauseName :: FunctionName,
_clausePatterns :: [Pattern],
_clausePatterns :: [PatternArg],
_clauseBody :: Expression
}
@ -113,14 +113,18 @@ instance Hashable Application where
-- | Fully applied constructor in a pattern.
data ConstructorApp = ConstructorApp
{ _constrAppConstructor :: Name,
_constrAppParameters :: [Pattern]
_constrAppParameters :: [PatternArg]
}
data PatternArg = PatternArg
{ _patternArgIsImplicit :: IsImplicit,
_patternArgPattern :: Pattern
}
data Pattern
= PatternVariable VarName
| PatternConstructorApp ConstructorApp
| PatternWildcard Wildcard
| PatternBraces Pattern
newtype InductiveParameter = InductiveParameter
{ _inductiveParamName :: VarName
@ -157,6 +161,7 @@ data Function = Function
instance Hashable Function
makeLenses ''Module
makeLenses ''PatternArg
makeLenses ''Include
makeLenses ''FunctionDef
makeLenses ''FunctionClause
@ -191,12 +196,16 @@ instance HasAtomicity ConstructorApp where
| null args = Atom
| otherwise = Aggregate appFixity
instance HasAtomicity PatternArg where
atomicity p
| Implicit <- p ^. patternArgIsImplicit = Atom
| otherwise = atomicity (p ^. patternArgPattern)
instance HasAtomicity Pattern where
atomicity p = case p of
PatternConstructorApp a -> atomicity a
PatternVariable {} -> Atom
PatternWildcard {} -> Atom
PatternBraces {} -> Atom
instance HasLoc FunctionParameter where
getLoc f = v (getLoc (f ^. paramType))
@ -232,9 +241,11 @@ instance HasLoc Pattern where
getLoc = \case
PatternVariable v -> getLoc v
PatternConstructorApp a -> getLoc a
PatternBraces p -> getLoc p
PatternWildcard i -> getLoc i
instance HasLoc PatternArg where
getLoc = getLoc . (^. patternArgPattern)
instance HasLoc ConstructorApp where
getLoc (ConstructorApp c ps) =
case last <$> nonEmpty ps of

View File

@ -244,27 +244,28 @@ renameToSubsE = fmap (ExpressionIden . IdenVar)
renameExpression :: Rename -> Expression -> Expression
renameExpression r = substitutionE (renameToSubsE r)
patternVariables :: Pattern -> [VarName]
patternVariables = \case
PatternVariable v -> [v]
PatternConstructorApp a -> goApp a
PatternBraces b -> patternVariables b
PatternWildcard {} -> []
patternArgVariables :: Traversal' PatternArg VarName
patternArgVariables f = traverseOf patternArgPattern (patternVariables f)
patternVariables :: Traversal' Pattern VarName
patternVariables f p = case p of
PatternVariable v -> PatternVariable <$> f v
PatternConstructorApp a -> PatternConstructorApp <$> goApp f a
PatternWildcard {} -> pure p
where
goApp :: ConstructorApp -> [VarName]
goApp (ConstructorApp _ ps) = concatMap patternVariables ps
goApp :: Traversal' ConstructorApp VarName
goApp g = traverseOf constrAppParameters (traverse (patternArgVariables g))
renamePatternArg :: Rename -> PatternArg -> PatternArg
renamePatternArg = over patternArgPattern . renamePattern
renamePattern :: Rename -> Pattern -> Pattern
renamePattern m = go
renamePattern m = over patternVariables renameVar
where
go :: Pattern -> Pattern
go p = case p of
PatternVariable v
| Just v' <- m ^. at v -> PatternVariable v'
PatternConstructorApp a -> PatternConstructorApp (goApp a)
_ -> p
goApp :: ConstructorApp -> ConstructorApp
goApp (ConstructorApp c ps) = ConstructorApp c (map go ps)
renameVar :: VarName -> VarName
renameVar v
| Just v' <- m ^. at v = v'
| otherwise = v
inductiveTypeVarsAssoc :: Foldable f => InductiveDef -> f a -> HashMap VarName a
inductiveTypeVarsAssoc def l
@ -275,6 +276,7 @@ inductiveTypeVarsAssoc def l
vars :: [VarName]
vars = def ^.. inductiveParameters . each . inductiveParamName
-- TODO remove this after monojuvix is gone
functionTypeVarsAssoc :: forall a f. Foldable f => FunctionDef -> f a -> HashMap VarName a
functionTypeVarsAssoc def l = sig <> mconcatMap clause (def ^. funDefClauses)
where
@ -297,8 +299,8 @@ functionTypeVarsAssoc def l = sig <> mconcatMap clause (def ^. funDefClauses)
clauseVars :: [Maybe VarName]
clauseVars = take n (map patternVar (c ^. clausePatterns))
where
patternVar :: Pattern -> Maybe VarName
patternVar = \case
patternVar :: PatternArg -> Maybe VarName
patternVar a = case a ^. patternArgPattern of
PatternVariable v -> Just v
_ -> Nothing

View File

@ -199,6 +199,11 @@ instance PrettyCode InductiveDef where
rhs <- indent' $ align $ concatWith (\a b -> a <> line <> kwPipe <+> b) inductiveConstructors'
return $ kwData <+> inductiveName' <+?> params <+> kwEquals <> line <> rhs
instance PrettyCode PatternArg where
ppCode a = do
p <- ppCode (a ^. patternArgPattern)
return (bracesIf (Implicit == a ^. patternArgIsImplicit) p)
instance PrettyCode ConstructorApp where
ppCode c = do
constr' <- ppCode (c ^. constrAppConstructor)
@ -210,7 +215,6 @@ instance PrettyCode Pattern where
PatternVariable v -> ppCode v
PatternConstructorApp a -> ppCode a
PatternWildcard {} -> return kwWildcard
PatternBraces b -> braces <$> ppCode b
instance PrettyCode FunctionDef where
ppCode f = do
@ -327,8 +331,11 @@ instance PrettyCode TypeCalls where
elems' <- mapM ppCode elems
return $ title <> line <> vsep elems' <> line
parensCond :: Bool -> Doc Ann -> Doc Ann
parensCond t d = if t then parens d else d
parensIf :: Bool -> Doc Ann -> Doc Ann
parensIf t = if t then parens else id
bracesIf :: Bool -> Doc Ann -> Doc Ann
bracesIf t = if t then braces else id
ppPostExpression ::
(PrettyCode a, HasAtomicity a, Member (Reader Options) r) =>
@ -358,7 +365,7 @@ ppLRExpression ::
a ->
Sem r (Doc Ann)
ppLRExpression associates fixlr e =
parensCond (atomParens associates (atomicity e) fixlr)
parensIf (atomParens associates (atomicity e) fixlr)
<$> ppCode e
ppCodeAtom :: (HasAtomicity c, PrettyCode c, Members '[Reader Options] r) => c -> Sem r (Doc Ann)

View File

@ -174,9 +174,9 @@ checkFunctionClause info FunctionClause {..} = do
where
clauseType :: Expression
clauseType = info ^. functionInfoDef . funDefType
helper :: [Pattern] -> Expression -> Sem r (LocalVars, Expression)
helper :: [PatternArg] -> Expression -> Sem r (LocalVars, Expression)
helper pats ty = runState emptyLocalVars (go pats ty)
go :: [Pattern] -> Expression -> Sem (State LocalVars ': r) Expression
go :: [PatternArg] -> Expression -> Sem (State LocalVars ': r) Expression
go pats bodyTy = case pats of
[] -> return bodyTy
(p : ps) -> case bodyTy of
@ -200,26 +200,38 @@ checkFunctionClause info FunctionClause {..} = do
typeOfArg :: FunctionParameter -> Expression
typeOfArg = (^. paramType)
matchIsImplicit :: Member (Error TypeCheckerError) r => IsImplicit -> PatternArg -> Sem r ()
matchIsImplicit expected actual =
unless
(expected == actual ^. patternArgIsImplicit)
( throw
( ErrArity
( ErrWrongPatternIsImplicit
WrongPatternIsImplicit
{ _wrongPatternIsImplicitExpected = expected,
_wrongPatternIsImplicitActual = actual
}
)
)
)
checkPattern ::
forall r.
Members '[Reader InfoTable, Error TypeCheckerError, State LocalVars, Inference, NameIdGen] r =>
FunctionName ->
FunctionParameter ->
Pattern ->
PatternArg ->
Sem r ()
checkPattern funName = go
where
go :: FunctionParameter -> Pattern -> Sem r ()
go argTy p = do
go :: FunctionParameter -> PatternArg -> Sem r ()
go argTy patArg = do
matchIsImplicit (argTy ^. paramImplicit) patArg
tyVarMap <- fmap (ExpressionIden . IdenVar) . (^. localTyMap) <$> get
ty <- normalizeType (substitutionE tyVarMap (typeOfArg argTy))
let unbrace = \case
PatternBraces b -> b
x -> x
pat = unbrace p
let pat = patArg ^. patternArgPattern
case pat of
PatternWildcard {} -> return ()
PatternBraces {} -> impossible
PatternVariable v -> do
modify (addType v ty)
registerIden v ty

View File

@ -42,7 +42,7 @@ viewCall = \case
return $ case s of
Nothing -> CallRow Nothing
Just s' -> CallRow (Just (s', REq))
_ -> return (CallRow Nothing)
Nothing -> return (CallRow Nothing)
ExpressionIden (IdenFunction x) ->
return (Just (singletonCall x))
_ -> return Nothing

View File

@ -20,15 +20,16 @@ emptySizeInfo =
_sizeSmaller = mempty
}
mkSizeInfo :: [Pattern] -> SizeInfo
mkSizeInfo :: [PatternArg] -> SizeInfo
mkSizeInfo ps = SizeInfo {..}
where
ps' = filter (not . isBrace) ps
isBrace = \case
PatternBraces {} -> True
_ -> False
_sizeEqual = ps
ps' :: [Pattern]
ps' = map (^. patternArgPattern) (filter (not . isBrace) ps)
isBrace :: PatternArg -> Bool
isBrace = (== Implicit) . (^. patternArgIsImplicit)
_sizeEqual = map (^. patternArgPattern) ps
_sizeSmaller :: HashMap VarName Int
_sizeSmaller =
HashMap.fromList
[ (v, i) | (i, p) <- zip [0 ..] ps', v <- smallerPatternVariables p
[ (v, i) | (i, p) <- zip [0 ..] ps', v <- p ^.. smallerPatternVariables
]

View File

@ -163,7 +163,7 @@ goFunctionDef f = do
goFunctionClause :: Name -> Abstract.FunctionClause -> Sem r FunctionClause
goFunctionClause n c = do
_clauseBody' <- goExpression (c ^. Abstract.clauseBody)
_clausePatterns' <- mapM goPattern (c ^. Abstract.clausePatterns)
_clausePatterns' <- mapM goPatternArg (c ^. Abstract.clausePatterns)
return
FunctionClause
{ _clauseName = n,
@ -171,17 +171,25 @@ goFunctionClause n c = do
_clauseBody = _clauseBody'
}
goPatternArg :: Abstract.PatternArg -> Sem r PatternArg
goPatternArg p = do
pat' <- goPattern (p ^. Abstract.patternArgPattern)
return
PatternArg
{ _patternArgIsImplicit = p ^. Abstract.patternArgIsImplicit,
_patternArgPattern = pat'
}
goPattern :: Abstract.Pattern -> Sem r Pattern
goPattern p = case p of
Abstract.PatternVariable v -> return (PatternVariable v)
Abstract.PatternConstructorApp c -> PatternConstructorApp <$> goConstructorApp c
Abstract.PatternWildcard i -> return (PatternWildcard i)
Abstract.PatternBraces b -> PatternBraces <$> goPattern b
Abstract.PatternEmpty -> unsupported "pattern empty"
goConstructorApp :: Abstract.ConstructorApp -> Sem r ConstructorApp
goConstructorApp c = do
_constrAppParameters' <- mapM goPattern (c ^. Abstract.constrAppParameters)
_constrAppParameters' <- mapM goPatternArg (c ^. Abstract.constrAppParameters)
return
ConstructorApp
{ _constrAppConstructor = c ^. Abstract.constrAppConstructor . Abstract.constructorRefName,

View File

@ -315,11 +315,17 @@ goFunctionClause funSig argTyps clause = do
projCtor :: Text -> Expression
projCtor ctorArg = functionCall (ExpressionVar (asProjName ctorArg ctorName)) [castToType ty arg]
subConditions :: Sem r [Expression]
subConditions = fmap concat (zipWithM patternCondition (map projCtor ctorArgs) _constrAppParameters)
subConditions =
fmap
concat
( zipWithM
patternCondition
(map projCtor ctorArgs)
(_constrAppParameters ^.. each . Micro.patternArgPattern)
)
fmap (isCtor :) subConditions
Micro.PatternVariable {} -> return []
Micro.PatternWildcard {} -> return []
Micro.PatternBraces b -> patternCondition arg b
clauseCondition :: Sem r (Maybe Expression)
clauseCondition = fmap (foldr1 f) . nonEmpty <$> conditions

View File

@ -174,7 +174,14 @@ typeOfConstructor name = do
getInductiveCType (info ^. Micro.constructorInfoInductive)
getClausePatterns :: Member (Reader Micro.TypesTable) r => Micro.FunctionClause -> Sem r [Micro.Pattern]
getClausePatterns c = filterCompileTimeArgsOrPatterns (c ^. Micro.clauseName) (c ^. Micro.clausePatterns)
getClausePatterns c =
filterCompileTimeArgsOrPatterns
(c ^. Micro.clauseName)
( c
^.. Micro.clausePatterns
. each
. Micro.patternArgPattern
)
functionInfoPatternsNum :: Member (Reader Micro.TypesTable) r => Micro.FunctionInfo -> Sem r Int
functionInfoPatternsNum fInfo = do
@ -203,9 +210,8 @@ buildPatternInfoTable argTyps c =
return
[(v ^. Micro.nameText, BindingInfo {_bindingInfoExpr = exp, _bindingInfoType = typ})]
Micro.PatternConstructorApp Micro.ConstructorApp {..} ->
goConstructorApp exp _constrAppConstructor _constrAppParameters
goConstructorApp exp _constrAppConstructor (_constrAppParameters ^.. each . Micro.patternArgPattern)
Micro.PatternWildcard {} -> return []
Micro.PatternBraces b -> go (b, (exp, typ))
goConstructorApp :: Expression -> Micro.Name -> [Micro.Pattern] -> Sem r [(Text, BindingInfo)]
goConstructorApp exp constructorName ps = do

View File

@ -359,7 +359,7 @@ goFunctionDefConcrete n d = do
goClause :: Micro.FunctionClause -> Sem r FunctionClause
goClause c = do
body' <- goExpression (c ^. Micro.clauseBody)
patterns' <- zipWithM goPattern' patternTys (c ^. Micro.clausePatterns)
patterns' <- zipWithM goPatternArg patternTys (c ^. Micro.clausePatterns)
return
FunctionClause
{ _clauseName = funName,
@ -437,7 +437,7 @@ goFunctionDefPoly def poly
pvars' <- mapM cloneName' pvars
let localVarsRename :: Micro.Rename
localVarsRename = HashMap.fromList (zipExact pvars pvars')
_clausePatterns = map (Micro.renamePattern localVarsRename) patsTail
_clausePatterns = map (Micro.renamePatternArg localVarsRename) patsTail
_clauseBody =
Micro.substitutionE
(concreteSubsE <> Micro.renameToSubsE localVarsRename)
@ -448,19 +448,21 @@ goFunctionDefPoly def poly
..
}
where
patsTail :: [Micro.Pattern]
patsTail :: [Micro.PatternArg]
patsTail = dropExact (length tyVars) (c ^. Micro.clausePatterns)
pvars :: [Micro.VarName]
pvars = concatMap Micro.patternVariables patsTail
pvars = concatMap (^.. Micro.patternArgVariables) patsTail
sig' :: Micro.ConcreteType
sig' = Micro.substitutionConcrete (i ^. concreteTypeSubs) tyTail
goPattern' :: forall r. Members '[Reader ConcreteTable, Reader Micro.InfoTable] r => Micro.ConcreteType -> Micro.Pattern -> Sem r Pattern
goPattern' ty = \case
goPatternArg :: forall r. Members '[Reader ConcreteTable, Reader Micro.InfoTable] r => Micro.ConcreteType -> Micro.PatternArg -> Sem r Pattern
goPatternArg ty = goPattern ty . (^. Micro.patternArgPattern)
goPattern :: forall r. Members '[Reader ConcreteTable, Reader Micro.InfoTable] r => Micro.ConcreteType -> Micro.Pattern -> Sem r Pattern
goPattern ty = \case
Micro.PatternVariable v -> return (PatternVariable (goName v))
Micro.PatternConstructorApp capp -> PatternConstructorApp <$> goApp capp
Micro.PatternWildcard {} -> return PatternWildcard
Micro.PatternBraces b -> goPattern' ty b
where
goApp :: Micro.ConstructorApp -> Sem r ConstructorApp
goApp capp = case ty ^. Micro.unconcreteType of
@ -469,7 +471,7 @@ goPattern' ty = \case
c' = goName (capp ^. Micro.constrAppConstructor)
cInfo <- Micro.lookupConstructor (capp ^. Micro.constrAppConstructor)
let psTysConcrete = map Micro.mkConcreteType' (cInfo ^. Micro.constructorInfoArgs)
ps' <- zipWithM goPattern' psTysConcrete (capp ^. Micro.constrAppParameters)
ps' <- zipWithM goPatternArg psTysConcrete (capp ^. Micro.constrAppParameters)
return (ConstructorApp c' ps')
Micro.ExpressionApplication a -> do
let getInductive :: Micro.Expression -> Micro.Name
@ -493,7 +495,7 @@ goPattern' ty = \case
subs = HashMap.fromList (zipExact tyParamVars (toList instanceTypes))
psTysConcrete :: [Micro.ConcreteType]
psTysConcrete = map (Micro.substitutionConcrete subs) psTys
ps' <- zipWithM goPattern' psTysConcrete (capp ^. Micro.constrAppParameters)
ps' <- zipWithM goPatternArg psTysConcrete (capp ^. Micro.constrAppParameters)
return (ConstructorApp c' ps')
_ -> impossible

View File

@ -174,7 +174,7 @@ goFunctionClause ::
FunctionClause 'Scoped ->
Sem r Abstract.FunctionClause
goFunctionClause FunctionClause {..} = do
_clausePatterns' <- mapM goPattern _clausePatterns
_clausePatterns' <- mapM goPatternArg _clausePatterns
_clauseBody' <- goExpression _clauseBody
goWhereBlock _clauseWhere
return
@ -360,30 +360,44 @@ goPostfixPatternApplication ::
Sem r Abstract.ConstructorApp
goPostfixPatternApplication a = uncurry Abstract.ConstructorApp <$> viewApp (PatternPostfixApplication a)
viewApp :: forall r. Pattern -> Sem r (Abstract.ConstructorRef, [Abstract.Pattern])
viewApp :: forall r. Pattern -> Sem r (Abstract.ConstructorRef, [Abstract.PatternArg])
viewApp = \case
PatternConstructor c -> return (goConstructorRef c, [])
PatternApplication (PatternApp l r) -> do
r' <- goPattern r
second (`snoc` r') <$> viewApp l
r' <- goPatternArg r
second (`snoc` r') <$> viewAppLeft l
PatternInfixApplication (PatternInfixApp l c r) -> do
l' <- goPattern l
r' <- goPattern r
l' <- goPatternArg l
r' <- goPatternArg r
return (goConstructorRef c, [l', r'])
PatternPostfixApplication (PatternPostfixApp l c) -> do
l' <- goPattern l
l' <- goPatternArg l
return (goConstructorRef c, [l'])
PatternVariable {} -> err
PatternWildcard {} -> err
PatternBraces {} -> err
PatternEmpty {} -> err
where
viewAppLeft :: PatternArg -> Sem r (Abstract.ConstructorRef, [Abstract.PatternArg])
viewAppLeft p
-- TODO proper error
| Implicit <- p ^. patternArgIsImplicit = error "An implicit pattern cannot be on the left of an application"
| otherwise = viewApp (p ^. patternArgPattern)
-- TODO proper error
err :: a
err = error "constructor expected on the left of a pattern application"
goConstructorRef :: ConstructorRef -> Abstract.ConstructorRef
goConstructorRef (ConstructorRef' n) = Abstract.ConstructorRef (goName n)
goPatternArg :: PatternArg -> Sem r Abstract.PatternArg
goPatternArg p = do
pat' <- goPattern (p ^. patternArgPattern)
return
Abstract.PatternArg
{ _patternArgIsImplicit = p ^. patternArgIsImplicit,
_patternArgPattern = pat'
}
goPattern :: Pattern -> Sem r Abstract.Pattern
goPattern p = case p of
PatternVariable a -> return $ Abstract.PatternVariable (goSymbol a)
@ -393,7 +407,6 @@ goPattern p = case p of
PatternPostfixApplication a -> Abstract.PatternConstructorApp <$> goPostfixPatternApplication a
PatternWildcard i -> return (Abstract.PatternWildcard i)
PatternEmpty -> return Abstract.PatternEmpty
PatternBraces b -> Abstract.PatternBraces <$> goPattern b
goAxiom :: Members '[InfoTableBuilder, Error ScoperError, Builtins] r => AxiomDef 'Scoped -> Sem r Abstract.AxiomDef
goAxiom a = do

View File

@ -68,7 +68,7 @@ tests =
"MicroJuvix"
"ExpectedExplicitPattern.juvix"
$ \case
ErrExpectedExplicitPattern {} -> Nothing
ErrWrongPatternIsImplicit {} -> Nothing
_ -> wrongError,
NegTest
"Expected explicit argument"

View File

@ -84,6 +84,13 @@ tests =
$ \case
ErrWrongType {} -> Nothing
_ -> wrongError,
NegTest
"Unexpected braces in pattern"
"issue1337"
"Braces.juvix"
$ \case
ErrArity (ErrWrongPatternIsImplicit {}) -> Nothing
_ -> wrongError,
NegTest
"Wrong return type name for a constructor of a simple data type"
"MicroJuvix"

View File

@ -0,0 +1,11 @@
module M;
inductive Nat {
O : Nat;
S : Nat -> Nat;
};
fun : Nat -> Nat;
fun (S {S {x}}) := x;
end;

View File

View File

@ -0,0 +1,11 @@
module Braces;
inductive Nat {
O : Nat;
S : Nat -> Nat;
};
fun : Nat -> Nat;
fun (S {S {x}}) := x;
end;

View File