curry-frontend issueshttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues2024-02-15T21:06:11Zhttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/92Provide quick fixes for error/warning messages2024-02-15T21:06:11ZFredrik WieczerkowskiProvide quick fixes for error/warning messages### Idea
Attach recommended fixes to error/warning messages that can be solved "easily", e.g.:
* Unused variables/type parameters/imports
* This could have multiple 'fixes':
* Remove the variable
* Rename the variable to `_` ...### Idea
Attach recommended fixes to error/warning messages that can be solved "easily", e.g.:
* Unused variables/type parameters/imports
* This could have multiple 'fixes':
* Remove the variable
* Rename the variable to `_` in the case of parameters
* Prefix the variable with `_` if #135 were to be implemented etc.
* Duplicate imports
* Required (but undeclared) language extensions
* Redundant (implied) language extensions
* Missing top-level type signatures
* Uninitialized record fields (see #125)
* Unused do-bindings (see #134)
* Migrations in the case of source breaks (e.g. if #135 were to be implemented)
* Case mode rename suggestions
* etc.
### Motivation
Having a unified solution for attaching fixes to a message, would make it easy to emit messages like this one from GHC:
```haskell
import Prelude (True)
```
```
src/ImportSyntaxCheck/ImportDataConstr.hs:1:17: error:
In module ‘Prelude’:
‘True’ is a data constructor of ‘Bool’
To import it use
import Prelude( Bool( True ) )
or
import Prelude( Bool(..) )
|
1 | import Prelude (True)
| ^^^^
```
This would also enable downstream features like [language server support](https://github.com/fwcd/curry-language-server/issues/10) for fixable errors and subsequently improve the editing experience for Curry in LSP-supporting editors, as in this Rust example:
![Screenshot](/uploads/912a320592c563c3a30602094f761645/Screenshot_from_2020-06-10_21-00-52.png)https://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/95Emit colored messages2020-10-29T15:33:01ZFredrik WieczerkowskiEmit colored messagesIt would be nice to have GHC-style colored error and warning messages:
![image](/uploads/5ad3843ffebff82130135f1f7a6c84f9/image.png)
Emitting these requires using an ANSI color library, for example [`ansi-terminal`](https://hackage.has...It would be nice to have GHC-style colored error and warning messages:
![image](/uploads/5ad3843ffebff82130135f1f7a6c84f9/image.png)
Emitting these requires using an ANSI color library, for example [`ansi-terminal`](https://hackage.haskell.org/package/ansi-terminal).
It would, however, be preferable to have color support directly in the pretty printing library rather than just including raw ANSI escape sequences as text. There are a bunch of options here, but none of them really are a fitting 'drop-in-replacement' for the currently used pretty printer:
* **Hughes/PJ pretty printers**:
* [`pretty`](https://hackage.haskell.org/package/pretty) is currently used and does not support ANSI coloring
* **Wadler/Leijen pretty printers**:
* [`ansi-wl-pprint`](https://hackage.haskell.org/package/ansi-wl-pprint) has ANSI coloring support, but [may get deprecated](https://github.com/ekmett/ansi-wl-pprint/issues/18)
* [`ansi-pretty`](https://hackage.haskell.org/package/ansi-pretty) is an extension of `ansi-wl-pprint`
* [`prettyprinter`](https://hackage.haskell.org/package/prettyprinter) is modern and supports ANSI coloring, but uses `Data.Text` instead of `String`
Additionally, Wadler/Leijen pretty printers have a lot of subtle differences in their API compared to Hughes/PJ printers, thereby complicating a potential migration. This includes many of them providing their own `Pretty` class.https://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/96Perform general refactoring2020-11-04T12:04:30ZFredrik WieczerkowskiPerform general refactoringAfter the merge of curry-base in !34, a general refactoring of the modules may be due, e.g. considering that the curry-base hierarchy (now located under `src/Curry/...`) duplicates some functionality of the rest of the frontend.After the merge of curry-base in !34, a general refactoring of the modules may be due, e.g. considering that the curry-base hierarchy (now located under `src/Curry/...`) duplicates some functionality of the rest of the frontend.https://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/97Add parameter for output dir2020-11-06T16:00:35ZMichael HanusAdd parameter for output dirSupport a parameter (e.g., --outputdir) to replace the default output directory ".curry" by another one.
Could be used to compile Curry system-specific target code.
*Note:* The outputdir is always relative to the source directory of the...Support a parameter (e.g., --outputdir) to replace the default output directory ".curry" by another one.
Could be used to compile Curry system-specific target code.
*Note:* The outputdir is always relative to the source directory of the module!Fredrik WieczerkowskiFredrik Wieczerkowskihttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/99Fix generation of AbstractCurry2020-11-17T17:17:23ZMichael HanusFix generation of AbstractCurryThe new frontend generates .acy files which are different (buggy)
compared to the previous version. Type declarations have the following
structure in AbstractCurry (version 2.0), see `AbstractCurry.Types`
in package `abstract-curry`:
...The new frontend generates .acy files which are different (buggy)
compared to the previous version. Type declarations have the following
structure in AbstractCurry (version 2.0), see `AbstractCurry.Types`
in package `abstract-curry`:
data CTypeDecl
= CType QName CVisibility [CTVarIName] [CConsDecl] [QName]
| CTypeSyn QName CVisibility [CTVarIName] CTypeExpr
| CNewType QName CVisibility [CTVarIName] CConsDecl [QName]
deriving (Eq, Show)
Consider the following minimal program:
data List = Empty
PAKCS/KiCS2 version generates the following acy file for this program:
{- AbstractCurry 2.0 -}
CurryProg "T"
["Prelude"]
Nothing
[]
[]
[CType ("T","List") Public [] [CCons [] (CContext []) ("T","Empty") Public []] []]
[]
[]
Unfortunately, the current frontend produces the following acy file:
{- AbstractCurry 2.0 -}
CurryProg "T"
[]
Nothing
[]
[]
[CType ("T","List") Public [] [CCons ("T","Empty") Public []] []]
[]
[]
As a consequence, many important Curry tools (CurryCheck, CurryDoc,
CurryPP) required for a basic Curry system do not work in
the new version!Finn TeegenFinn Teegenhttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/100Prelude is not imported in FCY2020-11-17T18:48:46ZMichael HanusPrelude is not imported in FCYTry the following program:
head (x:_) = x
The Prelude is not imported in the generated FCYTry the following program:
head (x:_) = x
The Prelude is not imported in the generated FCYhttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/102Fix error message for explicitly derived Data2020-11-19T16:25:50ZFredrik WieczerkowskiFix error message for explicitly derived DataExplicitly deriving `Data` currently generates an incorrect span in the error message:
```haskell
data X = X deriving (Data)
```
```
Error:
Instances of type class `Prelude.Data' cannot be derived
|
1 | interface Prelude where...Explicitly deriving `Data` currently generates an incorrect span in the error message:
```haskell
data X = X deriving (Data)
```
```
Error:
Instances of type class `Prelude.Data' cannot be derived
|
1 | interface Prelude where {
| ^^^^^^^^^^^^
```https://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/108Make specialization in dictionary transformation an optional optimization2020-11-23T16:54:00ZFinn TeegenMake specialization in dictionary transformation an optional optimizationThis is very useful for debugging the dictionary transformation.This is very useful for debugging the dictionary transformation.Finn TeegenFinn Teegenhttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/110Allow Data instances for external data types2020-11-25T11:09:14ZFinn TeegenAllow Data instances for external data typesCurrently, the frontend only allows custom data instances in the prelude. It should also allow data instances for external data types in every module. Moreover, the frontend currently does not check whether there is another Data instance...Currently, the frontend only allows custom data instances in the prelude. It should also allow data instances for external data types in every module. Moreover, the frontend currently does not check whether there is another Data instance in the Prelude for normal data types. That way, it is possible to have two Data instances at once for one data type. This issue would be fixed by allowing custom Data instances only for external data types.https://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/73Fix pretty printing of OPTIONS pragma2020-02-12T13:02:23ZFinn TeegenFix pretty printing of OPTIONS pragmaA pragma like `{-# OPTIONS_FRONTEND -ddump-all #-}` is pretty-printed as `{-# OPTIONS _FRONTEND -ddump-all #-}`.A pragma like `{-# OPTIONS_FRONTEND -ddump-all #-}` is pretty-printed as `{-# OPTIONS _FRONTEND -ddump-all #-}`.https://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/111Cleanup frontend targets2020-11-25T11:09:51ZFinn TeegenCleanup frontend targetshttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/112Remove renaming from type syntax check2020-11-26T17:47:36ZFinn TeegenRemove renaming from type syntax checkThe renaming was necessary when locally quantified type variables could be introduced. As this is no longer the case, the renaming is obsolete.The renaming was necessary when locally quantified type variables could be introduced. As this is no longer the case, the renaming is obsolete.https://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/113Frontend crash during parsing2020-11-26T20:50:18ZFinn TeegenFrontend crash during parsingAny error during parsing leads to a crash of the frontend with the error message `pakcs-frontend: Prelude.!!: index too large`.Any error during parsing leads to a crash of the frontend with the error message `pakcs-frontend: Prelude.!!: index too large`.Fredrik WieczerkowskiFredrik Wieczerkowskihttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/114Avoid pattern matching on () for dictionaries2020-11-27T15:29:04ZFinn TeegenAvoid pattern matching on () for dictionariesThe current augmentation introduces `()` arguments on which is pattern matched. This causes additional `case` expressions to be generated. We should avoid that. The same applies for the new method coming with a fix for #109.The current augmentation introduces `()` arguments on which is pattern matched. This causes additional `case` expressions to be generated. We should avoid that. The same applies for the new method coming with a fix for #109.Finn TeegenFinn Teegenhttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/115Remove type synonyms completely in desugaring2020-11-29T19:40:00ZFinn TeegenRemove type synonyms completely in desugaringCurrently, type synonyms remain in data constructor declarations (while they get properly replaced in signatures). Concerning that FC should not contain type synonyms anymore, desugaring should get rid of them.
Note that the dictionary ...Currently, type synonyms remain in data constructor declarations (while they get properly replaced in signatures). Concerning that FC should not contain type synonyms anymore, desugaring should get rid of them.
Note that the dictionary transformation performs this task at the moment. However, it is merely a side effect and does generally not belong in that phase. Moreover, having no type synonyms at all after desugaring simplifies all subsequent phases (including the dictionary transformation that currently has to deal with synonyms).https://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/116Refactor to distinguish Decl and LocalDecl2020-11-29T16:54:52ZFinn TeegenRefactor to distinguish Decl and LocalDeclhttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/117Wrong desugaring of type synonyms2020-11-29T19:40:01ZFinn TeegenWrong desugaring of type synonymsThe program
```
type A _ _ c = c
f = error "" :: A x x y
```
gets desugared to
```
type A _ _ c = c
f = error "" :: x
```
while the local type signature should be `:: y`. This is due to the double occurence of the variable `x` that is...The program
```
type A _ _ c = c
f = error "" :: A x x y
```
gets desugared to
```
type A _ _ c = c
f = error "" :: x
```
while the local type signature should be `:: y`. This is due to the double occurence of the variable `x` that is not handled properly.https://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/118Type class contexts are missing for external functions in AbstractCurry2020-12-08T14:28:25ZFinn TeegenType class contexts are missing for external functions in AbstractCurryFinn TeegenFinn Teegenhttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/119Type class contexts are ignored for external functions2020-12-08T14:28:04ZFinn TeegenType class contexts are ignored for external functionsDue to the fact that type class context in signatures of external functions are completely ignored during type checking, one could write expressions like `id =:= id` without type error.Due to the fact that type class context in signatures of external functions are completely ignored during type checking, one could write expressions like `id =:= id` without type error.https://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/120Add check for empty contexts for external functions2020-12-09T09:23:14ZFinn TeegenAdd check for empty contexts for external functionshttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/121Missing Data context for non-linear as-patterns2020-12-10T13:26:19ZFinn TeegenMissing Data context for non-linear as-patternsConsider the function `f x@(Just _) x = ()`. Its inferred type should be `f :: Data a => Maybe a -> Maybe a -> ()`, however, it is `f :: Maybe a -> Maybe a -> ()`.Consider the function `f x@(Just _) x = ()`. Its inferred type should be `f :: Data a => Maybe a -> Maybe a -> ()`, however, it is `f :: Maybe a -> Maybe a -> ()`.https://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/122Generate aValue using overlapping rules instead of ? operator2020-12-11T14:53:04ZFinn TeegenGenerate aValue using overlapping rules instead of ? operatorFinn TeegenFinn Teegenhttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/123Type-annotated FlatCurry is not generated if it is the only target2020-12-14T11:08:23ZFinn TeegenType-annotated FlatCurry is not generated if it is the only targetFinn TeegenFinn Teegenhttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/124Emit an AST even if errors occur during semantic analysis2021-03-26T00:19:01ZFredrik WieczerkowskiEmit an AST even if errors occur during semantic analysisCurrently, the Curry compiler monad (`CYT` for the transformer variant and `CYM` for the IO-based variant) implements warning messages using a `WriterT` and error messages using an `ExceptT`.
This, however, prevents tools like the Curry...Currently, the Curry compiler monad (`CYT` for the transformer variant and `CYM` for the IO-based variant) implements warning messages using a `WriterT` and error messages using an `ExceptT`.
This, however, prevents tools like the Curry language server from taking advantage of the 'broken' AST, which may still be syntactically correct, e.g. for features like context-aware code completion as the user types.
It would therefore be nice to have at least a `Maybe`-wrapped version of the AST if parsing succeeds, but one of the semantic checks fails.https://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/125Emit a warning for non-fully-initialized records2021-04-21T09:16:35ZFredrik WieczerkowskiEmit a warning for non-fully-initialized recordsNon-initialized record fields make it easy to accidentally introduce nondeterminism. Consider the following Curry example, which emits no warnings or errors:
```haskell
data X = X { n :: Int, m :: Bool }
mkX :: X
mkX = X { n = 3 }
tes...Non-initialized record fields make it easy to accidentally introduce nondeterminism. Consider the following Curry example, which emits no warnings or errors:
```haskell
data X = X { n :: Int, m :: Bool }
mkX :: X
mkX = X { n = 3 }
test :: Bool
test = not $ m mkX -- whoops
```
Since uninitialized fields (like `m` in this case) are interpreted as free variables in Curry, `test` evaluates to `False` and `True` nondeterministically.
Even if this is what the user intends, making it explicit might be better style:
```haskell
data X = X { n :: Int, m :: Bool }
mkX :: X
mkX = X { n = 3, m = m' }
where m' free
test :: Bool
test = not $ m mkX -- whoops
```
It would therefore be nice to have a warning message, perhaps similar to the one that GHC emits:
```
NonFullyInitializedRecord.hs:4:7: warning: [-Wmissing-fields]
• Fields of ‘X’ not initialised:
m :: Int
• In the expression: X {n = 3}
In an equation for ‘mkX’: mkX = X {n = 3}
|
4 | mkX = X { n = 3 }
|
```
If #92 would get integrated at some point, the compiler could potentially generate a quick fix for making the free fields explicit, similar to the example above.https://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/126Add hint to overloading errors2021-04-21T09:24:49ZMichael HanusAdd hint to overloading errorsThe definition
main = snd (x, True) where x free
produces the following error message:
Ambiguous type variable _3
in type Prelude.Data _3 => Prelude.Bool
Since this is difficult to understand for newbies, maybe the front...The definition
main = snd (x, True) where x free
produces the following error message:
Ambiguous type variable _3
in type Prelude.Data _3 => Prelude.Bool
Since this is difficult to understand for newbies, maybe the front end
can add a hint for such cases, i.e., when a type variable is ambiguous
but does not occur in the top-level type expression. E.g.:
Hint: add type annotation to local variable or declarationhttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/127Tuple Constructors in Interface Instance Declarations Cause Illegal Instance ...2021-07-06T09:52:08ZLeif-Erik KrügerTuple Constructors in Interface Instance Declarations Cause Illegal Instance Type ErrorsConsider the following module:
```haskell
module TupleConstructorInstance where
class C a where
methodC :: a Bool Bool
instance C (,) where
methodC = (True, False)
testExp :: (Bool, Bool)
testExp = methodC
```
Compiling this mod...Consider the following module:
```haskell
module TupleConstructorInstance where
class C a where
methodC :: a Bool Bool
instance C (,) where
methodC = (True, False)
testExp :: (Bool, Bool)
testExp = methodC
```
Compiling this module works without problems, but using it interactively in PAKCS causes an `Illegal instance type` error:
```
TupleConstructorInstance> testExp
Tests/.curry/pakcs-3.2.0/TupleConstructorInstance.icurry:8:12-8:14 Error:
Illegal instance type (,)
The instance type must be of the form (T u_1 ... u_n),
where T is not a type synonym and u_1, ..., u_n are
mutually distinct, non-anonymous type variables.
|
8 | instance C (,) {
| ^^^
ERROR occurred during parsing!
```
The cause of this error is the `checkTypeConstructor` function in the interface syntax check (only the first part of it is displayed here):
```haskell
checkTypeConstructor :: SpanInfo -> QualIdent -> ISC TypeExpr
checkTypeConstructor spi tc = do
tyEnv <- getTypeEnv
case qualLookupTypeKind tc tyEnv of
[] | not (isQualified tc) -> return $ VariableType spi $ unqualify tc
| otherwise -> do
report $ errUndefinedType tc
return $ ConstructorType spi tc
```
Unlike its counterpart `checkType` in the type syntax check, `checkTypeConstructor` does not have a special case for tuple constructors. You can see the `isQTupleId tc` guard of the `checkType` function here:
```haskell
checkType :: TypeExpr -> TSCM TypeExpr
checkType c@(ConstructorType spi tc) = do
m <- getModuleIdent
tEnv <- getTypeEnv
case qualLookupTypeKind tc tEnv of
[]
| isQTupleId tc -> return c
| not (isQualified tc) -> return $ VariableType spi $ unqualify tc
| otherwise -> report (errUndefinedType tc) >> return c
```
This missing guard in `checkTypeConstructor` means that the instance type `(,)` is identified as a type variable in the interface syntax check. Type variables are not allowed as instance types however, therefore an `Illegal instance type` error is reported.Leif-Erik KrügerLeif-Erik Krügerhttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/128Tuple Constructors in Interface Instance Declarations Cause Illegal Instance ...2021-07-01T11:25:35ZLeif-Erik KrügerTuple Constructors in Interface Instance Declarations Cause Illegal Instance Type ErrorsConsider the following module:
```haskell
module TupleConstructorInstance where
class C a where
methodC :: a Bool Bool
instance C (,) where
methodC = (True, False)
testExp :: (Bool, Bool)
testExp = methodC
```
Compiling this mod...Consider the following module:
```haskell
module TupleConstructorInstance where
class C a where
methodC :: a Bool Bool
instance C (,) where
methodC = (True, False)
testExp :: (Bool, Bool)
testExp = methodC
```
Compiling this module works without problems, but using it interactively in PAKCS causes an `Illegal instance type` error:
```
TupleConstructorInstance> testExp
Tests/.curry/pakcs-3.2.0/TupleConstructorInstance.icurry:8:12-8:14 Error:
Illegal instance type (,)
The instance type must be of the form (T u_1 ... u_n),
where T is not a type synonym and u_1, ..., u_n are
mutually distinct, non-anonymous type variables.
|
8 | instance C (,) {
| ^^^
ERROR occurred during parsing!
```
The cause of this error is the `checkTypeConstructor` function in the interface syntax check (only the first part of it is displayed here):
```haskell
checkTypeConstructor :: SpanInfo -> QualIdent -> ISC TypeExpr
checkTypeConstructor spi tc = do
tyEnv <- getTypeEnv
case qualLookupTypeKind tc tyEnv of
[] | not (isQualified tc) -> return $ VariableType spi $ unqualify tc
| otherwise -> do
report $ errUndefinedType tc
return $ ConstructorType spi tc
```
Unlike its counterpart `checkType` in the type syntax check, `checkTypeConstructor` does not have a special case for tuple constructors. You can see the `isQTupleId tc` guard of the `checkType` function here:
```haskell
checkType :: TypeExpr -> TSCM TypeExpr
checkType c@(ConstructorType spi tc) = do
m <- getModuleIdent
tEnv <- getTypeEnv
case qualLookupTypeKind tc tEnv of
[]
| isQTupleId tc -> return c
| not (isQualified tc) -> return $ VariableType spi $ unqualify tc
| otherwise -> report (errUndefinedType tc) >> return c
```
This missing guard in `checkTypeConstructor` means that the instance type `(,)` is identified as a type variable in the interface syntax check. Type variables are not allowed as instance types however, therefore an `Illegal instance type` error is reported.Leif-Erik KrügerLeif-Erik Krügerhttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/129Constraints with Type Variables Applied to Multiple Types Cause Illegal Class...2021-07-06T09:51:49ZLeif-Erik KrügerConstraints with Type Variables Applied to Multiple Types Cause Illegal Class Constraint ErrorsThe function
```haskell
f :: Eq (a Bool Bool) => a Bool Bool -> a Bool Bool -> Bool
f = (==)
```
should be accepted by PAKCS, but the following error message is reported:
```
Illegal class constraint Eq (a Bool Bool)
Constrain...The function
```haskell
f :: Eq (a Bool Bool) => a Bool Bool -> a Bool Bool -> Bool
f = (==)
```
should be accepted by PAKCS, but the following error message is reported:
```
Illegal class constraint Eq (a Bool Bool)
Constraints must be of the form C u or C (u t1 ... tn),
where C is a type class, u is a type variable and t1, ..., tn are types.
|
1 | f :: Eq (a Bool Bool) => a Bool Bool -> a Bool Bool -> Bool
| ^^
```
This error is caused by the function `rootType`, which is a subfunction of `checkConstraint`:
```haskell
checkConstraint :: Constraint -> TSCM Constraint
checkConstraint c@(Constraint spi qcls ty) = do
checkClass False qcls
ty' <- checkType ty
unless (isVariableType $ rootType ty') $ report $ errIllegalConstraint c
return $ Constraint spi qcls ty'
where
rootType (ApplyType _ ty' _) = ty'
rootType ty' = ty'
```
`rootType` is not defined recursively and only removes a single `ApplyType`, which means that type variables that are applied to multiple types are not identified as type variables. For example, `a Bool Bool` is represented in the AST by `ApplyType (ApplyType (VariableType "a") (ConstructorType "Bool")) (ConstructorType "Bool")` (simplified), so `rootType` returns `ApplyType (VariableType "a") (ConstructorType "Bool")`, which is not identified as a type variable by `isVariableType`.Leif-Erik KrügerLeif-Erik Krügerhttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/130Class methods that are not in scope can cause internal errors2021-07-06T16:48:42ZLeif-Erik KrügerClass methods that are not in scope can cause internal errorsConsider the following modules:
```haskell
module M where
class C a where
methodC :: a
```
```haskell
module N (C) where
import M
```
```haskell
module O where
import N
f :: C a => a
f = methodC
```
In `O`, `methodC` should not be...Consider the following modules:
```haskell
module M where
class C a where
methodC :: a
```
```haskell
module N (C) where
import M
```
```haskell
module O where
import N
f :: C a => a
f = methodC
```
In `O`, `methodC` should not be in scope and when compiling the module with PAKCS, an appropriate error message should be reported. Instead, we get the following internal error, which basically states that `funType` in the dictionary transformation module has not found `M.methodC` in the value environment:
```
Prelude> :l O
[1 of 4] Skipping Prelude ( /home/leif/pakcs-3.2.0/lib/Prelude.curry, /home/leif/pakcs-3.2.0/lib/.curry/pakcs-3.2.0/Prelude.fcy )
[2 of 4] Compiling M ( M.curry, .curry/pakcs-3.2.0/M.fcy )
[3 of 4] Compiling N ( N.curry, .curry/pakcs-3.2.0/N.fcy )
[4 of 4] Compiling O ( O.curry, .curry/pakcs-3.2.0/O.fcy )
pakcs-frontend: Internal error: Dictionary.funType QualIdent {qidSpanInfo = SpanInfo {srcSpan = Span {file = ".curry/pakcs-3.2.0/N.icurry", start = Position {file = ".curry/pakcs-3.2.0/N.icurry", line = 3, column = 7}, end = Position {file = ".curry/pakcs-3.2.0/N.icurry", line = 3, column = 15}}, srcInfoPoints = []}, qidModule = Just (ModuleIdent {midSpanInfo = SpanInfo {srcSpan = Span {file = ".curry/pakcs-3.2.0/N.icurry", start = Position {file = ".curry/pakcs-3.2.0/N.icurry", line = 3, column = 7}, end = Position {file = ".curry/pakcs-3.2.0/N.icurry", line = 3, column = 8}}, srcInfoPoints = []}, midQualifiers = ["M"]}), qidIdent = Ident {idSpanInfo = SpanInfo {srcSpan = Span {file = ".curry/pakcs-3.2.0/N.icurry", start = Position {file = ".curry/pakcs-3.2.0/N.icurry", line = 4, column = 3}, end = Position {file = ".curry/pakcs-3.2.0/N.icurry", line = 4, column = 9}}, srcInfoPoints = [Span {file = ".curry/pakcs-3.2.0/N.icurry", start = Position {file = ".curry/pakcs-3.2.0/N.icurry", line = 4, column = 3}, end = Position {file = ".curry/pakcs-3.2.0/N.icurry", line = 4, column = 9}}]}, idName = "methodC", idUnique = 0}}
CallStack (from HasCallStack):
error, called at src/Base/Messages.hs:78:21 in curry-frontend-2.0.0-2OM1MZb8aCM4fBMC351o4R:Base.Messages
ERROR occurred during parsing!
```
<br>
Interestingly, if we skip module `N`, but change `M` to export class `C` without `methodC` (as seen in the modified modules below), then `methodC` is in scope in `O`, so `O` compiles without problems. This is probably not intended. At any rate, it is different than the behavior of the GHC, which reports `Variable not in scope` errors for both the unmodified and modified versions of the modules `M`, `N`, and `O`.
```haskell
module M (C) where
class C a where
methodC :: a
```
```haskell
module O where
import M
f :: C a => a
f = methodC
```https://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/131Recursive module imports cause confusing error messages2023-05-26T08:59:58ZLeif-Erik KrügerRecursive module imports cause confusing error messagesConsider the following module `M`:
```haskell
module M where
import M
```
Compiling this module with PAKCS 3.2.0 (or 3.4.1-b6) causes the following error message, which does not point towards the actual error:
```
Error:
Could not...Consider the following module `M`:
```haskell
module M where
import M
```
Compiling this module with PAKCS 3.2.0 (or 3.4.1-b6) causes the following error message, which does not point towards the actual error:
```
Error:
Could not inspect modification time of file
".curry/pakcs-3.2.0/M.icurry"
ERROR occurred during parsing!
```
Interestingly, there seems to be an error message especially for this case in `errCyclicImport` in the `Interfaces` module, but for some reason, the error `errModificationTime` from the `CurryBuilder` module is reported instead.Fredrik WieczerkowskiFredrik Wieczerkowskihttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/132Instances with equivalent heads from different imported modules are not reported2023-05-26T02:35:19ZLeif-Erik KrügerInstances with equivalent heads from different imported modules are not reportedConsider the following modules `M`, `N` and `O`:
```haskell
module M where
instance Eq (a -> b) where
_ == _ = True
```
```haskell
module N where
instance Eq (a -> b) where
_ == _ = False
```
```haskell
module O where
import M
...Consider the following modules `M`, `N` and `O`:
```haskell
module M where
instance Eq (a -> b) where
_ == _ = True
```
```haskell
module N where
instance Eq (a -> b) where
_ == _ = False
```
```haskell
module O where
import M
import N
testExp :: Bool
testExp = not == id
```
The instances defined in `M` and `N` have the same instance head and are both imported in `O`, but when compiling the latter with PAKCS 3.2.0 (or 3.4.1-b6), no error is reported despite this. Instead, the instance from `M` is "overwritten" by the one from `N` and `testExp` evaluates to `False`.
This bug originates from the `Imports` module, where all imported instances are entered into the instance environment without checking them. Here, instances with equivalent heads overwrite each other. To fix the bug, we either must report such instances in this module or use a different kind of instance environment (for example a list of `InstEnv`s) during the first compilation steps and transform it to a regular `InstEnv` while reporting such errors in the instance check.
Another option, which would allow such imports if the instances with equivalent heads are not used, would be to rework the `InstEnv` data type such that multiple instances with equivalent heads from different modules can be stored in it. This seems to be the option used by the GHC, but it would require some changes in many modules working with instances to fully implement it in the Curry frontend.https://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/133Shadowing of imported symbols does not emit a warning2022-11-22T10:19:40ZFredrik WieczerkowskiShadowing of imported symbols does not emit a warningE.g.
```curry
f :: a -> a
f failed = failed
```
should warn about `Prelude.failed` being shadowed (similar to what GHC does when `-Wall` is enabled), but currently does not. Adding a function whose parameter shadows the (locally define...E.g.
```curry
f :: a -> a
f failed = failed
```
should warn about `Prelude.failed` being shadowed (similar to what GHC does when `-Wall` is enabled), but currently does not. Adding a function whose parameter shadows the (locally defined) function `f`, however, does emit a warning:
```curry
g :: a -> a
g f = f
```
```
.../src/Shadow.curry:9:3 Warning:
Shadowing symbol `f', bound at: .../src/Shadow.curry, line 6.1
|
9 | g f = f
| ^
```
Not sure if this is already covered by #62.https://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/134Emit warnings about unused do-bindings2022-03-03T15:17:01ZFredrik WieczerkowskiEmit warnings about unused do-bindingsIt would be nice if unused do-bindings (i.e. non-unit values) such as `getLine` in
```curry
unused :: IO ()
unused = do
getLine
return ()
```
would emit a warning similar to GHC (with `-Wall`):
```
UnusedDo.hs:5:3: warning: [-Wunu...It would be nice if unused do-bindings (i.e. non-unit values) such as `getLine` in
```curry
unused :: IO ()
unused = do
getLine
return ()
```
would emit a warning similar to GHC (with `-Wall`):
```
UnusedDo.hs:5:3: warning: [-Wunused-do-bind]
A do-notation statement discarded a result of type ‘String’
Suppress this warning by saying ‘_ <- getLine’
|
5 | getLine
| ^^^^^^^
```
This would also be a good candidate for a quick fix as proposed in #92.
Related: #62.https://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/135Idea: Allow underscore-prefixed identifiers2022-03-03T15:16:22ZFredrik WieczerkowskiIdea: Allow underscore-prefixed identifiersIn Haskell, prefixing an identifier with an underscore is allowed. E.g. the following snippet compiles in Haskell, but not in Curry:
```curry
_test :: Int
_test = 3
```
```
Anonymous.curry:3:2 Error:
Unexpected token identifier `te...In Haskell, prefixing an identifier with an underscore is allowed. E.g. the following snippet compiles in Haskell, but not in Curry:
```curry
_test :: Int
_test = 3
```
```
Anonymous.curry:3:2 Error:
Unexpected token identifier `test'
|
3 | _test :: Int
| ^
```
Such identifiers could be useful for a variety of reasons:
- In Haskell, a common pattern is to name the implementation of a function (possibly taking additional parameters) `_f` and the exported, public interface function `f`
- In Haskell, underscore-prefixed identifiers can be used to silence warnings about unused parameters. This could be useful if a parameter is explicitly to be marked as unused, but still assigned a name. For example:
```curry
const :: a -> b -> a
const x _y = y
```
would not emit a warning in Haskell. There is an additional challenge that this example shows, however:
**Allowing underscore-prefixed identifiers is a breaking change**, since the current Curry parser reads the function above as
```curry
const x _ y = y
```
(and thus throws a type error). If we were to implement a change that allows such identifiers, e.g. the following snippet would no longer be valid Curry:
```curry
const2 :: a -> b -> c -> a
const2 x _y = x
```
Same goes for the (currently) equivalent spelling
```curry
const2 :: a -> b -> c -> a
const2 x __ = x
```
While such formatting is usually considered unidiomatic, if we were to implement this feature, we should detect such cases and emit a descriptive error message along with a fix to rewrite the function as:
```curry
const2 x _ _ = x
```https://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/136Idea: Support shebangs in Curry source files2022-06-17T18:41:44ZFredrik WieczerkowskiIdea: Support shebangs in Curry source filesGHC allows a shebang line (starting with `#!`) to appear at the beginning of a Haskell source file, making it convenient to write directly executable scripts in Haskell. For example, writing the following is allowed:
```haskell
#!/usr/b...GHC allows a shebang line (starting with `#!`) to appear at the beginning of a Haskell source file, making it convenient to write directly executable scripts in Haskell. For example, writing the following is allowed:
```haskell
#!/usr/bin/env runhaskell
main = putStrLn "Hello world!"
```
For a hypothetical `runcurry` (or `runpakcs`/`runkics2`) tool it would be nice if the Curry frontend could similarly allow the user to write a single line starting with `#!` at the beginning of a source file (and just ignore it).https://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/137Make option `--extended` default2023-02-06T14:08:59ZMichael HanusMake option `--extended` defaultSince all actual Curry systems compiles programs with option `--extended`, this should be the default as many Curry programs use these extensions. This has also the advantage that the Curry Language Server does not report errors on such ...Since all actual Curry systems compiles programs with option `--extended`, this should be the default as many Curry programs use these extensions. This has also the advantage that the Curry Language Server does not report errors on such programs.
Thus, the options `FunctionalPatterns` and `AnonFreeVars` should be always set and new options `NoFunctionalPatterns` and `NoAnonFreeVars` should be added to enable the old behavior. For compatibility reasons, the option `--extended` should still be allowed.Fredrik WieczerkowskiFredrik Wieczerkowskihttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/138Default all type variables2023-07-26T16:17:34ZKai ProttDefault all type variablesCurrently not all type variables occurring in a flat curry expression are bound in the type of the surrounding function declaration.
Consider the following example:
```haskell
test = length []
```
Here, both `length` and `[]` will be ty...Currently not all type variables occurring in a flat curry expression are bound in the type of the surrounding function declaration.
Consider the following example:
```haskell
test = length []
```
Here, both `length` and `[]` will be typed with a free type variable.
While the resulting FlatCurry Code is certainly correct, all typed back ends need to default these type variables.
If I remember correctly, KiCS2 does not even do this in all required cases, e.g. when the type variable has a kind different than `Type`/`*`.
We'd like these type variables to be defaulted in the frontend directly.
Currently our idea is to create a new transformation phase on the IL where the AST is traversed and a new data type is created for each unique kind that occurrs in a type variable that needs to be defaulted.
Additionally, each type variable is replaced with the respective type constructor that has been generated.
Note that the generated data types need no constructors. Although it is not possible for a user to write a data type with arbitrary kind but without constructors (all type variables will be phantom and defaulted to `*`), we can generate these data types internally.
I am not sure if and when the frontend adds a dummy constructor to external data types or a data type without constructors, but this should be kept in mind.
Also, all environments should be updated with the new data types and they should not be exported to keep the transformation and compilation local and without name clashes.
@fte @mh @fwcd: Anyone got a better Idea?
@fwcd Do you have time to implement this? Should not be too complicated.
Note that in GHC with `-XPolyKinds`, Just two data types are sufficient for all possible kinds.
```haskell
data Zero
data One (a :: k)
```
In Curry we need:
```haskell
data Zero
data One (a :: *)
data Two (a :: *) (b :: *)
data OneTwo (a :: * -> *) (b :: *)
...
```https://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/139No Prelude import for lists and apply2023-11-16T13:41:35ZMichael HanusNo Prelude import for lists and applyThe FlatCurry of the following program use lists and the operation `Prelude.apply`:
```
f = []
ap g x = g x
```
However, the Prelude does not occur in the import list.The FlatCurry of the following program use lists and the operation `Prelude.apply`:
```
f = []
ap g x = g x
```
However, the Prelude does not occur in the import list.Kai ProttKai Protthttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/140Add uppercase/lowercase warnings in default mode2024-03-26T11:11:26ZMichael HanusAdd uppercase/lowercase warnings in default modeUppercase/lowercase warnings that are currently generated in the case mode `haskell` should be generated in the default case mode.
These warnings could be turned off by, e.g., `-W no-haskell-case`.Uppercase/lowercase warnings that are currently generated in the case mode `haskell` should be generated in the default case mode.
These warnings could be turned off by, e.g., `-W no-haskell-case`.Fredrik WieczerkowskiFredrik Wieczerkowskihttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/141Turn case warnings into errors2024-03-26T11:11:27ZMichael HanusTurn case warnings into errorsIn restricted case modes, like `haskell`, warnings are generated for illegal uppercase/lowercases.
These warning should be turned into errors in order to really enforce the case mode.In restricted case modes, like `haskell`, warnings are generated for illegal uppercase/lowercases.
These warning should be turned into errors in order to really enforce the case mode.Fredrik WieczerkowskiFredrik Wieczerkowskihttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/142Display diffs in failing tests2024-02-15T20:57:52ZFredrik WieczerkowskiDisplay diffs in failing testsIt would be cool if failing tests, instead of just noting the missing/unexpected message(s) could display a, potentially colored, diff between the actual and the expected message.
Here's a good example of a library that does this well: ...It would be cool if failing tests, instead of just noting the missing/unexpected message(s) could display a, potentially colored, diff between the actual and the expected message.
Here's a good example of a library that does this well: https://github.com/rust-pretty-assertions/rust-pretty-assertionshttps://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/143Add support for line pragmas2024-02-15T22:09:21ZFredrik WieczerkowskiAdd support for line pragmasGHC, like the C preprocessor, has [support for line pragmas](https://downloads.haskell.org/~ghc/7.0.3/docs/html/users_guide/pragmas.html#line-pragma), which let the user alter the line number and filename in warnings and errors:
```hask...GHC, like the C preprocessor, has [support for line pragmas](https://downloads.haskell.org/~ghc/7.0.3/docs/html/users_guide/pragmas.html#line-pragma), which let the user alter the line number and filename in warnings and errors:
```haskell
{-# LINE 82 "Foo.hs" #-}
f :: Int
f = "abc"
```
```
[1 of 2] Compiling Main ( LinePragma.hs, LinePragma.o )
Foo.hs:83:5: error: [GHC-83865]
• Couldn't match type ‘[Char]’ with ‘Int’
Expected: Int
Actual: String
• In the expression: "abc"
In an equation for ‘f’: f = "abc"
```
For us these pragmas would be primarily of interest in the automatically generated Curry interfaces (`.icurry`) where they could be used to refer to the original source locations. This in turn would be nice to have in the language server, which could accurately map definitions to their original locations in source code, even if the Curry compiler uses a cached interface file.https://git.ps.informatik.uni-kiel.de/curry/curry-frontend/-/issues/144-Werror is not respected in OPTIONS_FRONTEND pragmas2024-03-28T01:40:45ZFredrik Wieczerkowski-Werror is not respected in OPTIONS_FRONTEND pragmasPresumably this is because the option is applied at the very top-level where only command-line options are available. Perhaps we could make this work on a module-level, by making sure messages get correctly emitted as warning/error as th...Presumably this is because the option is applied at the very top-level where only command-line options are available. Perhaps we could make this work on a module-level, by making sure messages get correctly emitted as warning/error as they are produced?