-
Notifications
You must be signed in to change notification settings - Fork 0
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
feat: Human-friendly metavariable printing #54
base: main
Are you sure you want to change the base?
Changes from all commits
93f4c73
7ddcd22
6fbef1a
1fa7401
bebcac5
ff0481d
9c5f374
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,7 @@ | |
import Brat.FC (FC) | ||
import Brat.Graph (Node(..), NodeType(..)) | ||
import Brat.Naming (Name, FreshMonad(..)) | ||
import Brat.QualName (QualName) | ||
import Brat.Syntax.Common | ||
import Brat.Syntax.Core (Term(..)) | ||
import Brat.Syntax.Simple | ||
|
@@ -40,9 +41,10 @@ | |
import Control.Monad.Freer (req) | ||
import Data.Bifunctor | ||
import Data.Foldable (foldrM) | ||
import Data.List (partition) | ||
import Data.List (intercalate, partition) | ||
import Data.Type.Equality (TestEquality(..), (:~:)(..)) | ||
import qualified Data.Map as M | ||
import qualified Data.Set as S | ||
import Prelude hiding (last) | ||
|
||
simpleCheck :: Modey m -> Val Z -> SimpleTerm -> Either ErrorMsg () | ||
|
@@ -67,8 +69,10 @@ | |
-- TODO: Make an `Error` constructor for this | ||
pull1PortRo _ p _ R0 = fail $ "Port not found: " ++ p | ||
pull1PortRo m p stuff (RPr (p', ty) ro) | ||
| p == p' = if portNameExists m p ro | ||
then err (AmbiguousPortPull p (show (RPr (p', ty) ro))) | ||
| p == p' = do | ||
names <- req AskNames | ||
if portNameExists m p ro | ||
then err (AmbiguousPortPull p (showWithMetas names (RPr (p', ty) ro))) | ||
else pure ((p', ty), rebuildRo m ro (stuff <>> [])) | ||
| otherwise = pull1PortRo m p (stuff :< (p', ty)) ro | ||
where | ||
|
@@ -97,19 +101,19 @@ | |
(x, ro) <- pull1PortRo m p B0 ro | ||
RPr x <$> pullPortsRo m ps ro | ||
|
||
pullPortsRow :: Show ty | ||
pullPortsRow :: ShowWithMetas ty | ||
=> [PortName] | ||
-> [(NamedPort e, ty)] | ||
-> Checking [(NamedPort e, ty)] | ||
pullPortsRow = pullPorts (portName . fst) showRow | ||
pullPortsRow ps row = req AskNames >>= \nm -> pullPorts (portName . fst) (showRow nm) ps row | ||
|
||
pullPortsSig :: Show ty | ||
pullPortsSig :: ShowWithMetas ty | ||
=> [PortName] | ||
-> [(PortName, ty)] | ||
-> Checking [(PortName, ty)] | ||
pullPortsSig = pullPorts fst showSig | ||
pullPortsSig ps row = req AskNames >>= \nm -> pullPorts fst (showSig (showWithMetas nm)) ps row | ||
|
||
pullPorts :: forall a ty | ||
Check warning on line 116 in brat/Brat/Checker/Helpers.hs GitHub Actions / build
|
||
. (a -> PortName) -- A way to get a port name for each element | ||
-> ([a] -> String) -- A way to print the list | ||
-> [PortName] -- Things to pull to the front | ||
|
@@ -125,18 +129,25 @@ | |
([found], remaining) -> pure (found, remaining) | ||
(_, _) -> err $ AmbiguousPortPull p (showFn available) | ||
|
||
ensureEmpty :: Show ty => String -> [(NamedPort e, ty)] -> Checking () | ||
combineDisjointEnvs :: M.Map QualName v -> M.Map QualName v -> Checking (M.Map QualName v) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this still in |
||
combineDisjointEnvs l r = | ||
let commonKeys = S.intersection (M.keysSet l) (M.keysSet r) | ||
in if S.null commonKeys | ||
then pure $ M.union l r | ||
else typeErr ("Variable(s) defined twice: " ++ | ||
intercalate "," (map show $ S.toList commonKeys)) | ||
|
||
ensureEmpty :: ShowWithMetas ty => String -> [(NamedPort e, ty)] -> Checking () | ||
ensureEmpty _ [] = pure () | ||
ensureEmpty str xs = err $ InternalError $ "Expected empty " ++ str ++ ", got:\n " ++ showSig (rowToSig xs) | ||
ensureEmpty str xs = do | ||
nm <- req AskNames | ||
err $ InternalError $ "Expected empty " ++ str ++ ", got:\n " ++ showRow nm xs | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess there is no easy equivalent of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not as far as I'm aware 😔 |
||
|
||
noUnders m = do | ||
((outs, ()), (overs, unders)) <- m | ||
ensureEmpty "unders" unders | ||
pure (outs, overs) | ||
|
||
rowToSig :: Traversable t => t (NamedPort e, ty) -> t (PortName, ty) | ||
rowToSig = fmap $ first portName | ||
|
||
showMode :: Modey m -> String | ||
showMode Braty = "" | ||
showMode Kerny = "(kernel) " | ||
|
@@ -265,7 +276,9 @@ | |
pure (node, unders, overs) | ||
(nodes, unders', overs') <- getThunks Braty rest | ||
pure (node:nodes, unders <> unders', overs <> overs') | ||
getThunks m ro = err $ ExpectedThunk (showMode m) (showRow ro) | ||
getThunks m ro = do | ||
nm <- req AskNames | ||
err $ ExpectedThunk (showMode m) (showRow nm ro) | ||
|
||
-- The type given here should be normalised | ||
vecLayers :: Modey m -> Val Z -> Checking ([(Src, NumVal (VVar Z))] -- The sizes of the vector layers | ||
|
@@ -306,7 +319,7 @@ | |
pure src | ||
|
||
mkMono :: Monotone (VVar Z) -> Checking Src | ||
mkMono (Linear (VPar (ExEnd e))) = pure (NamedPort e "mono") | ||
Check warning on line 322 in brat/Brat/Checker/Helpers.hs GitHub Actions / build
|
||
mkMono (Full sm) = do | ||
(_, [], [(twoSrc,_)], _) <- next "2" (Const (Num 2)) (S0, Some (Zy :* S0)) R0 (RPr ("value", TNat) R0) | ||
(_, [(lhs,_),(rhs,_)], [(powSrc,_)], _) <- next "2^" (ArithNode Pow) (S0, Some (Zy :* S0)) | ||
|
@@ -333,7 +346,7 @@ | |
-> (Src, CTy m Z) -- The input to this level of mapfun | ||
-> Checking (Src, CTy m Z) | ||
mkMapFun (lenSrc, len) (valSrc, cty) = do | ||
let weak1 = changeVar (Thinning (ThDrop ThNull)) | ||
Check warning on line 349 in brat/Brat/Checker/Helpers.hs GitHub Actions / build
|
||
vecFun <- vectorisedFun len my cty | ||
(_, [(lenTgt,_), (valTgt, _)], [(vectorSrc, Right (VFun my' cty))], _) <- | ||
next "MapFun" MapFun (S0, Some (Zy :* S0)) | ||
|
@@ -382,10 +395,12 @@ | |
defineTgt tgt = defineEnd (InEnd (end tgt)) | ||
|
||
declareSrc :: Src -> Modey m -> BinderType m -> Checking () | ||
declareSrc src my ty = req (Declare (ExEnd (end src)) my ty) | ||
declareSrc (NamedPort end name) my ty = req (Declare (ExEnd end) my ty) *> | ||
req (NameMeta (ExEnd end) name) | ||
|
||
declareTgt :: Tgt -> Modey m -> BinderType m -> Checking () | ||
declareTgt tgt my ty = req (Declare (InEnd (end tgt)) my ty) | ||
declareTgt (NamedPort end name) my ty = req (Declare (InEnd end) my ty) *> | ||
req (NameMeta (InEnd end) name) | ||
|
||
-- listToRow :: [(PortName, BinderType m)] -> Ro m Z i | ||
-- listToRow [] = R0 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -95,6 +95,8 @@ data CheckingSig ty where | |
ANewHope :: InPort -> FC -> CheckingSig () | ||
AskHopes :: CheckingSig Hopes | ||
RemoveHope :: InPort -> CheckingSig () | ||
NameMeta :: End -> String -> CheckingSig () | ||
AskNames :: CheckingSig (M.Map End String) | ||
|
||
localAlias :: (QualName, Alias) -> Checking v -> Checking v | ||
localAlias _ (Ret v) = Ret v | ||
|
@@ -281,6 +283,12 @@ handler (Req s k) ctx g | |
if M.member e hset | ||
then handler (k ()) (ctx { hopes = M.delete e hset }) g | ||
else Left (dumbErr (InternalError ("Trying to remove unknown Hope: " ++ show e))) | ||
NameMeta end name -> let names = userNames (store ctx) in | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about making the name an extra Maybe parameter to (I say Maybe - we could then even turn Nothings into integer indices, say, to make them more compact than the rather-complex VPar End notation. Using |
||
case M.lookup end names of | ||
Just oldName -> error $ "Trying to name end (" ++ show end ++ ")\nas " ++ show name ++ " but it's already called " ++ oldName | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
Nothing -> let st = store ctx in | ||
handler (k ()) (ctx { store = st { userNames = M.insert end name (userNames st) } }) g | ||
AskNames -> handler (k (userNames (store ctx))) ctx g | ||
|
||
type Checking = Free CheckingSig | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -83,8 +83,11 @@ typeEqEta tm stuff@(ny :* _ks :* _sems) hopes k exp act = do | |
when (or [M.member ie hopes | InEnd ie <- ends]) $ typeErr "ends were in hopeset" | ||
case ends of | ||
[] -> typeEqRigid tm stuff k exp act -- easyish, both rigid i.e. already defined | ||
[e1, e2] | e1 == e2 -> pure () -- trivially same, even if both still yet-to-be-defined | ||
_es -> error "TODO: must wait for one or the other to become more defined" | ||
-- variables are trivially the same, even if undefined, but the values may | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like this PR has got muddled up with #75 |
||
-- be different! E.g. X =? 1 + X | ||
[_, _] | exp == act -> pure () | ||
-- TODO: Once we have scheduling, we must wait for one or the other to become more defined, rather than failing | ||
_ -> err (TypeMismatch tm (show exp) (show act)) | ||
where | ||
getEnd (VApp (VPar e) _) = Just e | ||
getEnd (VNum n) = getNumVar n | ||
|
@@ -143,7 +146,9 @@ typeEqRigid tm (_ :* _ :* semz) Nat exp act = do | |
act <- sem semz act | ||
if getNum exp == getNum act | ||
then pure () | ||
else err $ TypeMismatch tm (show exp) (show act) | ||
else do | ||
names <- req AskNames | ||
err $ TypeMismatch tm (showWithMetas names exp) (showWithMetas names act) | ||
typeEqRigid tm stuff@(_ :* kz :* _) (TypeFor m []) (VApp f args) (VApp f' args') | f == f' = | ||
svKind f >>= \case | ||
TypeFor m' ks | m == m' -> typeEqs tm stuff (snd <$> ks) (args <>> []) (args' <>> []) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -193,6 +193,9 @@ unify l k r = do | |
|
||
-- Solve a metavariable statically - don't do anything dynamic | ||
-- Once a metavariable is solved, we expect to not see it again in a normal form. | ||
-- | ||
-- N.B. We should try harder to preserve order here for more comprehensible | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about a tracking issue with all the ways to improve error messages ;) |
||
-- error messages. See the Helium/Top projects. | ||
instantiateMeta :: End -> Val Z -> Checking () | ||
instantiateMeta e val = do | ||
throwLeft (doesntOccur e val) | ||
|
@@ -252,7 +255,7 @@ unifyNum (NumValue lup lgro) (NumValue rup rgro) | |
demandSucc (StrictMono k (Full nPlus1)) = do | ||
n <- demandSucc nPlus1 | ||
pure $ nPlus ((2 ^ k) - 1) $ n2PowTimes (k + 1) $ nFull n | ||
demandSucc n = err . UnificationError $ "Couldn't force " ++ show n ++ " to be a successor" | ||
demandSucc n = req AskNames >>= \nm -> err (UnificationError $ "Couldn't force " ++ showWithMetas nm n ++ " to be a successor") | ||
|
||
-- Complain if a number isn't even, otherwise return half | ||
demandEven :: NumVal (VVar Z) -> Checking (NumVal (VVar Z)) | ||
|
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.
Good to keep the scope small, this doesn't cost you anything in line count: