Skip to content

Commit d6b738b

Browse files
committed
Merge trunk
2 parents 8218692 + d3916eb commit d6b738b

File tree

19 files changed

+742
-268
lines changed

19 files changed

+742
-268
lines changed

parser-typechecker/src/Unison/PrintError.hs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1000,11 +1000,11 @@ renderTypeError e env src = case e of
10001000
]
10011001
C.KindInferenceFailure _ -> "kind inference failure"
10021002
C.DuplicateDefinitions vs ->
1003-
let go :: (v, [loc]) -> Pretty (AnnotatedText a)
1003+
let go :: (v, NESet loc) -> Pretty (AnnotatedText a)
10041004
go (v, locs) =
10051005
"["
10061006
<> renderVar v
1007-
<> mconcat (intersperse " : " $ annotatedToEnglish <$> locs)
1007+
<> mconcat (intersperse " : " $ annotatedToEnglish <$> toList locs)
10081008
<> "]"
10091009
in "DuplicateDefinitions:" <> mconcat (go <$> Nel.toList vs)
10101010
C.ConcatPatternWithoutConstantLength loc typ ->
@@ -1121,7 +1121,7 @@ renderContext env ctx@(C.Context es) =
11211121
e -> Pr.shown e
11221122
showElem ctx (C.Solved _ v (Type.Monotype t)) =
11231123
"'" <> shortName v <> " = " <> renderType' env (C.apply ctx t)
1124-
showElem ctx (C.Ann v t) =
1124+
showElem ctx (C.Ann v _ t) =
11251125
shortName v <> " : " <> renderType' env (C.apply ctx t)
11261126
showElem _ (C.Marker v) = "|" <> shortName v <> "|"
11271127

parser-typechecker/src/Unison/Syntax/TermParser.hs

