re-engineering overloading and rebindable syntax

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

re-engineering overloading and rebindable syntax

Richard Eisenberg-5
Hi devs,

I've recently discovered the `overloaded` package, which allows us to do very clever things around overloading in a source plugin. In my over-excitement, I wondered about removing GHC's capability to do overloading and rebindable syntax, leaving those features to be implemented by source plugins. To first approximation, this would work well. But there are many drawbacks: poorer error messages, worries around the trustworthiness of non-GHC source plugins, cross compilation, etc. The idea is not viable right now.

Yet: I wonder if we couldn't take the general idea of doing this as source plugins, without actually implementing it that way. Currently, there is a good deal of code scattered throughout GHC to deal with overloaded constructs (numbers, strings, lists) and rebindable syntax. These make their presence known in a number of places in HsExpr and friends, and various machinations in the renamer and type-checker are needed to deal with them. The type-checker for rebindable syntax is buggy (#14963 and friends); the fix will involve likely *more* code devoted to rebindable syntax (albeit simpler code than what we have today).

If, say, the renamer implemented all overloading and rebindable syntax just by a straightforward syntactic transformation, this would all be much simpler. (Actually, it could also be done in the parser, but I think the renamer is a better home.)

Pros:
 - much, much simpler implementation
 - localized implementation: nothing in the type checker at all nor in HsSyn

Con:
 - worse error messages, which would now refer to the desugared code instead of the user-written code.

I can't think of any other downside.

How can we mitigate this? By expanding the possibilities of a SrcSpan. A SrcSpan is really a description of the provenance of a piece of AST. Right now, it considers two possibilities: that the code came from a specific stretch of rows and columns in an input file, or that the code came from elsewhere. Instead, we can expand (and perhaps rename) SrcSpan to include more possibilities. In support of my idea above, we could now have a SrcSpan that says some AST came from overloading. Such code is suppressed by default when pretty-printing. Thus, `fromString "blah"` could render as just `"blah"` (what the user wrote), if fromString was inserted by the translation pass described above. We can have a separate new SrcSpan that says that AST was written by translation from some original AST. That way, `ifThenElse a b c` can be printed as `if a then b else c`, if the former were translated from the latter. Though it's beyond my use-case above, we can also imagine a new SrcSpans that refer to a Template Haskell splice or a quasiquote.

What do we think? Is this a worthwhile direction of travel? I think the end result would be both a cleaner implementation of overloading and rebindable syntax *and* more informative and useful source-code provenances.

Richard
_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

RE: re-engineering overloading and rebindable syntax

GHC - devs mailing list
Sounds attractive.  By all means open a ticket, giving details.  I'm hazy about those details.  I think you are implying that every single piece of rebindable syntax can be typechecked by instead typechecking some (invisible) function application. Including when you are not using rebindable syntax: just use a built-in function.  

I think that's the way rebindable syntax mostly works today, but I'm not 100% sure that the vanilla (no -XRebindableSyntax) case is always done that way.   One way to get at this would be to write a table of all the cases where rebindable syntax is used, and what the equivalent function application or typing judgement is.  That would be helpful regardless!

Examples of where the error message gets worse, and why, would help to focus the conversation.

Simon

|  -----Original Message-----
|  From: ghc-devs <[hidden email]> On Behalf Of Richard
|  Eisenberg
|  Sent: 05 December 2019 09:54
|  To: Simon Peyton Jones via ghc-devs <[hidden email]>
|  Subject: re-engineering overloading and rebindable syntax
|  
|  Hi devs,
|  
|  I've recently discovered the `overloaded` package, which allows us to do
|  very clever things around overloading in a source plugin. In my over-
|  excitement, I wondered about removing GHC's capability to do overloading
|  and rebindable syntax, leaving those features to be implemented by source
|  plugins. To first approximation, this would work well. But there are many
|  drawbacks: poorer error messages, worries around the trustworthiness of
|  non-GHC source plugins, cross compilation, etc. The idea is not viable
|  right now.
|  
|  Yet: I wonder if we couldn't take the general idea of doing this as source
|  plugins, without actually implementing it that way. Currently, there is a
|  good deal of code scattered throughout GHC to deal with overloaded
|  constructs (numbers, strings, lists) and rebindable syntax. These make
|  their presence known in a number of places in HsExpr and friends, and
|  various machinations in the renamer and type-checker are needed to deal
|  with them. The type-checker for rebindable syntax is buggy (#14963 and
|  friends); the fix will involve likely *more* code devoted to rebindable
|  syntax (albeit simpler code than what we have today).
|  
|  If, say, the renamer implemented all overloading and rebindable syntax
|  just by a straightforward syntactic transformation, this would all be much
|  simpler. (Actually, it could also be done in the parser, but I think the
|  renamer is a better home.)
|  
|  Pros:
|   - much, much simpler implementation
|   - localized implementation: nothing in the type checker at all nor in
|  HsSyn
|  
|  Con:
|   - worse error messages, which would now refer to the desugared code
|  instead of the user-written code.
|  
|  I can't think of any other downside.
|  
|  How can we mitigate this? By expanding the possibilities of a SrcSpan. A
|  SrcSpan is really a description of the provenance of a piece of AST. Right
|  now, it considers two possibilities: that the code came from a specific
|  stretch of rows and columns in an input file, or that the code came from
|  elsewhere. Instead, we can expand (and perhaps rename) SrcSpan to include
|  more possibilities. In support of my idea above, we could now have a
|  SrcSpan that says some AST came from overloading. Such code is suppressed
|  by default when pretty-printing. Thus, `fromString "blah"` could render as
|  just `"blah"` (what the user wrote), if fromString was inserted by the
|  translation pass described above. We can have a separate new SrcSpan that
|  says that AST was written by translation from some original AST. That way,
|  `ifThenElse a b c` can be printed as `if a then b else c`, if the former
|  were translated from the latter. Though it's beyond my use-case above, we
|  can also imagine a new SrcSpans that refer to a Template Haskell splice or
|  a quasiquote.
|  
|  What do we think? Is this a worthwhile direction of travel? I think the
|  end result would be both a cleaner implementation of overloading and
|  rebindable syntax *and* more informative and useful source-code
|  provenances.
|  
|  Richard
|  _______________________________________________
|  ghc-devs mailing list
|  [hidden email]
|  http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

