diff options
Diffstat (limited to 'src/Inky')
-rw-r--r-- | src/Inky/Context.idr | 52 | ||||
-rw-r--r-- | src/Inky/Parser.idr | 698 | ||||
-rw-r--r-- | src/Inky/Term/Parser.idr | 286 | ||||
-rw-r--r-- | src/Inky/Thinning.idr | 97 | ||||
-rw-r--r-- | src/Inky/Type.idr | 2 |
5 files changed, 893 insertions, 242 deletions
diff --git a/src/Inky/Context.idr b/src/Inky/Context.idr index b0393f3..2e9af8f 100644 --- a/src/Inky/Context.idr +++ b/src/Inky/Context.idr @@ -7,15 +7,13 @@ import Data.Bool.Decidable import Data.Maybe.Decidable import Data.DPair import Data.Nat +import Decidable.Equality -- Contexts -------------------------------------------------------------------- export infix 2 :- -export -prefix 2 %% - public export record Assoc (a : Type) where constructor (:-) @@ -72,7 +70,7 @@ public export ctx ++ [<] = ctx ctx ++ ctx' :< x = (ctx ++ ctx') :< x -export +public export lengthAppend : Length ctx1 -> Length ctx2 -> Length (ctx1 ++ ctx2) lengthAppend len1 Z = len1 lengthAppend len1 (S len2) = S (lengthAppend len1 len2) @@ -83,9 +81,11 @@ length (ctx :< x) = S (length ctx) -- Variables ------------------------------------------------------------------- +export prefix 2 %% + public export -data VarPos : Context a -> (0 x : String) -> a -> Type where - [search x] +data VarPos : (ctx : Context a) -> (0 x : String) -> a -> Type where + [search ctx] Here : VarPos (ctx :< (x :- v)) x v There : VarPos ctx x v -> VarPos (ctx :< y) x v @@ -171,28 +171,31 @@ reflectEq ((%%) x {pos = pos1}) ((%%) y {pos = pos2}) -- Weakening +public export wknLPos : VarPos ctx1 x v -> Length ctx2 -> VarPos (ctx1 ++ ctx2) x v wknLPos pos Z = pos wknLPos pos (S len) = There (wknLPos pos len) +public export wknRPos : VarPos ctx2 x v -> VarPos (ctx1 ++ ctx2) x v wknRPos Here = Here wknRPos (There pos) = There (wknRPos pos) +public export splitPos : Length ctx2 -> VarPos (ctx1 ++ ctx2) x v -> Either (VarPos ctx1 x v) (VarPos ctx2 x v) splitPos Z pos = Left pos splitPos (S len) Here = Right Here splitPos (S len) (There pos) = mapSnd There $ splitPos len pos -export +public export wknL : {auto len : Length ctx2} -> Var ctx1 v -> Var (ctx1 ++ ctx2) v wknL i = toVar $ wknLPos i.pos len -export +public export wknR : Var ctx2 v -> Var (ctx1 ++ ctx2) v wknR i = toVar $ wknRPos i.pos -export +public export split : {auto len : Length ctx2} -> Var (ctx1 ++ ctx2) x -> Either (Var ctx1 x) (Var ctx2 x) split i = bimap toVar toVar $ splitPos len i.pos @@ -213,6 +216,19 @@ export nameOf : {ctx : Context a} -> (i : Var ctx v) -> Singleton i.name nameOf i = nameOfPos i.pos +-- Search + +lookupPos : (x : String) -> (ctx : Context a) -> Maybe (v ** VarPos ctx x v) +lookupPos x [<] = Nothing +lookupPos x (ctx :< (y :- v)) = + case decEq x y of + Yes Refl => Just (v ** Here) + No neq => bimap id There <$> lookupPos x ctx + +export +lookup : (x : String) -> (ctx : Context a) -> Maybe (v ** Var ctx v) +lookup x ctx = bimap id toVar <$> lookupPos x ctx + -- Environments ---------------------------------------------------------------- namespace Quantifier @@ -226,11 +242,12 @@ namespace Quantifier %name Quantifier.All env + public export indexAllPos : VarPos ctx x v -> All p ctx -> p v indexAllPos Here (env :< px) = px.value indexAllPos (There pos) (env :< px) = indexAllPos pos env - export + public export indexAll : Var ctx v -> All p ctx -> p v indexAll i env = indexAllPos i.pos env @@ -239,11 +256,16 @@ namespace Quantifier mapProperty f [<] = [<] mapProperty f (env :< (x :- px)) = mapProperty f env :< (x :- f px) - export + public export (++) : All p ctx1 -> All p ctx2 -> All p (ctx1 ++ ctx2) env1 ++ [<] = env1 env1 ++ env2 :< px = (env1 ++ env2) :< px + public export + split : Length ctx2 -> All p (ctx1 ++ ctx2) -> (All p ctx1, All p ctx2) + split Z env = (env, [<]) + split (S len) (env :< px) = mapSnd (:< px) $ split len env + -- Rows ------------------------------------------------------------------------ namespace Row @@ -274,7 +296,6 @@ namespace Row mapFresh f [<] = id mapFresh f (row :< (y :- _)) = andSo . mapSnd (mapFresh f row) . soAnd - public export Functor Row where map = Row.map @@ -295,6 +316,13 @@ namespace Row forget [<] = [<] forget (row :< x) = forget row :< x + export + extend : Row a -> Assoc a -> Maybe (Row a) + extend row (x :- v) = + case choose (x `freshIn` row) of + Left fresh => Just (row :< (x :- v)) + Right _ => Nothing + -- Equality -- soUnique : (x, y : So b) -> x = y diff --git a/src/Inky/Parser.idr b/src/Inky/Parser.idr index 1ad48d8..c44e7bd 100644 --- a/src/Inky/Parser.idr +++ b/src/Inky/Parser.idr @@ -1,21 +1,27 @@ module Inky.Parser +import public Data.List.Quantifiers +import public Data.Nat + import Control.WellFounded import Data.Bool +import Data.DPair import Data.List -import Data.List.Elem import Data.List1 -import Data.Nat import Data.So +import Data.String.Extra import Inky.Context +import Inky.Thinning import Text.Lexer +export +Interpolation Bounds where + interpolate bounds = "\{show (1 + bounds.startLine)}:\{show bounds.startCol}--\{show (1 + bounds.endLine)}:\{show bounds.endCol}" -- Parser Expressions ---------------------------------------------------------- -export -infixl 3 <**>, **>, <** -infixr 2 <||> +export infixl 3 <**>, **>, <** +export infixr 2 <||> public export linUnless : Bool -> Context a -> Context a @@ -23,124 +29,272 @@ linUnless False ctx = [<] linUnless True ctx = ctx public export -data Parser : (i : Type) -> (nil : Bool) -> (locked, free : Context (Bool, Type)) -> Type -> Type where - Var : (f : a -> b) -> Var free (nil, a) -> Parser i nil locked free b - Fail : (msg : String) -> Parser i False locked free a - Empty : (x : a) -> Parser i True locked free a - Lit : (text : i) -> (x : String -> a) -> Parser i False locked free a - (<**>) : - {nil1, nil2 : Bool} -> - Parser i nil1 locked free (a -> b) -> - Parser i nil2 (linUnless nil1 locked) (free ++ linUnless (not nil1) locked) a -> - Parser i (nil1 && nil2) locked free b - (<|>) : - {nil1, nil2 : Bool} -> - Parser i nil1 locked free a -> Parser i nil2 locked free a -> - So (not (nil1 && nil2)) => - Parser i (nil1 || nil2) locked free a +linUnlessLin : (0 a : Type) -> (b : Bool) -> linUnless {a} b [<] = [<] +linUnlessLin a False = Refl +linUnlessLin a True = Refl + +public export +data Parser : (i : Type) -> (nil : Bool) -> (locked, free : Context (Bool, Type)) -> Type -> Type + +public export +data ParserChain : (i : Type) -> (nil : Bool) -> (locked, free : Context (Bool, Type)) -> List Type -> Type + +data Parser where + Var : Var free (nil, a) -> Parser i nil locked free a + Lit : (text : i) -> Parser i False locked free String + Seq : + ParserChain i nil locked free as -> + Parser i nil locked free (HList as) + OneOf : + {nils : List Bool} -> + All (\nil => Parser i nil locked free a) nils -> + {auto 0 prf : length (filter Basics.id nils) `LTE` 1} -> + Parser i (any Basics.id nils) locked free a Fix : (0 x : String) -> - (f : a -> b) -> Parser i nil (locked :< (x :- (nil, a))) free a -> - Parser i nil locked free b + Parser i nil locked free a + Map : (a -> b) -> Parser i nil locked free a -> Parser i nil locked free b + WithBounds : Parser i nil locked free a -> Parser i nil locked free (WithBounds a) + +data ParserChain where + Nil : ParserChain i True locked free [] + (::) : + {nil1, nil2 : Bool} -> + Parser i nil1 locked free a -> + ParserChain i nil2 (linUnless nil1 locked) (free ++ linUnless (not nil1) locked) as -> + ParserChain i (nil1 && nil2) locked free (a :: as) %name Parser p, q +%name ParserChain ps, qs + +-- Weakening ------------------------------------------------------------------- public export -Functor (Parser i nil locked free) where - map f (Var g x) = Var (f . g) x - map f (Fail msg) = Fail msg - map f (Empty x) = Empty (f x) - map f (Lit text g) = Lit text (f . g) - map f ((<**>) {nil1 = True} p q) = map (f .) p <**> q - map f ((<**>) {nil1 = False} p q) = map (f .) p <**> q - map f (p <|> q) = map f p <|> map f q - map f (Fix x g p) = Fix x (f . g) p +rename : + locked1 `Thins` locked2 -> + free1 `Thins` free2 -> + {auto len : Length locked2} -> + Parser i nil locked1 free1 a -> Parser i nil locked2 free2 a +public export +renameChain : + locked1 `Thins` locked2 -> + free1 `Thins` free2 -> + {auto len : Length locked2} -> + ParserChain i nil locked1 free1 a -> ParserChain i nil locked2 free2 a +public export +renameAll : + locked1 `Thins` locked2 -> + free1 `Thins` free2 -> + {auto len : Length locked2} -> + All.All (\nil => Parser i nil locked1 free1 a) nils -> + All.All (\nil => Parser i nil locked2 free2 a) nils + +rename f g (Var i) = Var (index g i) +rename f g (Lit text) = Lit text +rename f g (Seq ps) = Seq (renameChain f g ps) +rename f g (OneOf ps) = OneOf (renameAll f g ps) +rename f g (Fix x p) = Fix x (rename (Keep f) g p) +rename f g (Map h p) = Map h (rename f g p) +rename f g (WithBounds p) = WithBounds (rename f g p) + +renameChain f g [] = [] +renameChain f g ((::) {nil1 = False} p ps) = rename f g p :: renameChain Id (append g f) ps +renameChain f g ((::) {nil1 = True} p ps) = rename f g p :: renameChain f g ps + +renameAll f g [] = [] +renameAll f g (p :: ps) = rename f g p :: renameAll f g ps public export -Applicative (Parser i True locked free) where - pure = Empty - (<*>) = (<**>) +weaken : + (len1 : Length free2) -> + {auto len2 : Length locked} -> + Parser i nil (free2 ++ locked) free1 a -> Parser i nil locked (free1 ++ free2) a +public export +weakenChain : + (len1 : Length free2) -> + {auto len2 : Length locked} -> + ParserChain i nil (free2 ++ locked) free1 a -> ParserChain i nil locked (free1 ++ free2) a +public export +weakenAll : + (len1 : Length free2) -> + {auto len2 : Length locked} -> + All.All (\nil => Parser i nil (free2 ++ locked) free1 a) nils -> + All.All (\nil => Parser i nil locked (free1 ++ free2) a) nils + +weaken len1 (Var x) = Var (wknL x) +weaken len1 (Lit text) = Lit text +weaken len1 (Seq ps) = Seq (weakenChain len1 ps) +weaken len1 (OneOf ps) = OneOf (weakenAll len1 ps) +weaken len1 (Fix x p) = Fix x (weaken len1 p) +weaken len1 (Map f p) = Map f (weaken len1 p) +weaken len1 (WithBounds p) = WithBounds (weaken len1 p) + +weakenChain len1 [] = [] +weakenChain len1 ((::) {nil1 = False} p ps) = weaken len1 p :: renameChain Id (assoc len2) ps +weakenChain len1 ((::) {nil1 = True} p ps) = weaken len1 p :: weakenChain len1 ps + +weakenAll len1 [] = [] +weakenAll len1 (p :: ps) = weaken len1 p :: weakenAll len1 ps -- Typing ---------------------------------------------------------------------- -export +-- Lists are sufficient, as we assume each symbol appears once. +-- TODO: switch to some efficient tree? + +public export peek : (env : All (const (List i)) free) -> Parser i nil locked free a -> List i -peek env (Var f x) = indexAll x env -peek env (Fail msg) = [] -peek env (Empty x) = [] -peek env (Lit text x) = [text] -peek env ((<**>) {nil1 = False} p q) = peek env p -peek env ((<**>) {nil1 = True} p q) = peek env p ++ peek env q -peek env (p <|> q) = peek env p ++ peek env q -peek env (Fix x f p) = peek env p +public export +peekChain : + (env : All (const (List i)) free) -> + ParserChain i nil locked free a -> List i +public export +peekAll : + (env : All (const (List i)) free) -> + All.All (\nil => Parser i nil locked free a) nils -> + All.All (const $ List i) nils -export +peek env (Var x) = indexAll x env +peek env (Lit text) = [text] +peek env (Seq ps) = peekChain env ps +peek env (OneOf ps) = concat (forget $ peekAll env ps) +peek env (Fix x p) = peek env p +peek env (Map f p) = peek env p +peek env (WithBounds p) = peek env p + +peekChain env [] = [] +peekChain env ((::) {nil1 = False} p ps) = peek env p +peekChain env ((::) {nil1 = True} p ps) = peek env p ++ peekChain env ps + +peekAll env [] = [] +peekAll env (p :: ps) = peek env p :: peekAll env ps + +public export follow : (penv1 : All (const (List i)) locked) -> (penv2 : All (const (List i)) free) -> (fenv1 : All (const (List i)) locked) -> (fenv2 : All (const (List i)) free) -> Parser i nil locked free a -> List i -follow penv1 penv2 fenv1 fenv2 (Var f x) = indexAll x fenv2 -follow penv1 penv2 fenv1 fenv2 (Fail msg) = empty -follow penv1 penv2 fenv1 fenv2 (Empty x) = empty -follow penv1 penv2 fenv1 fenv2 (Lit text x) = empty -follow penv1 penv2 fenv1 fenv2 ((<**>) {nil1 = False} p q) = - follow [<] (penv2 ++ penv1) [<] (fenv2 ++ fenv1) q -follow penv1 penv2 fenv1 fenv2 ((<**>) {nil1 = True} p q) = - peek penv2 q ++ - follow penv1 penv2 fenv1 fenv2 p ++ - follow penv1 penv2 fenv1 fenv2 q -follow penv1 penv2 fenv1 fenv2 (p <|> q) = - follow penv1 penv2 fenv1 fenv2 p ++ - follow penv1 penv2 fenv1 fenv2 q -follow penv1 penv2 fenv1 fenv2 (Fix x f p) = +public export +followChain : + (penv1 : All (const (List i)) locked) -> + (penv2 : All (const (List i)) free) -> + (fenv1 : All (const (List i)) locked) -> + (fenv2 : All (const (List i)) free) -> + ParserChain i nil locked free a -> List i +public export +followAll : + (penv1 : All (const (List i)) locked) -> + (penv2 : All (const (List i)) free) -> + (fenv1 : All (const (List i)) locked) -> + (fenv2 : All (const (List i)) free) -> + All.All (\nil => Parser i nil locked free a) nils -> List i + +follow penv1 penv2 fenv1 fenv2 (Var x) = indexAll x fenv2 +follow penv1 penv2 fenv1 fenv2 (Lit text) = [] +follow penv1 penv2 fenv1 fenv2 (Seq ps) = followChain penv1 penv2 fenv1 fenv2 ps +follow penv1 penv2 fenv1 fenv2 (OneOf ps) = followAll penv1 penv2 fenv1 fenv2 ps +follow penv1 penv2 fenv1 fenv2 (Fix x p) = -- Conjecture: The fix point converges after one step -- Proof: -- - we always add information -- - no step depends on existing information follow (penv1 :< (x :- peek penv2 p)) penv2 (fenv1 :< (x :- empty)) fenv2 p +follow penv1 penv2 fenv1 fenv2 (Map f p) = follow penv1 penv2 fenv1 fenv2 p +follow penv1 penv2 fenv1 fenv2 (WithBounds p) = follow penv1 penv2 fenv1 fenv2 p + +followChain penv1 penv2 fenv1 fenv2 [] = [] +followChain penv1 penv2 fenv1 fenv2 ((::) {nil1 = False, nil2} p ps) = + (if nil2 + then peekChain (penv2 ++ penv1) ps ++ follow penv1 penv2 fenv1 fenv2 p + else []) ++ + followChain [<] (penv2 ++ penv1) [<] (fenv2 ++ fenv1) ps +followChain penv1 penv2 fenv1 fenv2 ((::) {nil1 = True, nil2} p ps) = + (if nil2 + then peekChain penv2 ps ++ follow penv1 penv2 fenv1 fenv2 p + else []) ++ + followChain penv1 penv2 fenv1 fenv2 ps + +followAll penv1 penv2 fenv1 fenv2 [] = [] +followAll penv1 penv2 fenv1 fenv2 (p :: ps) = + follow penv1 penv2 fenv1 fenv2 p ++ + followAll penv1 penv2 fenv1 fenv2 ps -export -WellTyped : - Eq i => - (penv1 : All (const (List i)) locked) -> - (penv2 : All (const (List i)) free) -> - (fenv1 : All (const (List i)) locked) -> - (fenv2 : All (const (List i)) free) -> - Parser i nil locked free a -> Type -WellTyped penv1 penv2 fenv1 fenv2 (Var f x) = () -WellTyped penv1 penv2 fenv1 fenv2 (Fail msg) = () -WellTyped penv1 penv2 fenv1 fenv2 (Empty x) = () -WellTyped penv1 penv2 fenv1 fenv2 (Lit text x) = () -WellTyped penv1 penv2 fenv1 fenv2 ((<**>) {nil1 = False} p q) = - let set1 = follow penv1 penv2 fenv1 fenv2 p in - let set2 = peek (penv2 ++ penv1) q in - ( WellTyped penv1 penv2 fenv1 fenv2 p - , WellTyped [<] (penv2 ++ penv1) [<] (fenv2 ++ fenv1) q - , So (not $ any (`elem` set2) set1) - ) -WellTyped penv1 penv2 fenv1 fenv2 ((<**>) {nil1 = True} p q) = - let set1 = follow penv1 penv2 fenv1 fenv2 p in - let set2 = peek penv2 q in - ( WellTyped penv1 penv2 fenv1 fenv2 p - , WellTyped penv1 penv2 fenv1 fenv2 q - , So (not $ any (`elem` set2) set1) - ) -WellTyped penv1 penv2 fenv1 fenv2 (p <|> q) = - let set1 = peek penv2 p in - let set2 = peek penv2 q in - ( WellTyped penv1 penv2 fenv1 fenv2 p - , WellTyped penv1 penv2 fenv1 fenv2 q - , So (not $ any (`elem` set2) set1) - ) -WellTyped penv1 penv2 fenv1 fenv2 (Fix x f p) = - let fst = peek penv2 p in - let flw = follow (penv1 :< (x :- fst)) penv2 (fenv1 :< (x :- empty)) fenv2 p in - WellTyped (penv1 :< (x :- fst)) penv2 (fenv1 :< (x :- flw)) fenv2 p +public export +all' : (a -> Bool) -> List a -> Bool +all' f [] = True +all' f (x :: xs) = f x && all' f xs + +allTrue : (xs : List a) -> all' (const True) xs = True +allTrue [] = Refl +allTrue (x :: xs) = allTrue xs + +public export +disjoint : Eq a => List (List a) -> Bool +disjoint [] = True +disjoint (xs :: xss) = all' (\ys => all' (\x => not (x `elem` ys)) xs) xss && disjoint xss + +namespace WellTyped + public export + wellTyped : + (e : Eq i) -> + (penv1 : All (const (List i)) locked) -> + (penv2 : All (const (List i)) free) -> + (fenv1 : All (const (List i)) locked) -> + (fenv2 : All (const (List i)) free) -> + Parser i nil locked free a -> + Bool + public export + wellTypedChain : + (e : Eq i) -> + (penv1 : All (const (List i)) locked) -> + (penv2 : All (const (List i)) free) -> + (fenv1 : All (const (List i)) locked) -> + (fenv2 : All (const (List i)) free) -> + ParserChain i nil locked free a -> + Bool + public export + allWellTyped : + (e : Eq i) -> + (penv1 : All (const (List i)) locked) -> + (penv2 : All (const (List i)) free) -> + (fenv1 : All (const (List i)) locked) -> + (fenv2 : All (const (List i)) free) -> + All.All (\nil => Parser i nil locked free a) nils -> + Bool + + wellTyped e penv1 penv2 fenv1 fenv2 (Var i) = True + wellTyped e penv1 penv2 fenv1 fenv2 (Lit txt) = True + wellTyped e penv1 penv2 fenv1 fenv2 (Seq ps) = wellTypedChain e penv1 penv2 fenv1 fenv2 ps + wellTyped e penv1 penv2 fenv1 fenv2 (OneOf {nils, prf} ps) = + disjoint (forget $ peekAll penv2 ps) && allWellTyped e penv1 penv2 fenv1 fenv2 ps + wellTyped e penv1 penv2 fenv1 fenv2 (Fix x p) = + wellTyped e + (penv1 :< (x :- peek penv2 p)) + penv2 + (fenv1 :< (x :- follow (penv1 :< (x :- peek penv2 p)) penv2 (fenv1 :< (x :- [])) fenv2 p)) + fenv2 + p + wellTyped e penv1 penv2 fenv1 fenv2 (Map f p) = wellTyped e penv1 penv2 fenv1 fenv2 p + wellTyped e penv1 penv2 fenv1 fenv2 (WithBounds p) = wellTyped e penv1 penv2 fenv1 fenv2 p + + wellTypedChain e penv1 penv2 fenv1 fenv2 [] = True + wellTypedChain e penv1 penv2 fenv1 fenv2 ((::) {nil1 = False} p ps) = + disjoint [follow penv1 penv2 fenv1 fenv2 p, peekChain (penv2 ++ penv1) ps] && + wellTyped e penv1 penv2 fenv1 fenv2 p && + wellTypedChain e [<] (penv2 ++ penv1) [<] (fenv2 ++ fenv1) ps + wellTypedChain e penv1 penv2 fenv1 fenv2 ((::) {nil1 = True} p ps) = + disjoint [follow penv1 penv2 fenv1 fenv2 p, peekChain penv2 ps] && + wellTyped e penv1 penv2 fenv1 fenv2 p && + wellTypedChain e penv1 penv2 fenv1 fenv2 ps + + allWellTyped e penv1 penv2 fenv1 fenv2 [] = True + allWellTyped e penv1 penv2 fenv1 fenv2 (p :: ps) = + wellTyped e penv1 penv2 fenv1 fenv2 p && + allWellTyped e penv1 penv2 fenv1 fenv2 ps -- Parsing Function ------------------------------------------------------------ @@ -168,8 +322,10 @@ wknSmallerL (Strict prf) _ = ofSmaller prf wknSmallerL (Lax prf) _ = Lax prf wknSmallerR : (b1 : Bool) -> SmallerX b2 xs ys -> SmallerX (b1 || b2) xs ys -wknSmallerR b1 (Strict prf) = rewrite orFalseNeutral b1 in ofSmaller prf -wknSmallerR b1 (Lax prf) = rewrite orTrueTrue b1 in Lax prf +wknSmallerR b1 (Strict prf) = + if b1 then ofSmaller prf else ofSmaller prf +wknSmallerR b1 (Lax prf) = + if b1 then Lax prf else Lax prf forget : SmallerX b xs ys -> SmallerX True xs ys forget = wknSmallerR True @@ -180,6 +336,16 @@ toSmaller {xs = []} {ys = (y :: ys)} (Strict prf) = LTESucc LTEZero toSmaller {xs = (x :: xs)} {ys = []} (Strict prf) impossible toSmaller {xs = (x :: xs)} {ys = (y :: ys)} (Strict (LTESucc prf)) = LTESucc (toSmaller (Strict prf)) +anyCons : (b : Bool) -> (bs : List Bool) -> any Basics.id (b :: bs) = b || any Basics.id bs +anyCons b [] = sym (orFalseNeutral b) +anyCons b (b' :: bs) = + trans (anyCons (b || b') bs) $ + trans (sym $ orAssociative b b' (any id bs)) + (cong (b ||) (sym $ anyCons b' bs)) + +anyTrue : (bs : List Bool) -> any Basics.id (True :: bs) = True +anyTrue = anyCons True + -- Return Type namespace M @@ -203,39 +369,146 @@ namespace M wknR b1 (Err msg) = Err msg wknR b1 (Ok res ys prf) = Ok res ys (wknSmallerR b1 prf) + export + anyL : + (b : Bool) -> {0 bs : List Bool} -> + M xs (any Basics.id bs) a -> M xs (any Basics.id (b :: bs)) a + anyL b m = rewrite anyCons b bs in wknR b m + + export + anyR : (bs : List Bool) -> M xs b a -> M xs (any Basics.id (b :: bs)) a + anyR bs m = rewrite anyCons b bs in wknL m (any id bs) + -- The Big Function +data FirstNil : List Bool -> Type where + Here : FirstNil (True :: bs) + There : FirstNil bs -> FirstNil (False :: bs) + +findNil : (nils : List Bool) -> Maybe (FirstNil nils) +findNil [] = Nothing +findNil (False :: bs) = There <$> findNil bs +findNil (True :: bs) = Just Here + +memberOf : Eq a => (x : a) -> All.All (const $ List a) xs -> Maybe (Any (const ()) xs) +memberOf x [] = Nothing +memberOf x (xs :: xss) = + if x `elem` xs + then Just (Here ()) + else There <$> (x `memberOf` xss) + parser : - Eq i => Interpolation i => + (e : Eq i) => Interpolation i => (p : Parser i nil locked free a) -> (penv1 : _) -> (penv2 : _) -> (fenv1 : _) -> (fenv2 : _) -> - {auto 0 wf : WellTyped penv1 penv2 fenv1 fenv2 p} -> + {auto 0 wf : So (wellTyped e penv1 penv2 fenv1 fenv2 p)} -> (xs : List (WithBounds (Token i))) -> All (\x => (ys : List (WithBounds (Token i))) -> (0 _ : SmallerX False ys xs) -> uncurry (M ys) x) locked -> All (\x => (ys : List (WithBounds (Token i))) -> (0 _ : SmallerX True ys xs) -> uncurry (M ys) x) free -> M xs nil a -parser (Var f x) penv1 penv2 fenv1 fenv2 xs env1 env2 = - f <$> indexAll x env2 xs (Lax reflexive) -parser (Fail msg) penv1 penv2 fenv1 fenv2 xs env1 env2 = - Err msg -parser (Empty x) penv1 penv2 fenv1 fenv2 xs env1 env2 = - Ok x xs (Lax reflexive) -parser (Lit text f) penv1 penv2 fenv1 fenv2 xs env1 env2 = +parserChain : + (e : Eq i) => Interpolation i => + (ps : ParserChain i nil locked free as) -> + (penv1 : _) -> + (penv2 : _) -> + (fenv1 : _) -> + (fenv2 : _) -> + {auto 0 wf : So (wellTypedChain e penv1 penv2 fenv1 fenv2 ps)} -> + (xs : List (WithBounds (Token i))) -> + All (\x => (ys : List (WithBounds (Token i))) -> (0 _ : SmallerX False ys xs) -> uncurry (M ys) x) locked -> + All (\x => (ys : List (WithBounds (Token i))) -> (0 _ : SmallerX True ys xs) -> uncurry (M ys) x) free -> + M xs nil (HList as) +parserNil : + (e : Eq i) => Interpolation i => + (at : FirstNil nils) -> + (ps : All (\nil => Parser i nil locked free a) nils) -> + (penv1 : _) -> + (penv2 : _) -> + (fenv1 : _) -> + (fenv2 : _) -> + {auto 0 wf : So (allWellTyped e penv1 penv2 fenv1 fenv2 ps)} -> + (xs : List (WithBounds (Token i))) -> + All (\x => (ys : List (WithBounds (Token i))) -> (0 _ : SmallerX False ys xs) -> uncurry (M ys) x) locked -> + All (\x => (ys : List (WithBounds (Token i))) -> (0 _ : SmallerX True ys xs) -> uncurry (M ys) x) free -> + M xs (any Basics.id nils) a +parserOneOf : + (e : Eq i) => Interpolation i => + {nils : List Bool} -> + (at : Any (const ()) nils) -> + (ps : All (\nil => Parser i nil locked free a) nils) -> + (penv1 : _) -> + (penv2 : _) -> + (fenv1 : _) -> + (fenv2 : _) -> + {auto 0 wf : So (allWellTyped e penv1 penv2 fenv1 fenv2 ps)} -> + (xs : List1 (WithBounds (Token i))) -> + All (\x => (ys : List (WithBounds (Token i))) -> (0 _ : SmallerX False ys (forget xs)) -> uncurry (M ys) x) locked -> + All (\x => (ys : List (WithBounds (Token i))) -> (0 _ : SmallerX True ys (forget xs)) -> uncurry (M ys) x) free -> + M (forget xs) (any Basics.id nils) a + +parser (Var x) penv1 penv2 fenv1 fenv2 xs env1 env2 = + indexAll x env2 xs (Lax reflexive) +parser (Lit text) penv1 penv2 fenv1 fenv2 xs env1 env2 = case xs of [] => Err "expected \{text}, got end of file" y :: ys => if y.val.kind == text - then Ok (f y.val.text) ys (Strict reflexive) - else Err "\{show y.bounds}: expected \{text}, got \{y.val.kind}" -parser ((<**>) {nil1 = False, nil2} p q) penv1 penv2 fenv1 fenv2 xs env1 env2 = + then Ok y.val.text ys (Strict reflexive) + else Err "\{y.bounds}: expected \{text}, got \{y.val.kind}" +parser (Seq ps) penv1 penv2 fenv1 fenv2 xs env1 env2 = + parserChain ps penv1 penv2 fenv1 fenv2 xs env1 env2 +parser (OneOf {nils} ps) penv1 penv2 fenv1 fenv2 [] env1 env2 {wf} = + let 0 wfs = soAnd {a = disjoint (forget $ peekAll penv2 ps)} wf in + case findNil nils of + Nothing => Err "unexpected end of input" + Just at => parserNil at ps penv1 penv2 fenv1 fenv2 [] env1 env2 +parser (OneOf {nils} ps) penv1 penv2 fenv1 fenv2 (x :: xs) env1 env2 {wf = wf} = + let 0 wfs = soAnd {a = disjoint (forget $ peekAll penv2 ps)} wf in + let sets = peekAll penv2 ps in + case x.val.kind `memberOf` sets of + Just at => parserOneOf at ps penv1 penv2 fenv1 fenv2 (x ::: xs) env1 env2 + Nothing => case findNil nils of + Nothing => + Err + "\{x.bounds}: expected one of: \{join ", " $ map (\k => "\{k}") $ concat $ forget sets}; got \{x.val.kind}" + Just at => parserNil at ps penv1 penv2 fenv1 fenv2 (x :: xs) env1 env2 +parser (Fix {a, nil} x p) penv1 penv2 fenv1 fenv2 xs env1 env2 = + let f = parser p _ _ _ _ {wf} in + let + res : M xs nil a + res = + sizeInd {P = \ys => (0 prf : SmallerX True ys xs) -> M ys nil a} + (\ys, rec, lte => + f ys + ( mapProperty (\f, zs, 0 prf => f zs $ transX prf lte) env1 + :< (x :- (\zs, prf => rec zs (toSmaller prf) (forget $ transX prf lte))) + ) + (mapProperty (\f, zs, prf => f zs $ transX prf lte) env2)) + xs + (Lax reflexive) + in + res +parser (Map f p) penv1 penv2 fenv1 fenv2 xs env1 env2 = + f <$> parser p penv1 penv2 fenv1 fenv2 xs env1 env2 +parser (WithBounds p) penv1 penv2 fenv1 fenv2 xs env1 env2 = + case xs of + [] => irrelevantBounds <$> parser p penv1 penv2 fenv1 fenv2 [] env1 env2 + (x :: xs) => + (\y => MkBounded y x.isIrrelevant x.bounds) <$> + parser p penv1 penv2 fenv1 fenv2 (x :: xs) env1 env2 + +parserChain [] penv1 penv2 fenv1 fenv2 xs env1 env2 = Ok [] xs (Lax reflexive) +parserChain ((::) {nil1 = False, nil2} p ps) penv1 penv2 fenv1 fenv2 xs env1 env2 = + let 0 wfs = soAnd wf in + let 0 wfs' = soAnd (snd wfs) in case parser p penv1 penv2 fenv1 fenv2 xs env1 env2 of Err msg => Err msg - Ok f ys lt => + Ok x ys lt => case - parser q [<] (penv2 ++ penv1) [<] (fenv2 ++ fenv1) + parserChain ps [<] (penv2 ++ penv1) [<] (fenv2 ++ fenv1) ys [<] ( mapProperty (\f, zs, 0 prf => f zs $ forget $ transX prf lt) env2 @@ -243,122 +516,102 @@ parser ((<**>) {nil1 = False, nil2} p q) penv1 penv2 fenv1 fenv2 xs env1 env2 = ) of Err msg => Err msg - Ok x zs prf => Ok (f x) zs (rewrite sym $ andFalseFalse nil2 in transX prf lt) -parser ((<**>) {nil1 = True, nil2} p q) penv1 penv2 fenv1 fenv2 xs env1 env2 = + Ok y zs prf => Ok (x :: y) zs (rewrite sym $ andFalseFalse nil2 in transX prf lt) +parserChain ((::) {nil1 = True, nil2} p ps) penv1 penv2 fenv1 fenv2 xs env1 env2 = + let 0 wfs = soAnd wf in + let 0 wfs' = soAnd (snd wfs) in case parser p penv1 penv2 fenv1 fenv2 xs env1 env2 of Err msg => Err msg - Ok f ys lte => + Ok x ys lte => case - parser q penv1 penv2 fenv1 fenv2 + parserChain ps penv1 penv2 fenv1 fenv2 ys (mapProperty (\f, zs, prf => f zs $ transX prf lte) env1) (mapProperty (\f, zs, prf => f zs $ transX prf lte) env2) of Err msg => Err msg - Ok x zs prf => Ok (f x) zs (rewrite sym $ andTrueNeutral nil2 in transX prf lte) -parser ((<|>) {nil1, nil2} p q) penv1 penv2 fenv1 fenv2 xs env1 env2 = - case xs of - [] => - if nil1 - then parser p penv1 penv2 fenv1 fenv2 [] env1 env2 - else if nil2 - then parser q penv1 penv2 fenv1 fenv2 [] env1 env2 - else Err "unexpected end of input" - x :: xs => - if elem x.val.kind (peek penv2 p) - then wknL (parser p penv1 penv2 fenv1 fenv2 (x :: xs) env1 env2) nil2 - else if elem x.val.kind (peek penv2 q) - then wknR nil1 (parser q penv1 penv2 fenv1 fenv2 (x :: xs) env1 env2) - else if nil1 - then parser p penv1 penv2 fenv1 fenv2 (x :: xs) env1 env2 - else if nil2 - then parser q penv1 penv2 fenv1 fenv2 (x :: xs) env1 env2 - else Err "\{show x.bounds}: unexpected \{x.val.kind}" -parser (Fix {a, b, nil} x f p) penv1 penv2 fenv1 fenv2 xs env1 env2 = - let g = parser p _ _ _ _ {wf} in - let - res : M xs nil a - res = - sizeInd {P = \ys => (0 prf : SmallerX True ys xs) -> M ys nil a} - (\ys, rec, lte => - g ys - ( mapProperty (\f, zs, 0 prf => f zs $ transX prf lte) env1 - :< (x :- (\zs, prf => rec zs (toSmaller prf) (forget $ transX prf lte))) - ) - (mapProperty (\f, zs, prf => f zs $ transX prf lte) env2)) - xs - (Lax reflexive) - in - f <$> res + Ok y zs prf => Ok (x :: y) zs (rewrite sym $ andTrueNeutral nil2 in transX prf lte) + +parserNil {nils = True :: nils} Here (p :: ps) penv1 penv2 fenv1 fenv2 xs env1 env2 = + let 0 wfs = soAnd wf in + rewrite anyTrue nils in + parser p penv1 penv2 fenv1 fenv2 xs env1 env2 +parserNil (There at) (p :: ps) penv1 penv2 fenv1 fenv2 xs env1 env2 = + let 0 wfs = soAnd {a = wellTyped e penv1 penv2 fenv1 fenv2 p} wf in + parserNil at ps penv1 penv2 fenv1 fenv2 xs env1 env2 + +parserOneOf {nils = nil :: nils} (Here ()) (p :: ps) penv1 penv2 fenv1 fenv2 xs env1 env2 = + let 0 wfs = soAnd wf in + anyR nils (parser p penv1 penv2 fenv1 fenv2 (forget xs) env1 env2) +parserOneOf {nils = nil :: nils} (There at) (p :: ps) penv1 penv2 fenv1 fenv2 xs env1 env2 = + let 0 wfs = soAnd {a = wellTyped e penv1 penv2 fenv1 fenv2 p} wf in + anyL nil (parserOneOf at ps penv1 penv2 fenv1 fenv2 xs env1 env2) export parse : - Eq i => Interpolation i => + (e : Eq i) => Interpolation i => (p : Parser i nil [<] [<] a) -> - {auto 0 wf : WellTyped [<] [<] [<] [<] p} -> + {auto 0 wf : So (wellTyped e [<] [<] [<] [<] p)} -> (xs : List (WithBounds (Token i))) -> M xs nil a parse p xs = parser p [<] [<] [<] [<] xs [<] [<] --- Weakening ------------------------------------------------------------------- +-- Functor --------------------------------------------------------------------- public export -rename : - (len1 : Length locked1) -> - (len2 : Length locked2) -> - (forall x. Var locked1 x -> Var locked2 x) -> - (forall x. Var free1 x -> Var free2 x) -> - Parser i nil locked1 free1 a -> Parser i nil locked2 free2 a -rename len1 len2 ren1 ren2 (Var f x) = Var f (ren2 x) -rename len1 len2 ren1 ren2 (Fail msg) = Fail msg -rename len1 len2 ren1 ren2 (Empty x) = Empty x -rename len1 len2 ren1 ren2 (Lit text x) = Lit text x -rename len1 len2 ren1 ren2 ((<**>) {nil1 = False} p q) = - rename len1 len2 ren1 ren2 p <**> - rename Z Z id (either (wknL {len = len2} . ren2) (wknR . ren1) . split) q -rename len1 len2 ren1 ren2 ((<**>) {nil1 = True} p q) = - rename len1 len2 ren1 ren2 p <**> rename len1 len2 ren1 ren2 q -rename len1 len2 ren1 ren2 (p <|> q) = - rename len1 len2 ren1 ren2 p <|> rename len1 len2 ren1 ren2 q -rename len1 len2 ren1 ren2 (Fix x f p) = - Fix x f (rename (S len1) (S len2) (lift {len = S Z} ren1) ren2 p) +(++) : + {nil2 : Bool} -> + ParserChain i nil1 locked free as -> + ParserChain i nil2 (linUnless nil1 locked) (free ++ linUnless (not nil1) locked) bs -> + ParserChain i (nil1 && nil2) locked free (as ++ bs) +[] ++ qs = qs +((::) {nil1 = False, nil2} p ps) ++ qs = + p :: + ( ps + ++ rewrite linUnlessLin (Bool, Type) nil2 in + rewrite linUnlessLin (Bool, Type) (not nil2) in + qs) +((::) {nil1 = True, nil2} p ps) ++ qs = p :: (ps ++ qs) public export -weaken : - (len1 : Length free2) -> - {auto len2 : Length locked} -> - Parser i nil (free2 ++ locked) free1 a -> Parser i nil locked (free1 ++ free2) a -weaken len1 (Var f x) = Var f (wknL x) -weaken len1 (Fail msg) = Fail msg -weaken len1 (Empty x) = Empty x -weaken len1 (Lit text x) = Lit text x -weaken len1 ((<**>) {nil1 = False} p q) = - weaken len1 p <**> - rename Z Z - id - ( either (wknL . wknL) (either (wknL . wknR) wknR . split) - . split {len = lengthAppend len1 len2} - ) - q -weaken len1 ((<**>) {nil1 = True} p q) = weaken len1 p <**> weaken len1 q -weaken len1 (p <|> q) = weaken len1 p <|> weaken len1 q -weaken len1 (Fix x f p) = Fix x f (weaken len1 p) - -public export -shift : - {auto len1 : Length locked1} -> - (len2 : Length locked2) -> - (len3 : Length free2) -> - Parser i nil locked1 free1 a -> Parser i nil (locked1 ++ locked2) (free1 ++ free2) a -shift len2 len3 = rename len1 (lengthAppend len1 len2) wknL wknL +(<**>) : + {nil1, nil2 : Bool} -> + Parser i nil1 locked free a -> + Parser i nil2 (linUnless nil1 locked) (free ++ linUnless (not nil1) locked) b -> + Parser i (nil1 && nil2) locked free (a, b) +p <**> Seq ps = Map (\(x :: xs) => (x, xs)) $ Seq (p :: ps) +-- HACK: andTrueNeutral isn't public, so do a full case split. +(<**>) {nil1 = True, nil2 = True} p q = Map (\[x, y] => (x, y)) $ Seq [p, q] +(<**>) {nil1 = True, nil2 = False} p q = Map (\[x, y] => (x, y)) $ Seq [p, q] +(<**>) {nil1 = False, nil2 = True} p q = Map (\[x, y] => (x, y)) $ Seq [p, q] +(<**>) {nil1 = False, nil2 = False} p q = Map (\[x, y] => (x, y)) $ Seq [p, q] + +public export +Functor (Parser i nil locked free) where + map f (Map g p) = Map (f . g) p + map f p = Map f p + +public export +Applicative (Parser i True locked free) where + pure x = map (const x) (Seq []) + p <*> q = map (\(f, x) => f x) (p <**> q) -- Combinator ------------------------------------------------------------------ public export +(<|>) : + {nil1, nil2 : Bool} -> + Parser i nil1 locked free a -> + Parser i nil2 locked free a -> + {auto 0 prf : length (filter Basics.id [nil1, nil2]) `LTE` 1} -> + Parser i (nil1 || nil2) locked free a +p <|> q = OneOf [p, q] + +public export (<||>) : {nil1, nil2 : Bool} -> Parser i nil1 locked free a -> Parser i nil2 locked free b -> - So (not (nil1 && nil2)) => + {auto 0 prf : length (filter Basics.id [nil1, nil2]) `LTE` 1} -> Parser i (nil1 || nil2) locked free (Either a b) p <||> q = Left <$> p <|> Right <$> q @@ -368,7 +621,7 @@ public export Parser i nil1 locked free a -> Parser i nil2 (linUnless nil1 locked) (free ++ linUnless (not nil1) locked) b -> Parser i (nil1 && nil2) locked free b -p **> q = (\_ => id) <$> p <**> q +p **> q = snd <$> (p <**> q) public export (<**) : @@ -376,11 +629,24 @@ public export Parser i nil1 locked free a -> Parser i nil2 (linUnless nil1 locked) (free ++ linUnless (not nil1) locked) b -> Parser i (nil1 && nil2) locked free a -p <** q = const <$> p <**> q +p <** q = fst <$> (p <**> q) public export match : TokenKind i => (kind : i) -> Parser i False locked free (TokType kind) -match kind = Lit kind (tokValue kind) +match kind = Map (tokValue kind) $ Lit kind + +public export +enclose : + {b1, b2, b3 : Bool} -> + (left : Parser i b1 locked free ()) -> + (right : + Parser i b3 + (linUnless b2 (linUnless b1 locked)) + ((free ++ linUnless (not b1) locked) ++ linUnless (not b2) (linUnless b1 locked)) + ()) -> + Parser i b2 (linUnless b1 locked) (free ++ linUnless (not b1) locked) a -> + Parser i (b1 && b2 && b3 && True) locked free a +enclose left right p = (\[_, x, _] => x) <$> Seq {as = [(), a, ()]} [left, p, right] public export option : Parser i False locked free a -> Parser i True locked free (Maybe a) @@ -392,15 +658,29 @@ plus : Parser i False locked free a -> Parser i False locked free (List1 a) plus p = - Fix "plus" id - ( (:::) <$> shift (S Z) Z p - <**> maybe [] forget <$> option (Var id (%% "plus"))) + Fix "plus" + ( uncurry (:::) + <$> (rename (Drop Id) Id p <**> maybe [] forget <$> option (Var $ %% "plus"))) public export star : {auto len : Length locked} -> Parser i False locked free a -> Parser i True locked free (List a) -star p = - Fix "star" id - (maybe [] id <$> option ((::) <$> shift (S Z) Z p <**> Var id (%% "star"))) +star p = maybe [] forget <$> option (plus p) + +public export +sepBy1 : + {auto len : Length locked} -> + (sep : Parser i False locked free ()) -> + Parser i False locked free a -> + Parser i False locked free (List1 a) +sepBy1 sep p = uncurry (:::) <$> (p <**> star (weaken len sep **> weaken len p)) + +public export +sepBy : + {auto len : Length locked} -> + (sep : Parser i False locked free ()) -> + Parser i False locked free a -> + Parser i True locked free (List a) +sepBy sep p = maybe [] forget <$> option (sepBy1 sep p) diff --git a/src/Inky/Term/Parser.idr b/src/Inky/Term/Parser.idr new file mode 100644 index 0000000..7a67441 --- /dev/null +++ b/src/Inky/Term/Parser.idr @@ -0,0 +1,286 @@ +module Inky.Term.Parser + +import Data.List1 +import Data.String +import Inky.Context +import Inky.Parser +import Inky.Term +import Inky.Thinning +import Inky.Type +import Text.Lexer + +-- Lexer ----------------------------------------------------------------------- + +export +data InkyKind + = TermIdent + | TypeIdent + | Lit + | Suc + | Let + | In + | Case + | Of + | Fold + | By + | Nat + | ParenOpen + | ParenClose + | BracketOpen + | BracketClose + | AngleOpen + | AngleClose + | BraceOpen + | BraceClose + | Arrow + | DoubleArrow + | Bang + | Tilde + | Backslash + | Colon + | Equal + | Comma + | Ignore + +export +[EqI] Eq InkyKind where + TermIdent == TermIdent = True + TypeIdent == TypeIdent = True + Lit == Lit = True + Suc == Suc = True + Let == Let = True + In == In = True + Case == Case = True + Of == Of = True + Fold == Fold = True + By == By = True + Nat == Nat = True + ParenOpen == ParenOpen = True + ParenClose == ParenClose = True + BracketOpen == BracketOpen = True + BracketClose == BracketClose = True + AngleOpen == AngleOpen = True + AngleClose == AngleClose = True + BraceOpen == BraceOpen = True + BraceClose == BraceClose = True + Arrow == Arrow = True + DoubleArrow == DoubleArrow = True + Bang == Bang = True + Tilde == Tilde = True + Backslash == Backslash = True + Colon == Colon = True + Equal == Equal = True + Comma == Comma = True + Ignore == Ignore = True + _ == _ = False + +export +Interpolation InkyKind where + interpolate TermIdent = "term name" + interpolate TypeIdent = "type name" + interpolate Lit = "number" + interpolate Suc = "'suc'" + interpolate Let = "'let'" + interpolate In = "'in'" + interpolate Case = "'case'" + interpolate Of = "'of'" + interpolate Fold = "'fold'" + interpolate By = "'by'" + interpolate Nat = "'Nat'" + interpolate ParenOpen = "'('" + interpolate ParenClose = "')'" + interpolate BracketOpen = "'['" + interpolate BracketClose = "']'" + interpolate AngleOpen = "'<'" + interpolate AngleClose = "'>'" + interpolate BraceOpen = "'{'" + interpolate BraceClose = "'}'" + interpolate Arrow = "'->'" + interpolate DoubleArrow = "'=>'" + interpolate Bang = "'!'" + interpolate Tilde = "'~'" + interpolate Backslash = "'\\'" + interpolate Colon = "':'" + interpolate Equal = "'='" + interpolate Comma = "','" + interpolate Ignore = "" + +TokenKind InkyKind where + TokType TermIdent = String + TokType TypeIdent = String + TokType Lit = Nat + TokType _ = () + + tokValue TermIdent = id + tokValue TypeIdent = id + tokValue Lit = stringToNatOrZ + tokValue Suc = const () + tokValue Let = const () + tokValue In = const () + tokValue Case = const () + tokValue Of = const () + tokValue Fold = const () + tokValue By = const () + tokValue Nat = const () + tokValue ParenOpen = const () + tokValue ParenClose = const () + tokValue BracketOpen = const () + tokValue BracketClose = const () + tokValue AngleOpen = const () + tokValue AngleClose = const () + tokValue BraceOpen = const () + tokValue BraceClose = const () + tokValue Arrow = const () + tokValue DoubleArrow = const () + tokValue Bang = const () + tokValue Tilde = const () + tokValue Backslash = const () + tokValue Colon = const () + tokValue Equal = const () + tokValue Comma = const () + tokValue Ignore = const () + +keywords : List (String, InkyKind) +keywords = + [ ("suc", Suc) + , ("let", Let) + , ("in", In) + , ("case", Case) + , ("of", Of) + , ("fold", Fold) + , ("by", By) + , ("Nat", Nat) + ] + +export +relevant : InkyKind -> Bool +relevant = (/=) @{EqI} Ignore + +public export +InkyToken : Type +InkyToken = Token InkyKind + +termIdentifier : Lexer +termIdentifier = lower <+> many (alphaNum <|> exact "_") + +typeIdentifier : Lexer +typeIdentifier = upper <+> many (alphaNum <|> exact "_") + +export +tokenMap : TokenMap InkyToken +tokenMap = + toTokenMap [(spaces, Ignore)] ++ + [(termIdentifier, \s => + case lookup s keywords of + Just k => Tok k s + Nothing => Tok TermIdent s) + ,(typeIdentifier, \s => + case lookup s keywords of + Just k => Tok k s + Nothing => Tok TypeIdent s)] ++ + toTokenMap + [ (digits, Lit) + , (exact "(", ParenOpen) + , (exact ")", ParenClose) + , (exact "[", BracketOpen) + , (exact "]", BracketClose) + , (exact "<", AngleOpen) + , (exact ">", AngleClose) + , (exact "{", BraceOpen) + , (exact "}", BraceClose) + , (exact "->", Arrow) + , (exact "=>", DoubleArrow) + , (exact "!", Bang) + , (exact "~", Tilde) + , (exact "\\", Backslash) + , (exact ":", Colon) + , (exact "=", Equal) + , (exact ",", Comma) + ] + +-- Parser ---------------------------------------------------------------------- + +public export +InkyParser : Bool -> Context Type -> Context Type -> (a : Type) -> Type +InkyParser nil locked free a = + Parser InkyKind nil + (map (\a => (False, a)) locked) + (map (\a => (False, a)) free) + a + +public export +record TypeFun where + constructor MkTypeFun + try : (ctx : Context ()) -> Either String (Ty ctx ()) + +public export +TypeParser : Context () -> Context () -> Type +TypeParser locked free = + InkyParser False (map (const TypeFun) locked) (map (const TypeFun) free) TypeFun + +Row : InkyParser True [<] [<"openType" :- TypeFun] (List $ Assoc TypeFun) +Row = + sepBy (match Comma) + (mkAssoc <$> Seq [match TypeIdent, match Colon, Var (%% "openType")]) + where + mkAssoc : HList [String, (), TypeFun] -> Assoc TypeFun + mkAssoc [x, _, v] = x :- v + +tryRow : WithBounds (List $ Assoc TypeFun) -> (ctx : Context ()) -> Either String (Row (Ty ctx ())) +tryRow xs ctx = + foldlM + (\row, xf => do + a <- xf.value.try ctx + let Just row' = extend row (xf.name :- a) + | Nothing => Left "\{xs.bounds}: duplicate name \"\{xf.name}\"" + pure row') + [<] + xs.val + +OpenOrFixpointType : TypeParser [<] [<"openType" :- ()] +OpenOrFixpointType = + OneOf + [ mkFix <$> + Seq [match Backslash, match TypeIdent, match DoubleArrow, Var (%% "openType")] + , Var (%% "openType") + ] + where + mkFix : HList [(), String, (), TypeFun] -> TypeFun + mkFix [_, x, _, a] = MkTypeFun (\ctx => pure $ TFix x !(a.try (ctx :< (x :- ())))) + +AtomType : TypeParser [<"openType" :- ()] [<] +AtomType = + OneOf + [ + mkVar <$> WithBounds (match TypeIdent) + , MkTypeFun (\_ => pure TNat) <$ match Nat + , mkProd <$> enclose (match AngleOpen) (match AngleClose) (WithBounds Row) + , mkSum <$> enclose (match BracketOpen) (match BracketClose) (WithBounds Row) + , enclose (match ParenOpen) (match ParenClose) OpenOrFixpointType + ] + where + mkVar : WithBounds String -> TypeFun + mkVar x = + MkTypeFun + (\ctx => case lookup x.val ctx of + Just (() ** i) => pure (TVar i) + Nothing => Left "\{x.bounds}: unbound name \"\{x.val}\"") + + mkProd : WithBounds (List $ Assoc TypeFun) -> TypeFun + mkProd xs = MkTypeFun (\ctx => TProd <$> tryRow xs ctx) + + mkSum : WithBounds (List $ Assoc TypeFun) -> TypeFun + mkSum xs = MkTypeFun (\ctx => TSum <$> tryRow xs ctx) + +export +OpenType : TypeParser [<] [<] +OpenType = + Fix "openType" $ mkArrow <$> sepBy1 (match Arrow) AtomType + where + mkArrow : List1 TypeFun -> TypeFun + mkArrow = foldr1 (\x, y => MkTypeFun (\ctx => [| TArrow (x.try ctx) (y.try ctx) |])) + +%hint +export +OpenTypeWf : So (wellTyped EqI [<] [<] [<] [<] OpenType) +OpenTypeWf = Oh diff --git a/src/Inky/Thinning.idr b/src/Inky/Thinning.idr index 3d593ae..87640e2 100644 --- a/src/Inky/Thinning.idr +++ b/src/Inky/Thinning.idr @@ -20,13 +20,14 @@ data Thins : Context a -> Context a -> Type where -- Basics +public export indexPos : (f : ctx1 `Thins` ctx2) -> (pos : VarPos ctx1 x v) -> Var ctx2 v indexPos Id pos = toVar pos indexPos (Drop f) pos = ThereVar (indexPos f pos) indexPos (Keep f) Here = toVar Here indexPos (Keep f) (There pos) = ThereVar (indexPos f pos) -export +public export index : ctx1 `Thins` ctx2 -> Var ctx1 v -> Var ctx2 v index f i = indexPos f i.pos @@ -53,24 +54,6 @@ export indexInjective : (f : ctx1 `Thins` ctx2) -> {i, j : Var ctx1 v} -> index f i = index f j -> i = j indexInjective f {i = %% x, j = %% y} prf = toVarCong (indexPosInjective f $ toNatCong' prf) -export -indexId : (0 i : Var ctx v) -> index Id i = i -indexId (%% x) = Refl - -export -indexDrop : (0 f : ctx1 `Thins` ctx2) -> (0 i : Var ctx1 v) -> index (Drop f) i = ThereVar (index f i) -indexDrop f (%% x) = Refl - -export -indexKeepHere : (0 f : ctx1 `Thins` ctx2) -> index (Keep {x, y} f) (%% x) = (%% y) -indexKeepHere f = Refl - -export -indexKeepThere : - (0 f : ctx1 `Thins` ctx2) -> (0 i : Var ctx1 v) -> - index (Keep f) (ThereVar i) = ThereVar (index f i) -indexKeepThere f (%% x) = Refl - indexPosComp : (f : ctx2 `Thins` ctx3) -> (g : ctx1 `Thins` ctx2) -> (pos : VarPos ctx1 x v) -> indexPos (f . g) pos = index f (indexPos g pos) @@ -117,6 +100,80 @@ export (.index) : f ~~~ g -> (i : Var ctx1 v) -> index f i = index g i prf.index i = prf.indexPos i.pos +-- Useful for Parsers ---------------------------------------------------------- + +public export +dropAll : Length ctx2 -> ctx1 `Thins` ctx1 ++ ctx2 +dropAll Z = Id +dropAll (S len) = Drop (dropAll len) + +public export +keepAll : Length ctx -> ctx1 `Thins` ctx2 -> ctx1 ++ ctx `Thins` ctx2 ++ ctx +keepAll Z f = f +keepAll (S {x = x :- _} len) f = Keep (keepAll len f) + +public export +append : + ctx1 `Thins` ctx3 -> ctx2 `Thins` ctx4 -> + {auto len : Length ctx4} -> + ctx1 ++ ctx2 `Thins` ctx3 ++ ctx4 +append f Id = keepAll len f +append f (Drop g) {len = S len} = Drop (append f g) +append f (Keep g) {len = S len} = Keep (append f g) + +public export +assoc : Length ctx3 -> ctx1 ++ (ctx2 ++ ctx3) `Thins` (ctx1 ++ ctx2) ++ ctx3 +assoc Z = Id +assoc (S {x = x :- _} len) = Keep (assoc len) + +public export +growLength : ctx1 `Thins` ctx2 -> Length ctx1 -> Length ctx2 +growLength Id len = len +growLength (Drop f) len = S (growLength f len) +growLength (Keep f) (S len) = S (growLength f len) + +public export +thinLength : ctx1 `Thins` ctx2 -> Length ctx2 -> Length ctx1 +thinLength Id len = len +thinLength (Drop f) (S len) = thinLength f len +thinLength (Keep f) (S len) = S (thinLength f len) + +public export +thinAll : ctx1 `Thins` ctx2 -> All p ctx2 -> All p ctx1 +thinAll Id env = env +thinAll (Drop f) (env :< (x :- px)) = thinAll f env +thinAll (Keep {x, y} f) (env :< (_ :- px)) = thinAll f env :< (x :- px) + +public export +splitL : + {0 ctx1, ctx2, ctx3 : Context a} -> + Length ctx3 -> + ctx1 `Thins` ctx2 ++ ctx3 -> + Exists (\ctxA => Exists (\ctxB => (ctx1 = ctxA ++ ctxB, ctxA `Thins` ctx2, ctxB `Thins` ctx3))) +splitL Z f = Evidence ctx1 (Evidence [<] (Refl, f, Id)) +splitL (S len) Id = Evidence ctx2 (Evidence ctx3 (Refl, Id, Id)) +splitL (S len) (Drop f) = + let Evidence ctxA (Evidence ctxB (Refl, g, h)) = splitL len f in + Evidence ctxA (Evidence ctxB (Refl, g, Drop h)) +splitL (S len) (Keep f) = + let Evidence ctxA (Evidence ctxB (Refl, g, h)) = splitL len f in + Evidence ctxA (Evidence (ctxB :< _) (Refl, g, Keep h)) + +public export +splitR : + {0 ctx1, ctx2, ctx3 : Context a} -> + Length ctx2 -> + ctx1 ++ ctx2 `Thins` ctx3 -> + Exists (\ctxA => Exists (\ctxB => (ctx3 = ctxA ++ ctxB, ctx1 `Thins` ctxA, ctx2 `Thins` ctxB))) +splitR Z f = Evidence ctx3 (Evidence [<] (Refl, f, Id)) +splitR (S len) Id = Evidence ctx1 (Evidence ctx2 (Refl, Id, Id)) +splitR (S len) (Drop f) = + let Evidence ctxA (Evidence ctxB (Refl, g, h)) = splitR (S len) f in + Evidence ctxA (Evidence (ctxB :< _) (Refl, g, Drop h)) +splitR (S len) (Keep f) = + let Evidence ctxA (Evidence ctxB (Refl, g, h)) = splitR len f in + Evidence ctxA (Evidence (ctxB :< _) (Refl, g, Keep h)) + -------------------------------------------------------------------------------- -- Environments ---------------------------------------------------------------- -------------------------------------------------------------------------------- @@ -145,7 +202,7 @@ lookup env i = lookupPos env i.pos export lookupHere : (0 env : Env ctx1 ctx2 p) -> (0 x : String) -> (0 pv : p v) -> - lookup (env :< (x :- pv)) (%% x) = Right pv + lookup (env :< (x :- pv)) (toVar Here) = Right pv lookupHere env x pv = Refl export diff --git a/src/Inky/Type.idr b/src/Inky/Type.idr index e3eee12..9cfc1f7 100644 --- a/src/Inky/Type.idr +++ b/src/Inky/Type.idr @@ -65,7 +65,7 @@ thinCongAll prf (as :< (x :- a)) = thinId : (a : Ty ctx v) -> thin Id a = a thinIdAll : (as : Row (Ty ctx v)) -> thinAll Id as = as -thinId (TVar i) = cong TVar (indexId i) +thinId (TVar (%% x)) = Refl thinId TNat = Refl thinId (TArrow a b) = cong2 TArrow (thinId a) (thinId b) thinId (TProd as) = cong TProd (thinIdAll as) |