+71-34
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ rewriteBlock = do
112112
rewriteTermlike kw mk = do
113113
kw <- quasikeyword kw
114114
lhs <- term
115-
(_spanAnn, rhs) <- layoutBlock "==>"
115+
(_openAnn, _spanAnn, rhs) <- layoutBlock "==>"
116116
pure (mk (ann kw <> ann rhs) lhs rhs)
117117
rewriteTerm = rewriteTermlike "term" DD.rewriteTerm
118118
rewriteCase = rewriteTermlike "case" DD.rewriteCase
@@ -234,10 +234,10 @@ matchCase = do
234234
[ Nothing <$ quasikeyword "otherwise",
235235
Just <$> infixAppOrBooleanOp
236236
]
237-
(_spanAnn, t) <- layoutBlock "->"
237+
(_openAnn, _spanAnn, t) <- layoutBlock "->"
238238
pure (guard, t)
239239
let unguardedBlock = label "case match" do
240-
(_spanAnn, t) <- layoutBlock "->"
240+
(_openAnn, _spanAnn, t) <- layoutBlock "->"
241241
pure (Nothing, t)
242242
-- a pattern's RHS is either one or more guards, or a single unguarded block.
243243
guardsAndBlocks <- guardedBlocks <|> (pure @[] <$> unguardedBlock)
@@ -562,10 +562,12 @@ lam p = label "lambda" $ mkLam <$> P.try (some prefixDefinitionName <* reserved
562562
in Term.lam' (ann (head vs) <> ann b) annotatedArgs b
563563

564564
letBlock, handle, ifthen :: (Monad m, Var v) => TermP v m
565-
letBlock = label "let" $ (snd <$> layoutBlock "let")
565+
letBlock = label "let" $ do
566+
(_openAnn, _spanAnn, tm) <- layoutBlock "let"
567+
pure tm
566568
handle = label "handle" do
567-
(handleSpan, b) <- block "handle"
568-
(_withSpan, handler) <- layoutBlock "with"
569+
(_handleOpenAnn, handleSpan, b) <- block "handle"
570+
(_withOpenAnn, _withSpan, handler) <- layoutBlock "with"
569571
-- We don't use the annotation span from 'with' here because it will
570572
-- include a dedent if it's at the end of block.
571573
-- Meaning the newline gets overwritten when pretty-printing and it messes things up.
@@ -600,9 +602,9 @@ lamCase = do
600602

601603
ifthen = label "if" do
602604
start <- peekAny
603-
(_spanAnn, c) <- block "if"
604-
(_spanAnn, t) <- block "then"
605-
(_spanAnn, f) <- layoutBlock "else"
605+
(_ifOpenAnn, _spanAnn, c) <- block "if"
606+
(_thenAnn, _spanAnn, t) <- block "then"
607+
(_elseAnn, _spanAnn, f) <- layoutBlock "else"
606608
pure $ Term.iff (ann start <> ann f) c t f
607609

608610
text :: (Var v) => TermP v m
@@ -736,11 +738,17 @@ doc2Block = do
736738
docTop d = \case
737739
Doc.Section title body -> pure $ Term.apps' (f d "Section") [docParagraph d title, Term.list (gann body) body]
738740
Doc.Eval code ->
739-
Term.app (gann d) (f d "Eval") . addDelay . snd
740-
<$> subParse (block' False False "syntax.docEval" (pure $ pure ()) $ Ann.External <$ P.eof) code
741+
let inner = do
742+
(_openAnn, ann, tm) <- (block' False False "syntax.docEval" (pure $ pure ()) $ Ann.External <$ P.eof)
743+
pure (ann, tm)
744+
in Term.app (gann d) (f d "Eval") . addDelay . snd
745+
<$> subParse inner code
741746
Doc.ExampleBlock code ->
742-
Term.apps' (f d "ExampleBlock") . (Term.nat (gann d) 0 :) . pure . addDelay . snd
743-
<$> subParse (block' False True "syntax.docExampleBlock" (pure $ pure ()) $ Ann.External <$ P.eof) code
747+
let inner = do
748+
(_openAnn, ann, tm) <- (block' False True "syntax.docExampleBlock" (pure $ pure ()) $ Ann.External <$ P.eof)
749+
pure (ann, tm)
750+
in Term.apps' (f d "ExampleBlock") . (Term.nat (gann d) 0 :) . pure . addDelay . snd
751+
<$> subParse inner code
744752
Doc.CodeBlock label body ->
745753
pure $
746754
Term.apps'
@@ -1219,9 +1227,8 @@ delayQuote = P.label "quote" do
12191227

12201228
delayBlock :: (Monad m, Var v) => P v m (Ann {- Ann spanning the whole block -}, Term v Ann)
12211229
delayBlock = P.label "do" do
1222-
(spanAnn, b) <- layoutBlock "do"
1223-
let argSpan = (ann b {- would be nice to use the annotation for 'do' here, but it's not terribly important -})
1224-
pure $ (spanAnn, DD.delayTerm (ann b) argSpan b)
1230+
(openAnn, spanAnn, b) <- layoutBlock "do"
1231+
pure $ (spanAnn, DD.delayTerm (ann b) openAnn b)
12251232

12261233
bang :: (Monad m, Var v) => TermP v m
12271234
bang = P.label "bang" do
@@ -1363,7 +1370,7 @@ destructuringBind = do
13631370
-- (Some 42) = List.head elems
13641371
pat <- P.try (parsePattern <* P.lookAhead (openBlockWith "="))
13651372
(p, boundVars) <- over (_2 . mapped) snd <$> bindConstructorsInPattern pat
1366-
(_spanAnn, scrute) <- layoutBlock "=" -- Dwight K. Scrute ("The People's Scrutinee")
1373+
(_eqAnn, _spanAnn, scrute) <- layoutBlock "=" -- Dwight K. Scrute ("The People's Scrutinee")
13671374
let guard = Nothing
13681375
let absChain vs t = foldr (\v t -> ABT.abs' (ann t) v t) t vs
13691376
thecase t = Term.MatchCase p (fmap (absChain boundVars) guard) $ absChain boundVars t
@@ -1381,7 +1388,15 @@ destructuringBind = do
13811388
-- binding) and the entire body.
13821389
-- * If the binding is a lambda, the lambda node includes the entire LHS of the binding,
13831390
-- including the name as well.
1384-
binding :: forall m v. (Monad m, Var v) => P v m ((Ann, v), Term v Ann)
1391+
binding ::
1392+
forall m v.
1393+
(Monad m, Var v) =>
1394+
P
1395+
v
1396+
m
1397+
( (Ann {- annotation for the location of 'v' -}, v),
1398+
Term v Ann
1399+
)
13851400
binding = label "binding" do
13861401
typ <- optional typedecl
13871402
-- a ++ b = ...
@@ -1401,25 +1416,25 @@ binding = label "binding" do
14011416
Nothing -> do
14021417
-- we haven't seen a type annotation, so lookahead to '=' before commit
14031418
(lhsLoc, name, args) <- P.try (lhs <* P.lookAhead (openBlockWith "="))
1404-
(_bodySpanAnn, body) <- block "="
1419+
(_eqAnn, _bodySpanAnn, body) <- block "="
14051420
verifyRelativeName' (fmap Name.unsafeParseVar name)
14061421
let binding = mkBinding lhsLoc args body
14071422
-- We don't actually use the span annotation from the block (yet) because it
14081423
-- may contain a bunch of white-space and comments following a top-level-definition.
1409-
let spanAnn = ann lhsLoc <> ann binding
1410-
pure $ ((spanAnn, (L.payload name)), binding)
1424+
-- let spanAnn = ann lhsLoc <> ann binding
1425+
pure $ ((ann name, (L.payload name)), binding)
14111426
Just (nameT, typ) -> do
14121427
(lhsLoc, name, args) <- lhs
14131428
verifyRelativeName' (fmap Name.unsafeParseVar name)
14141429
when (L.payload name /= L.payload nameT) $
14151430
customFailure $
14161431
SignatureNeedsAccompanyingBody nameT
1417-
(_bodySpanAnn, body) <- block "="
1432+
(_eqAnn, _bodySpanAnn, body) <- block "="
14181433
let binding = mkBinding lhsLoc args body
14191434
-- We don't actually use the span annotation from the block (yet) because it
14201435
-- may contain a bunch of white-space and comments following a top-level-definition.
14211436
let spanAnn = ann nameT <> ann binding
1422-
pure $ ((spanAnn, L.payload name), Term.ann (ann nameT <> ann binding) binding typ)
1437+
pure $ ((ann nameT, L.payload name), Term.ann spanAnn binding typ)
14231438
where
14241439
mkBinding :: Ann -> [L.Token v] -> Term.Term v Ann -> Term.Term v Ann
14251440
mkBinding _lhsLoc [] body = body
@@ -1430,10 +1445,30 @@ binding = label "binding" do
14301445
customFailure :: (P.MonadParsec e s m) => e -> m a
14311446
customFailure = P.customFailure
14321447

1433-
block :: forall m v. (Monad m, Var v) => String -> P v m (Ann, Term v Ann)
1448+
block ::
1449+
forall m v.
1450+
(Monad m, Var v) =>
1451+
String ->
1452+
P
1453+
v
1454+
m
1455+
( Ann {- annotation of block-open symbol, e.g. 'do', 'let' -},
1456+
Ann {- annotation for whole block -},
1457+
Term v Ann
1458+
)
14341459
block s = block' False False s (openBlockWith s) closeBlock
14351460

1436-
layoutBlock :: forall m v. (Monad m, Var v) => String -> P v m (Ann, Term v Ann)
1461+
layoutBlock ::
1462+
forall m v.
1463+
(Monad m, Var v) =>
1464+
String ->
1465+
P
1466+
v
1467+
m
1468+
( Ann {- annotation of block-open symbol, e.g. 'do', 'let' -},
1469+
Ann {- annotation for whole layout block -},
1470+
Term v Ann
1471+
)
14371472
layoutBlock s = block' False False s (openBlockWith s) optionalCloseBlock
14381473

14391474
-- example: use Foo.bar.Baz + ++ x
@@ -1468,7 +1503,7 @@ importp = do
14681503
pure (suffix, Name.joinDot (L.payload prefix) suffix)
14691504

14701505
data BlockElement v
1471-
= Binding ((Ann, v), Term v Ann)
1506+
= Binding ((Ann {- span for the binding name -}, v), Term v Ann)
14721507
| DestructuringBind (Ann, Term v Ann -> Term v Ann)
14731508
| Action (Term v Ann)
14741509

@@ -1512,22 +1547,22 @@ block' ::
15121547
String ->
15131548
P v m (L.Token ()) ->
15141549
P v m end ->
1515-
P v m (Ann {- ann which spans the whole block -}, Term v Ann)
1550+
P v m (Ann {- span for the opening token, e.g. the "do" or opening bracket -}, Ann {- ann which spans the whole block -}, Term v Ann)
15161551
block' isTop implicitUnitAtEnd s openBlock closeBlock = do
15171552
open <- openBlock
15181553
(names, imports) <- imports
15191554
_ <- optional semi
15201555
statements <- local (\e -> e {names}) $ sepBy semi statement
15211556
end <- closeBlock
15221557
body <- substImports names imports <$> go open statements
1523-
pure (ann open <> ann end, body)
1558+
pure (ann open, ann open <> ann end, body)
15241559
where
15251560
statement = asum [Binding <$> binding, DestructuringBind <$> destructuringBind, Action <$> blockTerm]
15261561
go :: L.Token () -> [BlockElement v] -> P v m (Term v Ann)
15271562
go open =
15281563
let finish :: Term.Term v Ann -> TermP v m
15291564
finish tm = case Components.minimize' tm of
1530-
Left dups -> customFailure $ DuplicateTermNames (toList dups)
1565+
Left dups -> customFailure $ DuplicateTermNames (toList (fmap (second toList) dups))
15311566
Right tm -> pure tm
15321567
toTm :: [BlockElement v] -> TermP v m
15331568
toTm [] = customFailure $ EmptyBlock (const s <$> open)
@@ -1537,19 +1572,21 @@ block' isTop implicitUnitAtEnd s openBlock closeBlock = do
15371572
where
15381573
step :: BlockElement v -> Term v Ann -> TermP v m
15391574
step elem result = case elem of
1540-
Binding ((a, v), tm) ->
1575+
Binding ((a, v), tm) -> do
1576+
let fullLetRecSpan = ann a <> ann result
15411577
pure $
15421578
Term.consLetRec
15431579
isTop
1544-
(ann a <> ann result)
1580+
fullLetRecSpan
15451581
(a, v, tm)
15461582
result
1547-
Action tm ->
1583+
Action tm -> do
1584+
let fullLetRecSpan = (ann tm <> ann result)
15481585
pure $
15491586
Term.consLetRec
15501587
isTop
1551-
(ann tm <> ann result)
1552-
(ann tm, positionalVar (ann tm) (Var.named "_"), tm)
1588+
fullLetRecSpan
1589+
(Ann.External, positionalVar (ann tm) (Var.named "_"), tm)
15531590
result
15541591
DestructuringBind (_, f) ->
15551592
f <$> finish result

parser-typechecker/src/Unison/Typechecker.hs

+3-3
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ data Env v loc = Env
9999
-- a function to resolve the type of @Ref@ constructors
100100
-- contained in that term.
101101
synthesize ::
102-
(Monad f, Var v, BuiltinAnnotation loc, Ord loc, Show loc) =>
102+
(Monad f, Var v, BuiltinAnnotation loc, Ord loc, Show loc, Semigroup loc) =>
103103
PrettyPrintEnv ->
104104
Context.PatternMatchCoverageCheckAndKindInferenceSwitch ->
105105
Env v loc ->
@@ -353,7 +353,7 @@ typeDirectedNameResolution ppe oldNotes oldType env = do
353353
-- contained in the term. Returns @typ@ if successful,
354354
-- and a note about typechecking failure otherwise.
355355
check ::
356-
(Monad f, Var v, BuiltinAnnotation loc, Ord loc, Show loc) =>
356+
(Monad f, Var v, BuiltinAnnotation loc, Ord loc, Show loc, Semigroup loc) =>
357357
PrettyPrintEnv ->
358358
Env v loc ->
359359
Term v loc ->
@@ -376,7 +376,7 @@ check ppe env term typ =
376376
-- tweak (Type.ForallNamed' v body) = Type.forall() v (tweak body)
377377
-- tweak t = Type.arrow() t t
378378
-- | Returns `True` if the expression is well-typed, `False` otherwise
379-
wellTyped :: (Monad f, Var v, BuiltinAnnotation loc, Ord loc, Show loc) => PrettyPrintEnv -> Env v loc -> Term v loc -> f Bool
379+
wellTyped :: (Monad f, Var v, BuiltinAnnotation loc, Ord loc, Show loc, Semigroup loc) => PrettyPrintEnv -> Env v loc -> Term v loc -> f Bool
380380
wellTyped ppe env term = go <$> runResultT (synthesize ppe Context.PatternMatchCoverageCheckAndKindInferenceSwitch'Enabled env term)
381381
where
382382
go (may, _) = isJust may

parser-typechecker/src/Unison/Typechecker/Components.hs

+19-19
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
module Unison.Typechecker.Components (minimize, minimize') where
22

3-
import Control.Arrow ((&&&))
4-
import Data.Function (on)
5-
import Data.List (groupBy, sortBy)
63
import Data.List.NonEmpty (NonEmpty)
7-
import Data.List.NonEmpty qualified as Nel
4+
import Data.List.NonEmpty qualified as NEL
85
import Data.Map qualified as Map
96
import Data.Set qualified as Set
7+
import Data.Set.NonEmpty (NESet)
8+
import Data.Set.NonEmpty qualified as NESet
109
import Unison.ABT qualified as ABT
1110
import Unison.Prelude
1211
import Unison.Term (Term')
@@ -35,25 +34,26 @@ ordered = ABT.orderedComponents
3534
--
3635
-- Fails on the left if there are duplicate definitions.
3736
minimize ::
38-
(Var v) =>
37+
forall vt v a.
38+
(Var v, Ord a) =>
3939
Term' vt v a ->
40-
Either (NonEmpty (v, [a])) (Maybe (Term' vt v a))
40+
Either (NonEmpty (v, NESet a)) (Maybe (Term' vt v a))
4141
minimize (Term.LetRecNamedAnnotatedTop' isTop blockAnn bs e) =
42-
let bindings = first snd <$> bs
43-
group =
44-
map (fst . head &&& map (ABT.annotation . snd))
45-
. groupBy ((==) `on` fst)
46-
. sortBy
47-
(compare `on` fst)
48-
grouped = group bindings
49-
dupes = filter ok grouped
42+
let bindings :: [(v, Term' vt v a)]
43+
bindings = bs <&> \((_a, v), t) -> (v, t)
44+
grouped :: Map v (NESet a)
45+
grouped =
46+
bs
47+
& fmap (\((a, v), _t) -> (v, NESet.singleton a)) -- For duplicates, we care about the binding location.
48+
& Map.fromListWith (NESet.union)
49+
dupes = Map.filterWithKey ok grouped
5050
where
51-
ok (v, as)
51+
ok v as
5252
| Var.name v == "_" = False
5353
| otherwise = length as > 1
54-
in if not $ null dupes
55-
then Left $ Nel.fromList dupes
56-
else
54+
in case NEL.nonEmpty $ Map.toList dupes of
55+
Just dupeList -> Left dupeList
56+
Nothing -> do
5757
let cs0 = if isTop then unordered bindings else ordered bindings
5858
-- within a cycle, we put the lambdas first, so
5959
-- unguarded definitions can refer to these lambdas, example:
@@ -90,5 +90,5 @@ minimize (Term.LetRecNamedAnnotatedTop' isTop blockAnn bs e) =
9090
minimize _ = Right Nothing
9191

9292
minimize' ::
93-
(Var v) => Term' vt v a -> Either (NonEmpty (v, [a])) (Term' vt v a)
93+
(Var v, Ord a) => Term' vt v a -> Either (NonEmpty (v, NESet a)) (Term' vt v a)
9494
minimize' term = fromMaybe term <$> minimize term

0 commit comments

Comments
 (0)