Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Annotate ASTs with types at every node #991

Merged
merged 47 commits into from
Jan 25, 2023
Merged

Annotate ASTs with types at every node #991

merged 47 commits into from
Jan 25, 2023

Conversation

byorgey
Copy link
Member

@byorgey byorgey commented Jan 9, 2023

Values of type Syntax are as before: parsed syntax, with each node annotated with SrcLoc.

Values of type Syntax' Polytype, however, have each node annotated with both a SrcLoc and a Polytype. (Syntax is really just a synonym for Syntax' ().)

Type inference takes a Syntax and outputs a TModule, which now contains a Syntax' Polytype, in other words, a new version of the AST where every node has been annotated with the inferred type of the subterm rooted there.


Why is this useful?

  1. It will enable us to do type-specific elaboration/rewriting. For example I think this will allow us to solve Variables in a local monadic binder escape to outer scopes #681 , because we only want to apply a rewrite to variables with a command type.
  2. It makes type information for any specific subterm easily available. For example I hope we will be able to use this to enhance the OnHover LSP handler, e.g. to show the type of the term under the mouse.

I imagine the code changes might look kind of intimidating but I don't think it's really that bad once you understand what is going on, so I'm happy to answer any questions or explain anything.

mkProg = TApp (TConst Make) (TText (e ^. entityName))
mkPT = ProcessedTerm mkProg (Module mkTy empty) mkReq empty
let name = e ^. entityName
mkPT = [tmQ| make $str:name |]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice use of TH! 👍

pattern Syntax :: SrcLoc -> Term -> Syntax
pattern Syntax l t = Syntax' l t ()

{-# COMPLETE Syntax #-}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does COMPLETE do?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It specifies a set of constructors/pattern synonyms which should be considered "complete" for the purposes of pattern match coverage checking. i.e. if you pattern-match on everything listed in the COMPLETE pragma then GHC will not warn about missing cases. Using COMPLETE is common when creating pattern synonyms since there's no way in general to know whether an arbitrary set of pattern synonyms is going to cover all possible cases, so without the pragma in general GHC will generate lots of warnings about incomplete pattern matches.

https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/pragmas.html#complete-pragmas

Was accidentally deleting the `atomic` constant.
@byorgey byorgey marked this pull request as draft January 13, 2023 20:16
@byorgey
Copy link
Member Author

byorgey commented Jan 14, 2023

I've realized a big issue with the way this works: in particular it doesn't make sense to annotate every node of the AST with a Polytype; we should instead have a single Polytype for the entire thing at the top level, and annotate every node with a Type. For example suppose we have def wow = \x. format x ++ "!" end. The type of wow will correctly be inferred as forall a. a -> text, but if you hover over x, its type will be shown as forall a. a which does not make any sense. It should just have type a, or perhaps some made-up type variable like s0. I think I have an idea how to fix this...

@xsebek
Copy link
Member

xsebek commented Jan 15, 2023

@byorgey won't every definition and let binding have a Polytype?

I would not mind if the type was stored in the SDef/SLet instead of the original Maybe Polytype. 🙂

@xsebek xsebek mentioned this pull request Jan 15, 2023
2 tasks
@byorgey
Copy link
Member Author

byorgey commented Jan 15, 2023

won't every definition and let binding have a Polytype?

Yes, they should. Still trying to figure out a good way to annotate different things with Type or Polytype as appropriate...

@xsebek
Copy link
Member

xsebek commented Jan 19, 2023

@byorgey could you merge this as is and improve on it in the main branch? 🙂

The types are morally wrong with the forall, but it is still better than nothing and we will not be using them to figure the binding sites of variables, so it is not practically a problem. (In fact, we could strip all forall and it would make sense.)

I would like to rebase and merge my OnHover rework and the types added here are invaluable.

Not that I am in a rush, I just don't want to have merge conflicts with @kostmo if he works on the LSP further. 😅

@byorgey
Copy link
Member Author

byorgey commented Jan 19, 2023

You're right, I will do that. Can't let the perfect become the enemy of the good. 😄

@byorgey byorgey marked this pull request as ready for review January 24, 2023 22:24
@byorgey
Copy link
Member Author

byorgey commented Jan 24, 2023

As discussed above, we can merge this as-is now, and I've created #1042 for tracking the remaining issue.


isVar (TVar {}) = True
isVar _ = False
getVars = map (_sTerm &&& _sType) . filter (isVar . _sTerm) . universe
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

universe

🤯

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See, I put that in there on purpose to give people ideas. 😄 https://hackage.haskell.org/package/lens-5.2/docs/Control-Lens-Plated.html has some pretty powerful tools for working with ASTs.

@byorgey byorgey added the merge me Trigger the merge process of the Pull request. label Jan 24, 2023
@mergify mergify bot merged commit 1678b49 into main Jan 25, 2023
@mergify mergify bot deleted the annotate-ast branch January 25, 2023 00:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merge me Trigger the merge process of the Pull request.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Annotate AST nodes with inferred types
3 participants