cursorless icon indicating copy to clipboard operation
cursorless copied to clipboard

Adds support for the Haskell programming language

Open wenkokke opened this issue 1 year ago • 8 comments

Adds support for the Haskell programming language.

Roadmap

  • [ ] argumentOrParameter:
    • [x] argument.actual
    • [ ] argument.actual.iteration Blocked on one of:
      • #557
      • #2177
    • [x] argument.formal
    • [x] argument.formal.iteration
  • [x] anonymousFunction
  • [ ] branch
    • [x] branch.match
    • [x] branch.match.iteration
    • [ ] branch.if
    • [ ] branch.if.iteration
    • [ ] branch.guard
    • [ ] branch.guard.iteration
    • [ ] branch.ternary
  • [ ] collectionItem
  • [ ] collectionKey
    • [ ] key.mapPair
    • [ ] key.mapPair.iteration
  • [ ] comment
    • [ ] comment.line
    • [ ] comment.block
  • [ ] functionCall
    • [x] functionCall
    • [ ] functionCall.constructor
  • [ ] functionCallee
    • [x] functionCallee
    • [ ] functionCallee.constructor
  • [x] functionName
  • [ ] ifStatement
  • [x] list
  • [ ] map
  • [ ] name
    • [ ] name.assignment
    • [ ] name.assignment.pattern
    • [x] name.function
    • [ ] name.class
    • [ ] name.field
  • [ ] namedFunction
    • [x] namedFunction
    • [ ] namedFunction.method
  • [ ] statement
    • [ ] statement
    • [ ] statement.iteration.document
    • [ ] statement.iteration.block
  • [x] string
  • [ ] type
    • [ ] class
    • [ ] class.instance
    • [ ] className
    • [ ] type.adt
    • [ ] type.alias
    • [ ] type.annotation
    • [ ] type.constraint
    • [ ] type.dataFamily
    • [ ] type.dataInstance
    • [ ] type.field
    • [ ] type.foreignExport
    • [ ] type.foreignImport
    • [ ] type.function
    • [ ] type.gadt
    • [ ] type.newtype
    • [ ] type.typeFamily
    • [ ] type.typeInstance
  • [ ] value
    • [ ] value.assignment
    • [ ] value.field
    • [ ] value.mapPair
    • [ ] value.mapPair.iteration
    • [ ] value.return
  • [ ] condition
    • [ ] condition.if
    • [ ] condition.ternary
    • [ ] condition.match

Warning

This is work in progress. In the early stages, I'll be messy.

  • The commits will be uninformative.
  • The branch may receive force pushes at any point!

Discussion and RFCs

See #2186.


Haskell Node Types

  • adt
  • all_names
  • alt
  • alts
  • annotated_type_variable
  • bind_pattern
  • calling_convention
  • char
  • class
  • class_body
  • class_head
  • class_name
  • comma
  • comment
  • con_list
  • con_tuple
  • con_unit
  • constraint
  • constructor
  • constructor_operator
  • constructors
  • context
  • cpp
  • data_constructor
  • data_constructor_infix
  • data_constructor_record
  • data_family
  • data_instance
  • decl_tyfam_sig
  • decl_type
  • decls
  • default_declaration
  • default_signature
  • deriving
  • deriving_declaration
  • deriving_strategy
  • do_module
  • empty_file
  • equation
  • exp_apply
  • exp_arithmetic_sequence
  • exp_case
  • exp_cond
  • exp_do
  • exp_field
  • exp_if_guard
  • exp_in
  • exp_infix
  • exp_lambda
  • exp_lambda_case
  • exp_let
  • exp_let_in
  • exp_list
  • exp_list_comprehension
  • exp_literal
  • exp_name
  • exp_negation
  • exp_parens
  • exp_record
  • exp_section_left
  • exp_section_right
  • exp_sum_empty
  • exp_th_quoted_name
  • exp_tuple
  • exp_type_application
  • exp_unboxed_sum
  • exp_unboxed_tuple
  • expent
  • export
  • export_names
  • exports
  • field
  • fixity
  • float
  • forall
  • foreign_export
  • foreign_import
  • fun
  • function
  • fundep
  • fundeps
  • gadt_constructor
  • gdpat
  • guard
  • guard_equation
  • guards
  • haskell
  • head
  • impent
  • implicit_param
  • implicit_parid
  • import
  • import_con_names
  • import_item
  • import_list
  • import_package
  • infix
  • inst_datainst
  • inst_tyinst
  • instance
  • instance_head
  • integer
  • label
  • let
  • modifier
  • module
  • namespace
  • newtype
  • newtype_constructor
  • operator
  • pat_apply
  • pat_as
  • pat_field
  • pat_fields
  • pat_infix
  • pat_irrefutable
  • pat_list
  • pat_literal
  • pat_name
  • pat_negation
  • pat_parens
  • pat_record
  • pat_strict
  • pat_tuple
  • pat_typed
  • pat_unboxed_tuple
  • pat_view
  • pat_wildcard
  • pattern
  • pattern_guard
  • pattern_synonym
  • patterns
  • pragma
  • promoted
  • qual
  • qualified_constructor
  • qualified_constructor_operator
  • qualified_module
  • qualified_operator
  • qualified_type
  • qualified_type_operator
  • qualified_variable
  • quantifiers
  • quasiquote
  • quasiquote_bar
  • quasiquote_body
  • quasiquote_start
  • quoter
  • rec
  • record_fields
  • role_annotation
  • safety
  • signature
  • splice
  • stmt
  • strict_type
  • string
  • ticked
  • top_splice
  • transform
  • tycon_arrow
  • type
  • type_alias
  • type_apply
  • type_family
  • type_infix
  • type_instance
  • type_list
  • type_literal
  • type_name
  • type_operator
  • type_parens
  • type_role
  • type_star
  • type_tuple
  • type_unboxed_sum
  • type_unboxed_tuple
  • type_variable
  • variable
  • varop
  • via
  • where
  • wildcard