Re: re-engineering overloading and rebindable syntax

Vladislav Zavialov-2
In reply to this post by Richard Eisenberg-5
I find this idea attractive. Could we desugar `do` in the same manner using this SrcSpan trick? Could we desugar infix operators `a + b` to `(+) a b`? We just need to store in theh SrcSpan that the (+) was actually infix. Implementing as much syntactic sugar as possible this way would let us push complexity out of the type checker.

- Vlad

> On 5 Dec 2019, at 12:53, Richard Eisenberg <[hidden email]> wrote:
>
> Hi devs,
>
> How can we mitigate this? By expanding the possibilities of a SrcSpan. A SrcSpan is really a description of the provenance of a piece of AST. Right now, it considers two possibilities: that the code came from a specific stretch of rows and columns in an input file, or that the code came from elsewhere. Instead, we can expand (and perhaps rename) SrcSpan to include more possibilities. In support of my idea above, we could now have a SrcSpan that says some AST came from overloading. Such code is suppressed by default when pretty-printing. Thus, `fromString "blah"` could render as just `"blah"` (what the user wrote), if fromString was inserted by the translation pass described above. We can have a separate new SrcSpan that says that AST was written by translation from some original AST. That way, `ifThenElse a b c` can be printed as `if a then b else c`, if the former were translated from the latter. Though it's beyond my use-case above, we can also imagine a new SrcSpans that refer to a Template Haskell splice or a quasiquote.
>
> What do we think? Is this a worthwhile direction of travel? I think the end result would be both a cleaner implementation of overloading and rebindable syntax *and* more informative and useful source-code provenances.
>
> Richard
> _______________________________________________
> ghc-devs mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

Re: re-engineering overloading and rebindable syntax

MarLinn
In reply to this post by Richard Eisenberg-5
Hi,

On 05/12/2019 10.53, Richard Eisenberg wrote:
> Con:
>   - worse error messages, which would now refer to the desugared code instead of the user-written code.

I can think of several major parts that seem useful to solve this.
(Please excuse the very abstract and imprecise descriptions.)

1. Most "plugins" will probably still need a way to annotate the AST in
some way to inform their error message (i.e. SrcSpan?). These
annotations would be expand-only for all other plugins, the type
checker, and all other possible transformations. Their only job is to
inform their originator about what it did in case of an error. Ideally
this would be done in an expandable way.

2. Some stages might want to create suggested ASTs to help the user
understand the error, so this option should be part of an error
structure bubbling back up through the "plugins". But: the originators
of said ASTs should not need to know about annotations other than their
own, so they can not be expected to faithfully add them.

3. A "plugin" needs the ability to analyse an erroneous AST inside an
error structure and discover how it might have been constructed by said
plugin. Crucially, it might want to analyse the suggested ASTs with
potentially missing or misleading annotations.

This last part has me curious… if a plugin could do that well, it could
also quite possibly re-sugar any random piece of AST. In other words
there might come a day where GHC can tell a user what their code might
look like with different language extensions applied. And that's just
the tip of an iceberg of tooling possibilities.

So this might be a pipe dream for now. But practically speaking, I
expect most programmers to lean in one of two directions: to rely on
annotations heavily and ignore any suggested ASTs, or to go all-in on
the analysing part and annotate as little as possible. So if even one or
two implementers choose this second route, the pipe dream might become a
partial reality in the not-so-long term.

_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs