const { parens, braces, brackets, prefix_at, sep1, sep2, unboxed_tuple_full, unboxed_sum_full, forall, layout, layout_single, optional_where, } = require('./util.js') module.exports = { // ------------------------------------------------------------------------ // type parameters // ------------------------------------------------------------------------ _inferred_tyvar: $ => braces($, $._ktype_param), _type_param_parens: $ => parens($, $._ktype_param), _type_param_wildcard: _ => '_', _type_param_annotated: $ => prec('annotated', seq($.type_param, $._kind_annotation)), _type_param_invisible: $ => prefix_at($, field('bind', $.type_param)), /** * This is a supertype. */ type_param: $ => choice( alias($._type_param_wildcard, $.wildcard), alias($._type_param_invisible, $.invisible), alias($._type_param_parens, $.parens), field('bind', $.variable), ), _ktype_param: $ => choice( $.type_param, alias($._type_param_annotated, $.annotated), ), type_params: $ => repeat1(prec('patterns', $.type_param)), quantified_variables: $ => repeat1(choice($.type_param, alias($._inferred_tyvar, $.inferred))), // ------------------------------------------------------------------------ // tuples and parens // ------------------------------------------------------------------------ _type_parens: $ => parens($, field('type', $._ktype)), _type_tuple_elems: $ => sep2(',', field('element', $._ktype)), /** * Tuple types must either be saturated or empty, sections aren't legal. * We could be lenient here, but it seems useful to have a different node name for the prefix variant. */ _type_tuple: $ => parens($, $._type_tuple_elems), _type_unboxed_tuple: $ => unboxed_tuple_full($, $._ktype), _type_unboxed_sum: $ => unboxed_sum_full($, $._ktype), _type_list: $ => brackets($, sep1(',', field('element', $._ktype))), // ------------------------------------------------------------------------ // names etc // ------------------------------------------------------------------------ _type_promoted: $ => seq( '\'', choice( alias($._plist, $.empty_list), alias($._type_tuple, $.tuple), alias($._type_list, $.list), $.prefix_tuple, $.unit, ), ), _type_name: $ => choice( $.variable, $._promoted_tycons, prec('type-name', $._tycons), ), _type_star: _ => choice('*', '★'), _type_wildcard: _ => '_', // ------------------------------------------------------------------------ // application // ------------------------------------------------------------------------ _at_type: $ => prefix_at($, field('type', $.type)), _type_apply_arg: $ => choice($.type, alias($._at_type, $.kind_application)), /** * Type application, as in `Either e (Int, Text)` or `TypeRep @Int`. */ _type_apply: $ => prec.left('apply', seq( field('constructor', $.type), field('argument', $._type_apply_arg), )), // ------------------------------------------------------------------------ // infix // ------------------------------------------------------------------------ _type_infix: $ => prec.right('infix', seq( field('left_operand', $.type), field('operator', $._tyops), field('right_operand', $.type), )), // ------------------------------------------------------------------------ // unquantified type // ------------------------------------------------------------------------ /** * This is a supertype. */ type: $ => choice( $._type_name, alias($._type_star, $.star), alias($._type_wildcard, $.wildcard), alias($._type_parens, $.parens), alias($._type_promoted, $.promoted), alias($._type_list, $.list), alias($._plist, $.prefix_list), alias($._type_unboxed_tuple, $.unboxed_tuple), alias($._type_unboxed_sum, $.unboxed_sum), alias($._type_tuple, $.tuple), alias($._type_infix, $.infix), alias($._type_apply, $.apply), $._universal, ), // ------------------------------------------------------------------------ // forall // ------------------------------------------------------------------------ _forall_keyword: _ => choice('forall', '∀'), _forall_body: $ => seq( field('quantifier', $._forall_keyword), optional(field('variables', $.quantified_variables)), ), forall: $ => prec('qtype-single', seq( $._forall_body, '.', )), forall_required: $ => prec('qtype-single', seq( $._forall_body, $._arrow, )), _forall: $ => choice( $.forall, $.forall_required, ), _qtype_forall: $ => prec.right('qtype-curried', seq( $._forall_body, '.', field('type', $.quantified_type), )), _qtype_forall_required: $ => prec.right('qtype-curried', seq( $._forall_body, $._arrow, field('type', $.quantified_type), )), // ------------------------------------------------------------------------ // function // ------------------------------------------------------------------------ _fun_arrow: $ => seq( optional($._phantom_arrow), field('arrow', $._arrow), ), modifier: $ => prec('prefix', seq($._prefix_percent, $.type)), _linear_fun_arrow: $ => choice( seq( field('multiplicity', $.modifier), $._fun_arrow, ), seq( optional($._phantom_arrow), field('arrow', $._linear_arrow), ), ), /** * These also allow tight infix because unpack pragmas can precede them without space. * Technically pragmas aren't considered for tight infix, but it's simpler to do it this way than to track that in the * scanner. */ strict_field: $ => prec('prefix', seq($._any_prefix_bang, field('type', $.type))), lazy_field: $ => prec('prefix', seq($._any_prefix_tilde, field('type', $.type))), _parameter_type: $ => field('parameter', choice($.strict_field, $.lazy_field, $.quantified_type)), /** * We allow strict and lazy field types in function types so that GADTs don't need a separate rule tree. */ _qtype_function: $ => prec.right(seq( $._parameter_type, $._fun_arrow, field('result', $.quantified_type), )), _qtype_linear_function: $ => prec.right(seq( $._parameter_type, $._linear_fun_arrow, field('result', $.quantified_type), )), // ------------------------------------------------------------------------ // context // ------------------------------------------------------------------------ _qtype_context: $ => prec.right('qtype-curried', seq( $._context_inline, field('type', $.quantified_type), )), // ------------------------------------------------------------------------ // top level // ------------------------------------------------------------------------ /** * This is a supertype. */ quantified_type: $ => choice( alias($._qtype_function, $.function), alias($._qtype_linear_function, $.linear_function), alias($._qtype_forall, $.forall), alias($._qtype_forall_required, $.forall_required), alias($._qtype_context, $.context), $.implicit_parameter, prec.right($.type), ), _type_annotation: $ => seq( $._colon2, field('type', $.quantified_type), ), _kind_annotation: $ => seq( $._colon2, field('kind', $.quantified_type), ), _type_signature: $ => prec.right('annotated', seq( field('type', $.quantified_type), $._kind_annotation, )), _ktype: $ => choice( alias($._type_signature, $.signature), $.quantified_type, ), // ------------------------------------------------------------------------ // type head // ------------------------------------------------------------------------ _type_head_name: $ => field('name', choice( $._tycon, $.unit, alias($._plist, $.prefix_list), )), _type_head_parens: $ => parens( $, choice( $._type_head, $._type_head_params, ), ), _type_head_params: $ => choice( $._type_head_name, alias($._type_head_parens, $.parens), ), _type_head_infix: $ => prec('infix', seq( field('left_operand', $.type_param), field('operator', $._tyconops), field('right_operand', $.type_param), )), /** * A type head introduces the name and parameters in the declaration of a data type/family, type synonym/family, or * class. * * It can be in prefix or infix form: * * > A a b * > a +++ b * * Parameters can be visible or invisible, the latter marked by a prefix `@`. * They can be plain or parenthesized variable names, the latter with an optional kind signature. * They can be wildcards. * * Examples: `a`, `@a`, `(a :: Type)`, `@(_ :: Type -> Type)` * * The rules are slightly relaxed compared to GHC. */ _type_head: $ => choice( seq($._type_head_params, optional(field('patterns', $.type_params))), alias($._type_head_infix, $.infix), ), // ------------------------------------------------------------------------ // type instance head // ------------------------------------------------------------------------ _type_instance_head_parens: $ => parens( $, choice( $._type_instance_head, $._type_instance_head_params, ), optional($._kind_annotation), ), _type_instance_head_params: $ => choice( field('name', $._tycons), alias($._type_instance_head_parens, $.parens), ), type_patterns: $ => repeat1(prec('patterns', $._type_apply_arg)), /** * The equivalent of a type head, for type instances, which can contain full type patterns rather than just variable * binders. */ _type_instance_head: $ => choice( seq($._type_instance_head_params, optional(field('patterns', $.type_patterns))), seq($._cond_infix, alias($._type_infix, $.infix)), ), // ------------------------------------------------------------------------ // type decl // ------------------------------------------------------------------------ type_synomym: $ => seq( 'type', $._type_head, '=', field('type', $._ktype), ), kind_signature: $ => seq( 'type', $._type_head, $._kind_annotation, ), // ------------------------------------------------------------------------ // type instance // ------------------------------------------------------------------------ _type_instance_common: $ => seq( $._type_instance_head, '=', $.quantified_type, ), _type_instance: $ => seq( forall($), $._type_instance_common, ), type_instance: $ => seq( 'type', 'instance', $._type_instance, ), // ------------------------------------------------------------------------ // type family // ------------------------------------------------------------------------ type_family_result: $ => seq('=', field('result', $.quantified_type)), type_family_injectivity: $ => seq( $._bar, field('result', $.variable), $._arrow, field('determined', repeat1($.variable)), ), _tyfam_inj: $ => seq( $.type_family_result, optional($.type_family_injectivity), ), _tyfam: $ => seq( $._type_head, optional(choice($._kind_annotation, $._tyfam_inj)), ), _tyfam_equations: $ => layout($, field('equation', alias($._type_instance, $.equation))), /** * This syntax is valid in `.hs-boot` files. */ abstract_family: $ => layout_single($, '..'), type_family: $ => seq( 'type', 'family', $._tyfam, optional_where($, field('closed_family', choice( alias($._tyfam_equations, $.equations), $.abstract_family, ))), ), // ------------------------------------------------------------------------ // role // ------------------------------------------------------------------------ type_role: _ => choice( 'representational', 'nominal', 'phantom', '_', ), role_annotation: $ => seq( 'type', 'role', field('type', $._tycons), repeat1(field('role', $.type_role)), ) }