diff options
Diffstat (limited to 'src/Inky/Term/Parser.idr')
| -rw-r--r-- | src/Inky/Term/Parser.idr | 286 | 
1 files changed, 286 insertions, 0 deletions
| 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 | 
