Skip to content

Haskell: define without argument produces incorrect AST #560

@Commelina

Description

@Commelina

Reproduce

Consider the following test.cf file:

OpEq. Op ::= "=" ;
opEq. Op ::= "~" ;

define opEq = OpEq ;

Run bnfc --haskell -d -m test.cf && make:

[1 of 7] Compiling Test.Abs         ( Test/Abs.hs, Test/Abs.o )
Test/Abs.hs:13:8: error: [GHC-71614]
    A lambda requires at least one parameter
   |
13 | opEq = \ -> OpEq
   |        ^^^^^^^^^

Motivation

Defining labels without argument can be useful when supporting both ASCII and Unicode keywords. For example, consider the following example:

entrypoints Exp ;

EInt. Exp1 ::= Integer ;
EEq.  Exp  ::= Exp1 EqOp Exp1 ;
coercions Exp 1 ;

OpEq.  EqOp ::= "==" ;
OpNEq. EqOp ::= "/=" ;

Now we would like to also support operators and . Of course we can make it by defining tokens:

OpEq.  EqOp ::= TokEq  ;
OpNEq. EqOp ::= TokNEq ;

token TokEq  ({"=="} | '≡') ;
token TokNEq ({"/="} | '≠') ;

But we will have to do an unnecessary matching on TokEq and TokNEq. With define, we can write something like:

OpEq.  EqOp ::= "==" ;
OpNEq. EqOp ::= "/=" ;

opEqUnicode. EqOp ::= "≡"  ;
define opEqUnicode = OpEq  ;

opNEqUnicode. EqOp ::= "≠"   ;
define opNEqUnicode = OpNEq  ;

And the original AST remains the same.

Note

This example works correctly on other backends.

Currently, the Haskell and Haskell-GADT backends always generate a \ and -> for define rules, even there is no argument. (As a coincidence, it works with --functor because there is an extra argument for position.)

Thanks @loki259 for inspiration.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions