-
Notifications
You must be signed in to change notification settings - Fork 291
Fix use insertion when do block starts with destructuring bind
#5911
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
Conversation
pchiusano
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Self review
| reannotateUp g t = case ABT.out t of | ||
| ABT.Var v -> ABT.annotatedVar (annotation t, g t) v | ||
| ABT.Cycle body -> | ||
| let body' = reannotateUp g body | ||
| in ABT.cycle' (annotation t, snd (annotation body')) body' | ||
| ABT.Abs v body -> | ||
| let body' = reannotateUp g body | ||
| in ABT.abs' (annotation t, snd (annotation body')) v body' | ||
| ABT.Tm body -> | ||
| -- literals like 0xsaaff don't contribute to the annotations | ||
| -- even though they desugar to function calls | ||
| let body' = reannotateUp g <$> body | ||
| ann = if isLiteral t then mempty else g t <> foldMap (snd . annotation) body' | ||
| in ABT.tm' (annotation t, ann) body' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function didn't quite exist in ABT and it's too special purpose to add there since it's specific to the Unison term functor - nodes that are bytes literals have their annotation zero'd out to avoid contributing to use clauses that are inserted higher in the syntax tree.
| pattern Bytes' :: [Word64] -> Term3 v PrintAnnotation | ||
| pattern Bytes' :: [Word64] -> Term2 v at ap v a | ||
| pattern Bytes' bs <- (toBytes -> Just bs) | ||
|
|
||
| toBytes :: Term3 v PrintAnnotation -> Maybe [Word64] | ||
| toBytes :: Term2 v at ap v a -> Maybe [Word64] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needed to generalize these signatures to get it to typecheck. They were needlessly monomorphic.
| Delay' x | ||
| | Match' _ _ <- x -> do | ||
| Delay' x@(Match' scrutinee cs) | ||
| | not (isDestructuringBind scrutinee cs) -> do | ||
| px <- pretty0 (ac Annotation Block im doc) x | ||
| let hang = if isSoftHangable x then PP.softHang else PP.hang | ||
| pure . paren (p > Control) $ | ||
| fmt S.ControlKeyword "do" `hang` px | ||
| | otherwise -> do | ||
| let (im0', uses0) = calcImports im x | ||
| let allowUses = isLet x || (p == Bottom) | ||
| let im' = if allowUses then im0' else im | ||
| let uses = if allowUses then uses0 else [] | ||
| let soft = isSoftHangable x && null uses && p < Annotation | ||
| let hang = if soft then PP.softHang else PP.hang | ||
| px <- pretty0 (ac Annotation Block im' doc) x | ||
| -- this makes sure we get proper indentation if `px` spills onto | ||
| -- multiple lines, since `do` introduces layout block | ||
| let indent = PP.Width (if soft then 2 else 0) + (if soft && p < Application then 1 else 0) | ||
| pure . paren (p > Control) $ | ||
| fmt S.ControlKeyword "do" `hang` PP.lines (uses <> [PP.indentNAfterNewline indent px]) | ||
| Delay' x -> do | ||
| let (im0', uses0) = calcImports im x | ||
| let allowUses = isLet x || (p == Bottom) || isDestructure x | ||
| where | ||
| isDestructure (Match' scrutinee cs) = isDestructuringBind scrutinee cs | ||
| isDestructure _ = False | ||
| let im' = if allowUses then im0' else im | ||
| let uses = if allowUses then uses0 else [] | ||
| let soft = isSoftHangable x && null uses && p < Annotation | ||
| let hang = if soft then PP.softHang else PP.hang | ||
| px <- pretty0 (ac Annotation Block im' doc) x | ||
| -- this makes sure we get proper indentation if `px` spills onto | ||
| -- multiple lines, since `do` introduces layout block | ||
| let indent = PP.Width (if soft then 2 else 0) + (if soft && p < Application then 1 else 0) | ||
| pure . paren (p > Control) $ | ||
| fmt S.ControlKeyword "do" `hang` PP.lines (uses <> [PP.indentNAfterNewline indent px]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic is finnicky but it is the same as before, except that we allow use insertion if the first thing in a do is a destructuring bind.
Previously, the pretty-printer would fail to insert a
useclause at the start of adoblock, if thatdoblock began with a destructuring bind. This could sometimes lead to some terrible rendering with chains of operators all showing up with qualified names.Here's a minimal example. There are two things called
++, azoink.++andfoo.++. Thus, the code must disambiguate with auseclause:The
useclause wasn't being used when viewingexamplebecause thedoblock starts with aMatch, which isn't typically considered a candidate spot foruseinsertion. But actually, if thematchhappens to be a destructuring bind, putting auseclause there is fine.Here's before and after -
Before:
After:
Testing
I added a transcript test and it passes all the existing transcript tests.
Misc
I fixed what ended up being an unrelated bug with
Bytesliterals causing imports ofBytes.fromList.impl.