-
Notifications
You must be signed in to change notification settings - Fork 1
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: *
-kinded holes which are solved by BRAT
#69
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
f783923
Add hole solving but not for nats
croyzor 6f9d28a
Merge branch 'main' into just-holes
croyzor 889fb32
Merge remote-tracking branch 'origin/main' into HEAD
acl-cqc 2bc84cf
Drop unnecessary 'derive Ord' for TypeKind
acl-cqc e32d0b9
Remove repeated export of DIRY in Syntax/Common.hs
acl-cqc 3a60703
review comments
acl-cqc 4965210
another comment
acl-cqc 9b8a997
No need to filter hopes, but clarify with error
acl-cqc 06c454e
Factor out getNumVar, use in typeEq'
acl-cqc 6b05fb6
hlint
acl-cqc File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
module Brat.Checker.SolveHoles (typeEq) where | ||
|
||
import Brat.Checker.Helpers (buildConst) | ||
import Brat.Checker.Monad | ||
import Brat.Checker.Types (kindForMode) | ||
import Brat.Error (ErrorMsg(..)) | ||
import Brat.Eval | ||
import Brat.Syntax.Common | ||
import Brat.Syntax.Simple (SimpleTerm(..)) | ||
import Brat.Syntax.Value | ||
import Control.Monad.Freer | ||
import Bwd | ||
import Hasochism | ||
import Util (zipSameLength) | ||
|
||
import Control.Monad (when) | ||
import Data.Bifunctor (second) | ||
import Data.Foldable (sequenceA_) | ||
import Data.Functor | ||
import Data.Maybe (mapMaybe) | ||
import qualified Data.Map as M | ||
import Data.Type.Equality (TestEquality(..), (:~:)(..)) | ||
|
||
-- Demand that two closed values are equal, we're allowed to solve variables in the | ||
-- hope set to make this true. | ||
-- Raises a user error if the vals cannot be made equal. | ||
typeEq :: String -- String representation of the term for error reporting | ||
-> TypeKind -- The kind we're comparing at | ||
-> Val Z -- Expected | ||
-> Val Z -- Actual | ||
-> Checking () | ||
typeEq str = typeEq' str (Zy :* S0 :* S0) | ||
|
||
|
||
-- Internal version of typeEq with environment for non-closed values | ||
typeEq' :: String -- String representation of the term for error reporting | ||
-> (Ny :* Stack Z TypeKind :* Stack Z Sem) n | ||
-> TypeKind -- The kind we're comparing at | ||
-> Val n -- Expected | ||
-> Val n -- Actual | ||
-> Checking () | ||
typeEq' str stuff@(_ny :* _ks :* sems) k exp act = do | ||
hopes <- req AskHopes | ||
exp <- sem sems exp | ||
act <- sem sems act | ||
typeEqEta str stuff hopes k exp act | ||
|
||
isNumVar :: Sem -> Maybe SVar | ||
isNumVar (SNum (NumValue 0 (StrictMonoFun (StrictMono 0 (Linear v))))) = Just v | ||
isNumVar _ = Nothing | ||
|
||
-- Presumes that the hope set and the two `Sem`s are up to date. | ||
typeEqEta :: String -- String representation of the term for error reporting | ||
-> (Ny :* Stack Z TypeKind :* Stack Z Sem) n | ||
-> Hopes -- A map from the hope set to corresponding FCs | ||
-> TypeKind -- The kind we're comparing at | ||
-> Sem -- Expected | ||
-> Sem -- Actual | ||
-> Checking () | ||
typeEqEta tm (lvy :* kz :* sems) hopes (TypeFor m ((_, k):ks)) exp act = do | ||
-- Higher kinded things | ||
let nextSem = semLvl lvy | ||
let xz = B0 :< nextSem | ||
exp <- applySem exp xz | ||
act <- applySem act xz | ||
typeEqEta tm (Sy lvy :* (kz :<< k) :* (sems :<< nextSem)) hopes (TypeFor m ks) exp act | ||
-- Not higher kinded - check for flex terms | ||
-- (We don't solve under binders for now, so we only consider Zy here) | ||
-- 1. "easy" flex cases | ||
typeEqEta _tm (Zy :* _ks :* _sems) hopes k (SApp (SPar (InEnd e)) B0) act | ||
| M.member e hopes = solveHope k e act | ||
typeEqEta _tm (Zy :* _ks :* _sems) hopes k exp (SApp (SPar (InEnd e)) B0) | ||
| M.member e hopes = solveHope k e exp | ||
typeEqEta _ (Zy :* _ :* _) hopes Nat exp act | ||
| Just (SPar (InEnd e)) <- isNumVar exp, M.member e hopes = solveHope Nat e act | ||
| Just (SPar (InEnd e)) <- isNumVar act, M.member e hopes = solveHope Nat e exp | ||
-- 2. harder cases, neither is in the hope set, so we can't define it ourselves | ||
typeEqEta tm stuff@(ny :* _ks :* _sems) hopes k exp act = do | ||
exp <- quote ny exp | ||
act <- quote ny act | ||
let ends = mapMaybe getEnd [exp,act] | ||
-- sanity check: we've already dealt with either end being in the hopeset | ||
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" | ||
where | ||
getEnd (VApp (VPar e) _) = Just e | ||
getEnd (VNum n) = getNumVar n | ||
getEnd _ = Nothing | ||
|
||
-- This will update the `hopes`, potentially invalidating things that have | ||
-- been eval'd. | ||
-- The Sem is closed, for now. | ||
solveHope :: TypeKind -> InPort -> Sem -> Checking () | ||
solveHope k hope v = quote Zy v >>= \v -> case doesntOccur (InEnd hope) v of | ||
Right () -> do | ||
defineEnd (InEnd hope) v | ||
dangling <- case (k, v) of | ||
(Nat, VNum _v) -> err $ Unimplemented "Nat hope solving" [] | ||
(Nat, _) -> err $ InternalError "Head of Nat wasn't a VNum" | ||
_ -> buildConst Unit TUnit | ||
req (Wire (end dangling, kindType k, hope)) | ||
req (RemoveHope hope) | ||
Left msg -> case v of | ||
VApp (VPar (InEnd end)) B0 | hope == end -> pure () | ||
-- TODO: Not all occurrences are toxic. The end could be in an argument | ||
-- to a hoping variable which isn't used. | ||
-- E.g. h1 = h2 h1 - this is valid if h2 is the identity, or ignores h1. | ||
_ -> err msg | ||
|
||
typeEqs :: String -> (Ny :* Stack Z TypeKind :* Stack Z Sem) n -> [TypeKind] -> [Val n] -> [Val n] -> Checking () | ||
typeEqs _ _ [] [] [] = pure () | ||
typeEqs tm stuff (k:ks) (exp:exps) (act:acts) = typeEqs tm stuff ks exps acts <* typeEq' tm stuff k exp act | ||
typeEqs _ _ _ _ _ = typeErr "arity mismatch" | ||
|
||
typeEqRow :: Modey m | ||
-> String -- The term we complain about in errors | ||
-> (Ny :* Stack Z TypeKind :* Stack Z Sem) lv -- Next available level, the kinds of existing levels | ||
-> Ro m lv top0 | ||
-> Ro m lv top1 | ||
-> Either ErrorMsg (Some ((Ny :* Stack Z TypeKind :* Stack Z Sem) -- The new stack of kinds and fresh level | ||
:* ((:~:) top0 :* (:~:) top1)) -- Proofs both input rows have same length (quantified over by Some) | ||
,[Checking ()] -- subproblems to run in parallel | ||
) | ||
typeEqRow _ _ stuff R0 R0 = pure (Some (stuff :* (Refl :* Refl)), []) | ||
typeEqRow m tm stuff (RPr (_,ty1) ro1) (RPr (_,ty2) ro2) = typeEqRow m tm stuff ro1 ro2 <&> second | ||
((:) (typeEq' tm stuff (kindForMode m) ty1 ty2)) | ||
typeEqRow m tm (ny :* kz :* semz) (REx (_,k1) ro1) (REx (_,k2) ro2) | k1 == k2 = typeEqRow m tm (Sy ny :* (kz :<< k1) :* (semz :<< semLvl ny)) ro1 ro2 | ||
typeEqRow _ _ _ _ _ = Left $ TypeErr "Mismatched rows" | ||
|
||
-- Calls to typeEqRigid *must* start with rigid types to ensure termination | ||
typeEqRigid :: String -- String representation of the term for error reporting | ||
-> (Ny :* Stack Z TypeKind :* Stack Z Sem) n | ||
-> TypeKind -- The kind we're comparing at | ||
-> Val n -- Expected | ||
-> Val n -- Actual | ||
-> Checking () | ||
typeEqRigid tm (_ :* _ :* semz) Nat exp act = do | ||
-- TODO: What if there's hope in the numbers? | ||
exp <- sem semz exp | ||
act <- sem semz act | ||
if getNum exp == getNum act | ||
then pure () | ||
else err $ TypeMismatch tm (show exp) (show 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' <>> []) | ||
-- pattern should always match | ||
_ -> err $ InternalError "quote gave a surprising result" | ||
where | ||
svKind (VPar e) = kindOf (VPar e) | ||
svKind (VInx n) = pure $ proj kz n | ||
typeEqRigid tm lvkz (TypeFor m []) (VCon c args) (VCon c' args') | c == c' = | ||
req (TLup (m, c)) >>= \case | ||
Just ks -> typeEqs tm lvkz (snd <$> ks) args args' | ||
Nothing -> err $ TypeErr $ "Type constructor " ++ show c | ||
++ " undefined " ++ " at kind " ++ show (TypeFor m []) | ||
typeEqRigid tm lvkz (Star []) (VFun m0 (ins0 :->> outs0)) (VFun m1 (ins1 :->> outs1)) | Just Refl <- testEquality m0 m1 = do | ||
probs :: [Checking ()] <- throwLeft $ typeEqRow m0 tm lvkz ins0 ins1 >>= \case -- this is in Either ErrorMsg | ||
(Some (lvkz :* (Refl :* Refl)), ps1) -> typeEqRow m0 tm lvkz outs0 outs1 <&> (ps1++) . snd | ||
sequenceA_ probs -- uses Applicative (unlike sequence_ which uses Monad), hence parallelized | ||
typeEqRigid tm lvkz (TypeFor _ []) (VSum m0 rs0) (VSum m1 rs1) | ||
| Just Refl <- testEquality m0 m1 = case zipSameLength rs0 rs1 of | ||
Nothing -> typeErr "Mismatched sum lengths" | ||
Just rs -> traverse eqVariant rs >>= (sequenceA_ . concat) | ||
where | ||
eqVariant (Some r0, Some r1) = throwLeft (snd <$> typeEqRow m0 tm lvkz r0 r1) | ||
typeEqRigid tm _ _ v0 v1 = err $ TypeMismatch tm (show v0) (show v1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
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.
Left
hope set
as OK terminology, but removed things like