-# LANGUAGE MultiParamTypeClasses #-}
-# LANGUAGE TypeSynonymInstances #-}
-# LANGUAGE FlexibleInstances #-}
-# LANGUAGE InstanceSigs #-}
Isabelle.UTF8 (
setup, setup3,
Recode (..)
qualified System.IO as IO
Data.Text (Text)
qualified Data.Text as Text
qualified Data.Text.Encoding as Encoding
qualified Data.Text.Encoding.Error as Error
Data.ByteString (ByteString)
qualified Isabelle.Bytes as Bytes
Isabelle.Bytes (Bytes)
:: IO.Handle -> IO ()
h = do
IO.hSetEncoding h IO.utf8
IO.hSetNewlineMode h IO.noNewlineTranslation
System.Environment (lookupEnv)
Data.Maybe (fromMaybe)
qualified Data.Text as Text
Data.Text (Text)
qualified Data.Text.Lazy as Lazy
Data.String (IsString)
qualified Data.List.Split as Split
qualified Isabelle.Symbol as Symbol
qualified Isabelle.Bytes as Bytes
Isabelle.Bytes (Bytes)
qualified Isabelle.UTF8 as UTF8
- functions -}
|>) :: a -> (a -> b) -> b
|> f = f x
|->) :: (a, b) -> (a -> b -> c) -> c
x, y) |-> f = f x y
#>) :: (a -> b) -> (b -> c) -> a -> c
f #> g) x = x |> f |> g
#->) :: (a -> (c, b)) -> (c -> b -> d) -> a -> d
f #-> g) x = x |> f |-> g
- lists -}
:: (a -> b -> b) -> [a] -> b -> b
_ [] y = y
f (x : xs) y = fold f xs (f x y)
:: (a -> b -> b) -> [a] -> b -> b
_ [] y = y
f (x : xs) y = f x (fold_rev f xs y)
:: (a -> b -> (c, b)) -> [a] -> b -> ([c], b)
_ [] y = ([], y)
f (x : xs) y =
let
(x', y') = f x y
(xs', y'') = fold_map f xs y'
in (x' : xs', y'')
:: a -> [a]
x = [x]
:: [a] -> a
[x] = x
_ = undefined
:: Monad m => ([a] -> m [b]) -> a -> m b
f x = the_single 🪙 f [x]
:: ((Int, a) -> b) -> [a] -> [b]
f = map_aux 0
where
map_aux _ [] = []
map_aux i (x : xs) = f (i, x) : map_aux (i + 1) xs
:: (a -> Maybe b) -> [a] -> Maybe (Int, b)
f = get_aux 0
where
get_aux _ [] = Nothing
get_aux i (x : xs) =
case f x of
Nothing -> get_aux (i + 1) xs
Just y -> Just (i, y)
:: a -> [a] -> [a]
s (x : xs@(_ : _)) = x : s : separate s xs
_ xs = xs;
- string-like interfaces -}
(IsString a, Monoid a, Eq a, Ord a) => StringLike a where
space_explode :: Char -> a -> [a]
trim_line :: a -> a
:: Int -> (Int -> Char) -> (Int -> a -> a) -> a -> a
n at trim s =
if n >= 2 && at (n - 2) == '\r' && at (n - 1) == '\n' then trim (n - 2) s
else if n >= 1 && Symbol.is_ascii_line_terminator (at (n - 1)) then trim (n - 1) s
else s
StringLike String where
space_explode :: Char -> String -> [String]
space_explode c = Split.split (Split.dropDelims (Split.whenElt (== c)))
trim_line :: String -> String
trim_line s = gen_trim_line (length s) (s !!) take s
StringLike Text where
space_explode :: Char -> Text -> [Text]
space_explode c str =
if Text.null str then []
else if Text.all (/= c) str then [str]
else map Text.pack $ space_explode c $ Text.unpack str
trim_line :: Text -> Text
trim_line s = gen_trim_line (Text.length s) (Text.index s) Text.take s
StringLike Lazy.Text where
space_explode :: Char -> Lazy.Text -> [Lazy.Text]
space_explode c str =
if Lazy.null str then []
else if Lazy.all (/= c) str then [str]
else map Lazy.pack $ space_explode c $ Lazy.unpack str
trim_line :: Lazy.Text -> Lazy.Text
trim_line = Lazy.fromStrict . trim_line . Lazy.toStrict
StringLike Bytes where
space_explode :: Char -> Bytes -> [Bytes]
space_explode c str =
if Bytes.null str then []
else if Bytes.all_char (/= c) str then [str]
else
explode (Bytes.unpack str)
where
explode rest =
case span (/= (Bytes.byte c)) rest of
(_, []) -> [Bytes.pack rest]
(prfx, _ : rest') -> Bytes.pack prfx : explode rest'
trim_line :: Bytes -> Bytes
trim_line s = gen_trim_line (Bytes.length s) (Bytes.char . Bytes.index s) Bytes.take s
StringLike a => STRING a where make_string :: a -> String
STRING String where make_string = id
STRING Text where make_string = Text.unpack
STRING Lazy.Text where make_string = Lazy.unpack
STRING Bytes where make_string = UTF8.decode
StringLike a => TEXT a where make_text :: a -> Text
TEXT String where make_text = Text.pack
TEXT Text where make_text = id
TEXT Lazy.Text where make_text = Lazy.toStrict
TEXT Bytes where make_text = UTF8.decode
StringLike a => BYTES a where make_bytes :: a -> Bytes
BYTES String where make_bytes = UTF8.encode
BYTES Text where make_bytes = UTF8.encode
BYTES Lazy.Text where make_bytes = UTF8.encode . Lazy.toStrict
BYTES Bytes where make_bytes = id
:: Show a => a -> Bytes
= make_bytes . show
:: Show a => a -> Text
= make_text . show
- strings -}
:: StringLike a => a -> Maybe a
s = if s == "" then Nothing else Just s
:: StringLike a => a -> a -> a -> a
lpar rpar str = lpar <> str <> rpar
:: StringLike a => a -> a
= enclose "\"" "\""
:: StringLike a => a -> [a] -> a
s = mconcat . separate s
:: StringLike a => [a] -> a
= space_implode " "
, commas_quote :: StringLike a => [a] -> a
= space_implode ", "
= commas . map quote
:: StringLike a => a -> [a]
= space_explode '\n'
:: StringLike a => [a] -> a
= space_implode "\n"
:: StringLike a => a -> [a]
= trim_line #> split_lines #> map trim_line
- getenv -}
:: Bytes -> IO Bytes
x = do
y <- lookupEnv (make_string x)
return $ make_bytes $ fromMaybe "" y
:: Bytes -> IO Bytes
x = do
y <- getenv x
if Bytes.null y then
errorWithoutStackTrace $ make_string ("Undefined Isabelle environment variable: " <> quote x)
else return y ›
Data.Word (Word8)
qualified Isabelle.Bytes as Bytes
Isabelle.Bytes (Bytes)
- type -}
Symbol = Bytes
:: Symbol
= ""
, not_eof :: Symbol -> Bool
= Bytes.null
= not . is_eof
- ASCII characters -}
:: Char -> Bool
c = 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
:: Char -> Bool
c = '0' <= c && c <= '9'
:: Char -> Bool
c = '0' <= c && c <= '9' || 'A' <= c && c <= 'F' || 'a' <= c && c <= 'f'
:: Char -> Bool
c = c == '_' || c == '\''
:: Char -> Bool
c = c `elem` (" \t\n\11\f\r" :: String)
:: Char -> Bool
c = c == '\r' || c == '\n'
:: Char -> Bool
c = is_ascii_letter c || is_ascii_digit c || is_ascii_quasi c
:: String -> Bool
s =
not (null s) && is_ascii_letter (head s) && all is_ascii_letdig s
- explode symbols: ASCII, UTF8, named -}
:: Word8 -> Bool
b = b >= 128
:: Word8 -> Bool
b = 128 <= b && b < 192
:: Word8 -> Bool
b = 128 <= b && b < 160
|>) :: a -> (a -> b) -> b
|> f = f x
:: Bytes -> [Symbol]
string = scan 0
where
byte = Bytes.index string
substring i j =
if i == j - 1 then Bytes.singleton (byte i)
else Bytes.pack (map byte [i .. j - 1])
n = Bytes.length string
test pred i = i < n && pred (byte i)
test_char pred i = i < n && pred (Bytes.char (byte i))
many pred i = if test pred i then many pred (i + 1) else i
maybe_char c i = if test_char (== c) i then i + 1 else i
maybe_ascii_id i =
if test_char is_ascii_letter i
then many (is_ascii_letdig . Bytes.char) (i + 1)
else i
scan i =
if i < n then
let
b = byte i
c = Bytes.char b
in
{-encoded newline-}
if c == '\r' then "\n" : scan (maybe_char '\n' (i + 1))
{-pseudo utf8: encoded ascii control-}
else if b == 192 && test is_utf8_control (i + 1) && not (test is_utf8 (i + 2))
then Bytes.singleton (byte (i + 1) - 128) : scan (i + 2)
{-utf8-}
else if is_utf8 b then
let j = many is_utf8_trailer (i + 1)
in substring i j : scan j
{-named symbol-}
else if c == '\\' && test_char (== '<') (i + 1) then
let j = (i + 2) |> maybe_char '^' |> maybe_ascii_id |> maybe_char '>'
in substring i j : scan j
{-single character-}
else Bytes.singleton b : scan (i + 1)
else [] ›
Isabelle.Library
qualified Isabelle.Properties as Properties
qualified Isabelle.Value as Value
qualified Isabelle.Bytes as Bytes
Isabelle.Bytes (Bytes)
- basic markup -}
T = (Bytes, Properties.T)
:: T
= ("", [])
:: T -> Bool
("", _) = True
_ = False
:: Properties.T -> T -> T
more_props (elem, props) =
(elem, fold_rev Properties.put more_props props)
:: Bytes -> T
name = (name, [])
:: Bytes -> Bytes -> Bytes -> T
name prop = \s -> (name, [(prop, s)])
- misc properties -}
:: Bytes
= ‹Markup.nameN›
:: Bytes -> T -> T
a = properties [(nameN, a)]
:: Bytes
= ‹Markup.xnameN›
:: Bytes -> T -> T
a = properties [(xnameN, a)]
:: Bytes
= ‹Markup.kindN›
- formal entities -}
:: Bytes
= ‹Markup.bindingN›
:: T
= markup_elem bindingN
:: Bytes
= ‹Markup.entityN›
:: Bytes -> Bytes -> T
kind name =
(entityN,
java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because "brackoff" is null
(if Bytes.null kind then [] else [(kindN, kind)]))
:: Bytes
= ‹Markup.defN›
:: Bytes
= ‹Markup.refN›
- completion -}
:: Bytes
= ‹Markup.completionN›
:: T
= markup_elem completionN
:: Bytes
= ‹Markup.no_completionN›
:: T
= markup_elem no_completionN
:: Bytes
= ‹Markup.blockN›
:: Bool -> Int -> T
c i =
(blockN,
java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because "brackoff" is null
(if i /= 0 then [(indentN, Value.print_int i)] else []))
:: Bytes
= ‹Markup.breakN›
:: Int -> Int -> T
w i =
(breakN,
java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because "brackoff" is null
(if i /= 0 then [(indentN, Value.print_int i)] else []))
:: Bytes
= ‹Markup.fbreakN›
:: T
= markup_elem fbreakN
:: Bytes
= ‹Markup.itemN›
:: T
= markup_elem itemN
- text properties -}
:: Bytes
= ‹Markup.wordsN›
:: T
= markup_elem wordsN
- inner syntax -}
:: Bytes
= ‹Markup.tfreeN›
:: T
= markup_elem tfreeN
:: Bytes
= ‹Markup.tvarN›
:: T
= markup_elem tvarN
:: Bytes
= ‹Markup.freeN›
:: T
= markup_elem freeN
:: Bytes
= ‹Markup.skolemN›
:: T
= markup_elem skolemN
:: Bytes
= ‹Markup.boundN›
:: T
= markup_elem boundN
:: Bytes
= ‹Markup.varN›
:: T
= markup_elem varN
:: Bytes
= ‹Markup.numeralN›
:: T
= markup_elem numeralN
:: Bytes
= ‹Markup.literalN›
:: T
= markup_elem literalN
:: Bytes
= ‹Markup.delimiterN›
:: T
= markup_elem delimiterN
:: Bytes
= ‹Markup.inner_stringN›
:: T
= markup_elem inner_stringN
:: Bytes
= ‹Markup.inner_cartoucheN›
:: T
= markup_elem inner_cartoucheN
:: Bytes
= ‹Markup.token_rangeN›
:: T
= markup_elem token_rangeN
:: Bytes
= ‹Markup.sortingN›
:: T
= markup_elem sortingN
:: Bytes
= ‹Markup.typingN›
:: T
= markup_elem typingN
:: Bytes
= ‹Markup.class_parameterN›
:: T
= markup_elem class_parameterN
- antiquotations -}
:: Bytes
= ‹Markup.antiquotedN›
:: T
= markup_elem antiquotedN
:: Bytes
= ‹Markup.antiquoteN›
:: T
= markup_elem antiquoteN
- text structure -}
:: Bytes
= ‹Markup.paragraphN›
:: T
= markup_elem paragraphN
:: Bytes
= ‹Markup.text_foldN›
:: T
= markup_elem text_foldN
- outer syntax -}
:: Bytes
= ‹Markup.keyword1N›
:: T
= markup_elem keyword1N
:: Bytes
= ‹Markup.keyword2N›
:: T
= markup_elem keyword2N
:: Bytes
= ‹Markup.keyword3N›
:: T
= markup_elem keyword3N
:: Bytes
= ‹Markup.quasi_keywordN›
:: T
= markup_elem quasi_keywordN
:: Bytes
= ‹Markup.improperN›
:: T
= markup_elem improperN
:: Bytes
= ‹Markup.operatorN›
:: T
= markup_elem operatorN
:: Bytes
= ‹Markup.stringN›
:: T
= markup_elem stringN
:: Bytes
= ‹Markup.alt_stringN›
:: T
= markup_elem alt_stringN
:: Bytes
= ‹Markup.verbatimN›
:: T
= markup_elem verbatimN
:: Bytes
= ‹Markup.cartoucheN›
:: T
= markup_elem cartoucheN
:: Bytes
= ‹Markup.commentN›
:: T
= markup_elem commentN
- comments -}
:: Bytes
= ‹Markup.comment1N›
:: T
= markup_elem comment1N
:: Bytes
= ‹Markup.comment2N›
:: T
= markup_elem comment2N
:: Bytes
= ‹Markup.comment3N›
:: T
= markup_elem comment3N
positions starting from 1; values <= 0 mean "absent". Count Isabelle
, not UTF8 bytes nor UTF16 characters. Position range specifies a
-open interval offset .. end_offset (exclusive).
Prelude hiding (id)
Data.Maybe (isJust, fromMaybe)
Data.Bifunctor (first)
qualified Isabelle.Properties as Properties
qualified Isabelle.Bytes as Bytes
qualified Isabelle.Value as Value
Isabelle.Bytes (Bytes)
qualified Isabelle.Markup as Markup
qualified Isabelle.YXML as YXML
Isabelle.Library
qualified Isabelle.Symbol as Symbol
Isabelle.Symbol (Symbol)
Isabelle.Library
qualified Isabelle.Properties as Properties
qualified Isabelle.Markup as Markup
qualified Isabelle.Buffer as Buffer
qualified Isabelle.Bytes as Bytes
Isabelle.Bytes (Bytes)
- types -}
Attributes = Properties.T
Body = [Tree]
Tree = Elem (Markup.T, Body) | Text Bytes
:: Tree -> Buffer.T -> Buffer.T
tree =
case unwrap_elem tree of
Just (_, ts) -> fold add_content ts
Nothing ->
case tree of
Elem (_, ts) -> fold add_content ts
Text s -> Buffer.add s
:: Body -> Bytes
= Buffer.build_content . fold add_content
Isabelle.Library
qualified Isabelle.Bytes as Bytes
Isabelle.Bytes (Bytes)
qualified Isabelle.Markup as Markup
qualified Isabelle.XML as XML
qualified Isabelle.Buffer as Buffer
qualified Isabelle.Bytes as Bytes
qualified Isabelle.Name as Name
Isabelle.Name (Name)
qualified Isabelle.Properties as Properties
qualified Isabelle.Markup as Markup
Isabelle.XML.Classes
qualified Isabelle.XML as XML
qualified Isabelle.YXML as YXML
Names = [(Name, (Name, Name))] -- external name, kind, internal name
T = Completion Properties.T Int Names -- position, total length, names
:: Int -> Properties.T -> Names -> T
limit props names = Completion props (length names) (take limit names)
:: T
= names 0 [] []
:: Int -> (Name, Properties.T) -> ((Name -> Bool) -> Names) -> T
limit (name, props) make_names =
if name /= "" && name /= "_" then
names limit props (make_names (Bytes.isPrefixOf (Name.clean name)))
else none
:: T -> (Markup.T, XML.Body)
(Completion props total names) =
if not (null names) then
(Markup.properties props Markup.completion, encode (total, names))
else (Markup.empty, [])
qualified Isabelle.Bytes as Bytes
Isabelle.Bytes (Bytes)
Isabelle.Library hiding (enclose, quote, separate, commas)
qualified Isabelle.Buffer as Buffer
qualified Isabelle.Markup as Markup
qualified Isabelle.XML as XML
qualified Isabelle.YXML as YXML
T =
Block Markup.T Bool Int [T]
| Break Int Int
| Str Bytes
- output -}
s = if Bytes.null s then [] else [XML.Text s]
markup body =
if Markup.is_empty markup then body
else [XML.Elem (markup, body)]
:: T -> XML.Body
(Block markup consistent indent prts) =
concatMap symbolic prts
|> symbolic_markup block_markup
|> symbolic_markup markup
where block_markup = if null prts then Markup.empty else Markup.block consistent indent
(Break wd ind) = [XML.Elem (Markup.break wd ind, symbolic_text (Bytes.spaces wd))]
(Str s) = symbolic_text s
:: T -> Bytes
= YXML.string_of_body . symbolic
:: T -> Bytes
= Buffer.build_content . out
where
out (Block markup _ _ prts) =
let (bg, en) = YXML.output_markup markup
in Buffer.add bg #> fold out prts #> Buffer.add en
out (Break _ wd) = Buffer.add (Bytes.spaces wd)
out (Str s) = Buffer.add s
- derived operations to create formatting expressions -}
n | n < 0 = 0
n = n
:: BYTES a => a -> T
= Str . make_bytes
:: Int -> Int -> T
wd ind = Break (force_nat wd) ind
:: [Name] -> Context
used = fold declare used context
- generating fresh names -}
:: Name -> Name
str = str <> "a"
:: Name -> Name
str =
let
a = Bytes.byte 'a'
z = Bytes.byte 'z'
bump (b : bs) | b == z = a : bump bs
bump (b : bs) | a <= b && b < z = b + 1 : bs
bump bs = a : bs
:: Free -> Term -> Term
(name, typ) body = Abs (name, typ, abstract 0 body)
where
abstract lev (Free (x, ty)) | name == x && typ == ty = Bound lev
abstract lev (Abs (a, ty, t)) = Abs (a, ty, abstract (lev + 1) t)
abstract lev (App (t, u)) = App (abstract lev t, abstract lev u)
abstract _ t = t
:: Term -> Name.Context -> Name.Context
(Free (x, _)) = Name.declare x
(Abs (_, _, b)) = declare_frees b
(App (t, u)) = declare_frees t #> declare_frees u
_ = id
:: Int -> Term -> Term
inc = if inc == 0 then id else incr 0
where
incr lev (Bound i) = if i >= lev then Bound (i + inc) else Bound i
incr lev (Abs (a, ty, b)) = Abs (a, ty, incr (lev + 1) b)
incr lev (App (t, u)) = App (incr lev t, incr lev u)
incr _ t = t
:: Term -> Term -> Term
arg = subst 0
where
subst lev (Bound i) =
if i < lev then Bound i
else if i == lev then incr_boundvars lev arg
else Bound (i - 1)
subst lev (Abs (a, ty, b)) = Abs (a, ty, subst (lev + 1) b)
subst lev (App (t, u)) = App (subst lev t, subst lev u)
subst _ t = t
:: Name.Context -> Term -> Maybe (Free, Term)
names (Abs (x, ty, b)) =
let
(x', _) = Name.variant x (declare_frees b names)
v = (x', ty)
in Just (v, subst_bound (Free v) b)
_ _ = Nothing
:: Name.Context -> Term -> ([Free], Term)
names tm =
case dest_lambda names tm of
Just (v, t) ->
let (vs, t') = strip_lambda names t'
in (v : vs, t')
Nothing -> ([], tm)
- type and term operators -}
:: Name -> (Typ, Typ -> Bool)
name = (mk, is)
where
mk = Type (name, [])
is (Type (c, _)) = c == name
is _ = False
:: Name -> (Typ -> Typ, Typ -> Maybe Typ)
name = (mk, dest)
where
mk ty = Type (name, [ty])
dest (Type (c, [ty])) | c == name = Just ty
dest _ = Nothing
:: Name -> (Typ -> Typ -> Typ, Typ -> Maybe (Typ, Typ))
name = (mk, dest)
where
mk ty1 ty2 = Type (name, [ty1, ty2])
dest (Type (c, [ty1, ty2])) | c == name = Just (ty1, ty2)
dest _ = Nothing
:: Name -> (Term, Term -> Bool)
name = (mk, is)
where
mk = Const (name, [])
is (Const (c, _)) = c == name
is _ = False
:: Name -> (Term -> Term, Term -> Maybe Term)
name = (mk, dest)
where
mk t = App (Const (name, []), t)
dest (App (Const (c, _), t)) | c == name = Just t
dest _ = Nothing
:: Name -> (Term -> Term -> Term, Term -> Maybe (Term, Term))
name = (mk, dest)
where
mk t u = App (App (Const (name, []), t), u)
dest (App (App (Const (c, _), t), u)) | c == name = Just (t, u)
dest _ = Nothing
:: Name -> (Typ -> Term, Term -> Maybe Typ)
name = (mk, dest)
where
mk ty = Const (name, [ty])
dest (Const (c, [ty])) | c == name = Just ty
dest _ = Nothing
:: Name -> (Typ -> Term -> Term, Term -> Maybe (Typ, Term))
name = (mk, dest)
where
mk ty t = App (Const (name, [ty]), t)
dest (App (Const (c, [ty]), t)) | c == name = Just (ty, t)
dest _ = Nothing
:: Name -> (Typ -> Term -> Term -> Term, Term -> Maybe (Typ, Term, Term))
name = (mk, dest)
where
mk ty t u = App (App (Const (name, [ty]), t), u)
dest (App (App (Const (c, [ty]), t), u)) | c == name = Just (ty, t, u)
dest _ = Nothing
:: Name -> (Free -> Term -> Term, Name.Context -> Term -> Maybe (Free, Term))
name = (mk, dest)
where
mk (a, ty) b = App (Const (name, [ty]), lambda (a, ty) b)
dest names (App (Const (c, _), t)) | c == name = dest_lambda names t
dest _ _ = Nothing
:: P Indexname
(a, b) = if b == 0 then [a] else [a, int_atom b]
:: T Sort
= list string
:: T Typ
ty =
ty |> variant
[\case { Type (a, b) -> Just ([a], list typ b); _ -> Nothing }, \case { TFree (a, b) -> Just ([a], sort b); _ -> Nothing }, \case { TVar (a, b) -> Just (indexname a, sort b); _ -> Nothing }]
:: T Typ
ty = if is_dummyT ty then [] else typ ty
:: T Term
t =
t |> variant
[\case { Const (a, b) -> Just ([a], list typ b); _ -> Nothing }, \case { Free (a, b) -> Just ([a], var_type b); _ -> Nothing }, \case { Var (a, b) -> Just (indexname a, var_type b); _ -> Nothing }, \case { Bound a -> Just ([], int a); _ -> Nothing }, \case { Abs (a, b, c) -> Just ([a], pair typ term (b, c)); _ -> Nothing }, \case { App a -> Just ([], pair term term a); _ -> Nothing }, \case { OFCLASS (a, b) -> Just ([b], typ a); _ -> Nothing }] ›
:: P Indexname
[a] = (a, 0)
[a, b] = (a, int_atom b)
:: T Sort
= list string
:: T Typ
ty =
ty |> variant
[\([a], b) -> Type (a, list typ b), \([a], b) -> TFree (a, sort b), \(a, b) -> TVar (indexname a, sort b)]
:: T Typ
[] = dummyT
body = typ body
:: T Term
t =
t |> variant
[\([a], b) -> Const (a, list typ b), \([a], b) -> Free (a, var_type b), \(a, b) -> Var (indexname a, var_type b), \([], a) -> Bound (int a), \([a], b) -> let (c, d) = pair typ term b in Abs (a, c, d), \([], a) -> App (pair term term a), \([a], b) -> OFCLASS (typ b, a)] ›
generate_file "Isabelle/XML/Classes.hs" = ‹
- generated by Isabelle -}
qualified Isabelle.XML as XML
qualified Isabelle.XML.Encode as Encode
qualified Isabelle.XML.Decode as Decode
qualified Isabelle.Term_XML.Encode as Encode
qualified Isabelle.Term_XML.Decode as Decode
qualified Isabelle.Properties as Properties
Isabelle.Bytes (Bytes)
Isabelle.Term (Typ, Term)
Encode_Atom a where encode_atom :: Encode.A a
Decode_Atom a where decode_atom :: Decode.A a
Encode_Atom Int where encode_atom = Encode.int_atom
Decode_Atom Int where decode_atom = Decode.int_atom
Encode_Atom Bool where encode_atom = Encode.bool_atom
Decode_Atom Bool where decode_atom = Decode.bool_atom
Encode_Atom () where encode_atom = Encode.unit_atom
Decode_Atom () where decode_atom = Decode.unit_atom
Encode a where encode :: Encode.T a
Decode a where decode :: Decode.T a
Encode Bytes where encode = Encode.string
Decode Bytes where decode = Decode.string
Encode Int where encode = Encode.int
Decode Int where decode = Decode.int
Encode Bool where encode = Encode.bool
Decode Bool where decode = Decode.bool
Encode () where encode = Encode.unit
Decode () where decode = Decode.unit
(Encode a, Encode b) => Encode (a, b)
where encode = Encode.pair encode encode
(Decode a, Decode b) => Decode (a, b)
where decode = Decode.pair decode decode
(Encode a, Encode b, Encode c) => Encode (a, b, c)
where encode = Encode.triple encode encode encode
(Decode a, Decode b, Decode c) => Decode (a, b, c)
where decode = Decode.triple decode decode decode
Encode a => Encode [a] where encode = Encode.list encode
Decode a => Decode [a] where decode = Decode.list decode
Encode a => Encode (Maybe a) where encode = Encode.option encode
Decode a => Decode (Maybe a) where decode = Decode.option decode
Encode XML.Tree where encode = Encode.tree
Decode XML.Tree where decode = Decode.tree
Encode Properties.T where encode = Encode.properties
Decode Properties.T where decode = Decode.properties
Encode Typ where encode = Encode.typ
Decode Typ where decode = Decode.typ
Encode Term where encode = Encode.term
Decode Term where decode = Decode.term ›
Prelude hiding (read)
Data.Maybe
qualified Data.ByteString as ByteString
qualified Isabelle.Bytes as Bytes
Isabelle.Bytes (Bytes)
qualified Isabelle.Symbol as Symbol
qualified Isabelle.UTF8 as UTF8
qualified Isabelle.XML as XML
qualified Isabelle.YXML as YXML
Network.Socket (Socket)
qualified Network.Socket.ByteString as Socket
Isabelle.Library
qualified Isabelle.Value as Value
:: Socket -> Int -> IO Bytes
socket n = read_body 0 []
where
result = Bytes.concat . reverse
read_body len ss =
if len >= n then return (result ss)
else
(do
s <- Socket.recv socket (min (n - len) 8192)
case ByteString.length s of
0 -> return (result ss)
m -> read_body (len + m) (Bytes.make s : ss))
:: Socket -> Int -> IO (Maybe Bytes, Int)
socket n = do
msg <- read socket n
let len = Bytes.length msg
return (if len == n then Just msg else Nothing, len)
:: Socket -> IO (Maybe Bytes)
socket = read_body []
where
result = trim_line . Bytes.pack . reverse
read_body bs = do
s <- Socket.recv socket 1
case ByteString.length s of
0 -> return (if null bs then Nothing else Just (result bs))
1 ->
case ByteString.head s of
10 -> return (Just (result bs))
b -> read_body (b : bs)
- messages with multiple chunks (arbitrary content) -}
:: Bytes -> [Int]
line =
let
res = map Value.parse_nat (space_explode ',' line)
in
if all isJust res then map fromJust res
else error ("Malformed message header: " <> quote (UTF8.decode line))
:: Socket -> Int -> IO Bytes
socket n = do
res <- read_block socket n
return $
case res of
(Just chunk, _) -> chunk
(Nothing, len) ->
java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because "brackoff" is null
show len <> " of " <> show n <> " bytes")
:: Socket -> IO (Maybe [Bytes])
socket = do
res <- read_line socket
case res of
Just line -> Just 🪙 mapM (read_chunk socket) (parse_header line)
Nothing -> return Nothing
:: Bytes -> [Bytes]
msg =
let n = Bytes.length msg in
if is_length msg || is_terminated msg then
error ("Bad content for line message:\n" <> take 100 (UTF8.decode msg))
else
(if n > 100 || Bytes.any_char (== '\n') msg then make_header [n + 1] else []) <> [msg, "\n"]
:: Socket -> IO (Maybe Bytes)
socket = do
opt_line <- read_line socket
case opt_line of
Nothing -> return Nothing
Just line ->
case Value.parse_nat line of
Nothing -> return $ Just line
Just n -> fmap trim_line . fst 🪙 read_block socket n
:: Socket -> IO (Maybe XML.Body)
socket = do
res <- read_line_message socket
return (YXML.parse_body 🪙 res)
qualified Data.List as List
Control.Monad (when, forM_)
Data.Map.Strict (Map)
qualified Data.Map.Strict as Map
Control.Exception as Exception
Control.Concurrent (ThreadId)
qualified Control.Concurrent as Concurrent
Control.Concurrent.Thread (Result)
qualified Control.Concurrent.Thread as Thread
qualified Isabelle.UUID as UUID
qualified Isabelle.Properties as Properties
- thread info -}
Resources = Map Unique (IO ())
Info = Info {uuid :: UUID.T, props :: Properties.T, stopped :: Bool, resources :: Resources}
Infos = Map ThreadId Info
:: Infos -> ThreadId -> Maybe Info
infos id = Map.lookup id infos
:: ThreadId -> IO (Maybe Info)
id = do
state <- readIORef global_state
return $ lookup_info state id
:: ThreadId -> (Info -> Info) -> IO (Maybe Info)
id f =
atomicModifyIORef' global_state
(\infos ->
case lookup_info infos id of
Nothing -> (infos, Nothing)
Just info ->
let info' = f info
in (Map.insert id info' infos, Just info'))
:: ThreadId -> IO ()
id =
atomicModifyIORef' global_state (\infos -> (Map.delete id infos, ()))
- thread properties -}
:: IO (Maybe Info)
= do
id <- Concurrent.myThreadId
get_info id
:: IO Properties.T
= maybe [] props 🪙 my_info
:: (Properties.T -> Properties.T) -> IO ()
f = do
id <- Concurrent.myThreadId
map_info id (\info -> info {props = f (props info)})
return ()
- managed resources -}
:: IO () -> IO Unique
resource = do
id <- Concurrent.myThreadId
u <- newUnique
map_info id (\info -> info {resources = Map.insert u resource (resources info)})
return u
:: Unique -> IO ()
u = do
id <- Concurrent.myThreadId
map_info id (\info -> info {resources = Map.delete u (resources info)})
return ()
:: IO () -> IO a -> IO a
resource body =
Exception.bracket (add_resource resource) del_resource (const body)
- stop -}
:: IO Bool
= maybe False stopped 🪙 my_info
:: IO ()
= do
stopped <- is_stopped
when stopped $ throw ThreadKilled
:: ThreadId -> IO ()
id = do
info <- map_info id (\info -> info {stopped = True})
let ops = case info of Nothing -> []; Just Info{resources} -> map snd (Map.toDescList resources)
sequence_ ops
- UUID -}
:: IO (Maybe UUID.T)
= fmap uuid 🪙 my_info
:: UUID.T -> IO ()
uuid = do
id <- find_id uuid
forM_ id stop
- fork -}
Fork a = (ThreadId, UUID.T, IO (Result a))
:: IO a -> (Either SomeException a -> IO b) -> IO (Fork b)
body finally = do
uuid <- UUID.random
java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because "brackoff" is null
Exception.mask (\restore ->
Thread.forkIO
(Exception.try
(do
id <- Concurrent.myThreadId
atomicModifyIORef' global_state (init_info id uuid)
restore body)
>>= (\res -> do id <- Concurrent.myThreadId; delete_info id; finally res)))
return (id, uuid, result)
:: IO a -> IO (Fork a)
body = fork_finally body Thread.result ›
Control.Monad (forever, when)
qualified Control.Exception as Exception
Network.Socket (Socket)
qualified Network.Socket as Socket
qualified System.IO as IO
qualified Data.ByteString.Char8 as Char8
Isabelle.Library
qualified Isabelle.Bytes as Bytes
Isabelle.Bytes (Bytes)
qualified Isabelle.UUID as UUID
qualified Isabelle.Byte_Message as Byte_Message
qualified Isabelle.Isabelle_Thread as Isabelle_Thread
Eq Time where Time a == Time b = a == b
Ord Time where compare (Time a) (Time b) = compare a b
Num Time where
fromInteger = Time . fromInteger
Time a + Time b = Time (a + b)
Time a - Time b = Time (a - b)
Time a * Time b = Time (a * b)
abs (Time a) = Time (abs a)
signum (Time a) = Time (signum a)
:: Double -> Time
s = Time (round (s * 1000.0))
:: Double -> Time
m = Time (round (m * 60000.0))
:: Int -> Time
= Time
:: Time
= ms 0
:: Time -> Bool
(Time ms) = ms == 0
:: Time -> Bool
(Time ms) = ms >= 1
:: Time -> Double
(Time ms) = fromIntegral ms / 1000.0
:: Time -> Double
(Time ms) = fromIntegral ms / 60000.0
:: Time -> Int
(Time ms) = ms
Show Time where
show t = printf "%.3f" (get_seconds t)
:: Time -> Bytes
t = make_bytes (show t) <> "s"
:: IO Time
= do
t <- getPOSIXTime
return $ Time (round (realToFrac t * 1000.0 :: Double)) ›
Text.Printf (printf)
qualified Isabelle.Symbol as Symbol
qualified Isabelle.Bytes as Bytes
Isabelle.Bytes (Bytes)
qualified Isabelle.Time as Time
Isabelle.Time (Time)
Isabelle.Library
- concrete syntax -}
:: Bytes -> Bytes
str =
if Bytes.null str then "\"\""
else str |> Bytes.unpack |> map trans |> Bytes.concat
where
trans b =
case Bytes.char b of
'\t' -> "$'\\t'"
'\n' -> "$'\\n'"
'\f' -> "$'\\f'"
'\r' -> "$'\\r'"
c ->
if Symbol.is_ascii_letter c || Symbol.is_ascii_digit c || c `elem` ("+,-./:_" :: String)
then Bytes.singleton b
else if b < 32 || b >= 127 then make_bytes (printf "$'\\x%02x'" b :: String)
else "\\" <> Bytes.singleton b
qualified Data.Map.Strict as Map
Data.Map.Strict (Map)
qualified Isabelle.Properties as Properties
Isabelle.Bytes (Bytes)
qualified Isabelle.Value as Value
qualified Isabelle.Time as Time
Isabelle.Time (Time)
Isabelle.Library
qualified Isabelle.XML.Decode as Decode
Isabelle.XML.Classes (Decode (..))
:: T -> Bytes -> Opt
(Options map) name =
case Map.lookup name map of
Just opt | _typ opt /= unknownT -> opt
_ -> error (make_string ("Unknown system option " <> quote name))
:: T -> Bytes -> Bytes -> Opt
options name typ =
let
opt = check_name options name
t = _typ opt
in
if t == typ then opt
else error (make_string ("Ill-typed system option " <> quote name <> " : " <> t <> " vs. " <> typ))
- get typ -}
:: T -> Bytes -> Bytes
options name = _typ (check_name options name)
- get value -}
:: Bytes -> (Bytes -> Maybe a) -> T -> Bytes -> a
typ parse options name =
let opt = check_type options name typ in
case parse (_value opt) of
Just x -> x
Nothing ->
java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because "brackoff" is null
" : " <> typ <> " =\n" <> quote (_value opt)))
:: T -> Bytes -> Bool
= get boolT Value.parse_bool
:: T -> Bytes -> Int
= get intT Value.parse_int
:: T -> Bytes -> Double
= get realT Value.parse_real
:: T -> Bytes -> Time
options = Time.seconds . real options
:: T -> Bytes -> Bytes
= get stringT Just
- decode -}
Decode T where
decode :: Decode.T T
decode =
let
decode_entry :: Decode.T (Bytes, Opt)
decode_entry body =
let
(pos, (name, (typ, value))) =
Decode.pair Decode.properties (Decode.pair Decode.string (Decode.pair Decode.string Decode.string)) body
in (name, Opt { _pos = pos, _name = name, _typ = typ, _value = value })
in Options . Map.fromList . Decode.list decode_entry ›
Data.Maybe (fromMaybe)
Control.Exception (throw, AsyncException (UserInterrupt))
Network.Socket (Socket)
qualified Isabelle.Bytes as Bytes
Isabelle.Bytes (Bytes)
qualified Isabelle.Byte_Message as Byte_Message
qualified Isabelle.Time as Time
Isabelle.Timing (Timing (..))
qualified Isabelle.Options as Options
qualified Isabelle.Bash as Bash
qualified Isabelle.Process_Result as Process_Result
qualified Isabelle.XML.Encode as Encode
qualified Isabelle.YXML as YXML
qualified Isabelle.Value as Value
qualified Isabelle.Server as Server
qualified Isabelle.Isabelle_Thread as Isabelle_Thread
Isabelle.Library
:: Bytes -> Bytes -> Bash.Params -> IO Process_Result.T
address password params = do
Server.connection port password
(\socket -> do
isabelle_tmp <- getenv "ISABELLE_TMP"
Byte_Message.write_message socket (run isabelle_tmp)
loop Nothing socket)
where
port =
case Bytes.try_unprefix Server.localhost_prefix address of
Just port -> make_string port
Nothing -> errorWithoutStackTrace "Bad bash_process server address"
kill :: Maybe Bytes -> IO ()
kill maybe_uuid = do
case maybe_uuid of
Just uuid ->
Server.connection port password (\socket ->
Byte_Message.write_message socket [Bash.server_kill, uuid])
Nothing -> return ()
err = errorWithoutStackTrace "Malformed result from bash_process server"
the = fromMaybe err
loop :: Maybe Bytes -> Socket -> IO Process_Result.T
loop maybe_uuid socket = do
result <- Isabelle_Thread.bracket_resource (kill maybe_uuid) (Byte_Message.read_message socket)
case result of
Just [head, uuid] | head == Bash.server_uuid -> loop (Just uuid) socket
Just [head] | head == Bash.server_interrupt -> throw UserInterrupt
Just [head, msg] | head == Bash.server_failure -> errorWithoutStackTrace $ make_string msg
Just (head : a : b : c : d : lines) | head == Bash.server_result ->
let
rc = the $ Value.parse_int a
elapsed = Time.ms $ the $ Value.parse_int b
cpu = Time.ms $ the $ Value.parse_int c
timing = Timing elapsed cpu Time.zero
n = the $ Value.parse_int d
out_lines = take n lines
err_lines = drop n lines
in return $ Process_Result.make rc out_lines err_lines timing
_ -> err ›
Prelude hiding (init)
Data.IORef
Data.Map.Strict (Map)
qualified Data.Map.Strict as Map
qualified Data.List as List
Isabelle.Time (Time)
qualified Isabelle.Time as Time
Entry v = Entry {_value :: v, _access :: Time, _timing :: Time}
T k v = Cache (IORef (Map k (Entry v)))
:: IO (T k v)
= Cache 🪙 newIORef Map.empty
:: Ord k => T k v -> k -> Entry v -> IO v
(Cache ref) x e = do
atomicModifyIORef' ref (\entries ->
let
entry =
case Map.lookup x entries of
Just e' | _access e' > _access e -> e'
_ -> e
in (Map.insert x entry entries, _value entry))
:: Ord k => T k v -> k -> IO v -> IO v
cache@(Cache ref) x body = do
start <- Time.now
entries <- readIORef ref
case Map.lookup x entries of
Just entry -> do
commit cache x (entry {_access = start})
Nothing -> do
y <- body
stop <- Time.now
commit cache x (Entry y start (stop - start))
:: Ord k => T k v -> Int -> Time -> IO ()
(Cache ref) max_size min_timing = do
atomicModifyIORef' ref (\entries ->
let
sort = List.sortBy (\(_, e1) (_, e2) -> compare (_access e2) (_access e1))
entries1 = Map.filter (\e -> _timing e >= min_timing) entries
entries2 =
if Map.size entries1 <= max_size then entries1
else Map.fromList $ List.take max_size $ sort $ Map.toList entries1
in (entries2, ())) ›
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.