wenkokke avatar Jan 17 '24 12:01 wenkokke

-- RFC: What should `argumentOrParameter` match in the following case?
fst :: (a, b) -> a
fst tup@(x, y) = x
--  ^^^^^^^^^^     <- 1️⃣ the whole pattern
--  ^^^            <- 2️⃣ only the names of whole arguments (may not be given)
--  ^^^  ^  ^      <- 3️⃣ all names in the left-hand side of the function

I would expect x and y to match here. What is the case for the other ones?

pokey avatar Jan 18 '24 14:01 pokey

-- RFC: What should "branch" match?
foo = bar
  where
    bar = 1
--   1️⃣ `foo = bar` and `bar = 1`
--   2️⃣ `foo = bar where bar = 1`
--   3️⃣ `foo = bar where bar = 1` and `bar = 1`

what makes any of them a "branch"?

pokey avatar Jan 18 '24 14:01 pokey

-- RFC: What should `argumentOrParameter` match in the following case?
fst :: (a, b) -> a
fst tup@(x, y) = x
--  ^^^^^^^^^^     <- 1️⃣ the whole pattern
--  ^^^            <- 2️⃣ only the names of whole arguments (may not be given)
--  ^^^  ^  ^      <- 3️⃣ all names in the left-hand side of the function

I would expect x and y to match here. What is the case for the other ones?

  • tup is the name of the first argument
  • the whole pattern is the structure of the whole first argument
  • x and y aren't the arguments to the function, but the first and second fields of the tuple
tup = (1, 2)

assert (fst tup == 1)

wenkokke avatar Jan 18 '24 14:01 wenkokke

-- RFC: What should "branch" match?
foo = bar
  where
    bar = 1
--   1️⃣ `foo = bar` and `bar = 1`
--   2️⃣ `foo = bar where bar = 1`
--   3️⃣ `foo = bar where bar = 1` and `bar = 1`

what makes any of them a "branch"?

all top-level defintions are branches, and it'd be odd to exclude single-branch branching constructs, e.g., having "branch" not match the branch in an if statement without an else

not :: Bool -> Bool
not True = False
not False = True

that's equivalent to

not :: Bool -> Bool
not x = case x of
  True -> False
  False -> True

and equivalent to

not :: Bool -> Bool
not x = if x the False else True

wenkokke avatar Jan 18 '24 14:01 wenkokke

shall we make a haskell discussion so we can use threading? all the quoting is quickly going to become a headache 😅

pokey avatar Jan 18 '24 15:01 pokey

note: this PR is semi-blocked on https://github.com/tree-sitter/tree-sitter-haskell/issues/111, which causes the parse tree to sometimes be wrong. For example see name.function34. If run individually, it is correct, if run as part of the whole suite, we get the wrong parse tree.

We could try to come up with a workaround if necessary, but for now we're hoping the issue gets fixed soon

pokey avatar Jan 25 '24 10:01 pokey

note: this PR is semi-blocked on https://github.com/tree-sitter/tree-sitter-haskell/issues/111, which causes the parse tree to sometimes be wrong. For example see name.function34. If run individually, it is correct, if run as part of the whole suite, we get the wrong parse tree.

We could try to come up with a workaround if necessary, but for now we're hoping the issue gets fixed soon

@pokey Would you prefer we (1) move on with incorrect tests, (2) add a workaround which reinstantiates the parser between every run, or (3) fork and temporarily patch tree-sitter-haskell?

wenkokke avatar Feb 21 '24 12:02 wenkokke

Note: This PR is currently blocked on the ongoing rewrite of the Haskell grammar (see #120).

wenkokke avatar Apr 21 '24 13:04 wenkokke

Note: This PR is currently blocked on the ongoing rewrite of the Haskell grammar (see #120).

Just wanted to circle back to this --- it looks like that rewrite of the Haskell grammar has been merged in. But not trying to rush you or anything like that, obviously.

ym-han avatar Jul 05 '25 16:07 ym-han

Note: This PR is currently blocked on the ongoing rewrite of the Haskell grammar (see #120).

Just wanted to circle back to this --- it looks like that rewrite of the Haskell grammar has been merged in. But not trying to rush you or anything like that, obviously.

It was, but it took a very long time and I got distracted with other things. Feel free to pick this up.

wenkokke avatar Jul 06 '25 00:07 wenkokke

Note: This PR is currently blocked on the ongoing rewrite of the Haskell grammar (see #120).

Just wanted to circle back to this --- it looks like that rewrite of the Haskell grammar has been merged in. But not trying to rush you or anything like that, obviously.

It was, but it took a very long time and I got distracted with other things. Feel free to pick this up.

Got it, that makes sense! I probably won't be able to get to this super soon myself, but I'll at least try to look at it sometime in the next 3 months.

ym-han avatar Jul 10 '25 07:07 ym-han