pax_global_header00006660000000000000000000000064147601740260014521gustar00rootroot0000000000000052 comment=98d038bba0a481deb1bd03c3e05c5abd5d48be73 coq-simple-io-1.11.0/000077500000000000000000000000001476017402600142575ustar00rootroot00000000000000coq-simple-io-1.11.0/.circleci/000077500000000000000000000000001476017402600161125ustar00rootroot00000000000000coq-simple-io-1.11.0/.circleci/config.yml000066400000000000000000000044111476017402600201020ustar00rootroot00000000000000version: 2.1 jobs: test: parameters: coq: type: string docker: - image: <> resource_class: large environment: OPAMJOBS: 4 OPAMVERBOSE: 1 OPAMWITHTEST: true OPAMYES: true TERM: xterm DEPENDANTS: | coq-itree-io coq-quickchick coq-freespec-ffi coq-bonsai steps: - startup - build commands: startup: steps: - checkout - run: name: Configure environment command: echo . ~/.profile >> $BASH_ENV - run: name: Install dependencies command: | opam update opam pin add --kind=path . -n # Make opam aware of our dependency constraints opam install --deps-only . opam list no_output_timeout: 30m build: steps: - run: name: Build, test, and install command: opam install . -j4 # gets killed at -j 35 by default - run: name: Test dependants command: | for PACKAGE in $DEPENDANTS do DEPS_FAILED=false opam install --deps-only $PACKAGE || DEPS_FAILED=true ([ $DEPS_FAILED == true ] && echo Skipping $PACKAGE) || \ (opam install -t $PACKAGE && echo Tested $PACKAGE) done - run: name: Uninstall and cleanup command: | opam uninstall . make clean ls -AGR -I .git workflows: version: 2 build: jobs: - test: name: 'Coq 8.12' coq: 'coqorg/coq:8.12-ocaml-4.11-flambda' - test: name: 'Coq 8.13' coq: 'coqorg/coq:8.13-ocaml-4.13-flambda' - test: name: 'Coq 8.14' coq: 'coqorg/coq:8.14-ocaml-4.14-flambda' - test: name: 'Coq 8.15' coq: 'coqorg/coq:8.15-ocaml-4.14-flambda' - test: name: 'Coq 8.16' coq: 'coqorg/coq:8.16' - test: name: 'Coq 8.17' coq: 'coqorg/coq:8.17' - test: name: 'Coq 8.18' coq: 'coqorg/coq:8.18' - test: name: 'Coq 8.19' coq: 'coqorg/coq:8.19' - test: name: 'Coq 8.20' coq: 'coqorg/coq:8.20' - test: name: 'Coq dev' coq: 'rocq/rocq-prover:dev' coq-simple-io-1.11.0/.gitattributes000066400000000000000000000001441476017402600171510ustar00rootroot00000000000000*.ml.cppo linguist-language=OCaml *.mlg.cppo linguist-language=OCaml *.v.cppo linguist-language=Coq coq-simple-io-1.11.0/.gitignore000066400000000000000000000005671476017402600162570ustar00rootroot00000000000000META _CoqProject src/SimpleIO_Plugin.v src/IO_Stdlib.v src/IO_String.v src/IO_RawChar.v src/IO_Filename.v src/IO_Float.v src/IO_Unsafe.v plugin/META.coq-simple-io test/TestInt63.v .coqdeps.d *~ *.coq.d *.vok *.vos *.v.d *.vo *.aux *.glob *.a *.o *.cm* *.ml *.ml.d *.mli.d *.mlg.d *.mlpack.d build _build deps.dot deps.jpg Makefile.coq Makefile.coq.conf doc/ html/ .DS_Store coq-simple-io-1.11.0/CHANGELOG.md000066400000000000000000000070431476017402600160740ustar00rootroot00000000000000# 1.11.0 - Add option `RunIO IOMode Forward` to forward stdin and stdout of the extracted executable to the coqc process, allowing IO actions to be run as interactive command-line scripts. - Fix a file system race: when multiple `RunIO` commands ran concurrently in the same folder, they used the same local `__qc_tmp` temporary file, clobbering each other. # 1.10.0 - Compatibility with Coq 8.20 # 1.9.0 - Add `RunIO Reset` - Rename `RunIO Builder Basic` to `RunIO Builder Ocamlfind` - Extend `RunIO Builder` commands with an optional string to pass to the build executable. Example: `RunIO Builder Ocamlfind "-I mydir"`. - Add `IO_Random.init`. # 1.8.0 - Redesign `RunIO` auxiliary commands for configuring extraction. + `RunIO Include "dir".` copies `dir` when compiling package. + `RunIO Open "M".` prefixes the extracted OCaml file with `open M`. + `RunIO Package "pkg".` adds `pkg` when compiling with `ocamlfind opt` or `ocamlbuild`. + `RunIO Builder Basic.` (default) compiles using `ocamlfind opt`. + `RunIO Builder Ocamlbuild.` compiles using `ocamlbuild`. + `RunIO Builder Dune.` compiles using `dune`. This ignores `RunIO Package`; dependencies should be specified in the `dune` file. + `RunIO Smart (On|Off).` (`On` by default) enable|disable automatic detection of common package dependencies (currently `zarith` for `Big_Int_Z` and `coq-core.kernel` for `Uint63`). - Add `IO_Filename`. - Use `dune` for building. # 1.7.0 - Fix definitions of `catch_not_found`, `catch_sys_error` - Add: + `IO_Exceptions.catch_any_exc` + in `Stdlib`: `input`, `really_input`, `really_input_string` + `IO_Sys.OSys.argv`. # 1.6.0 - Add `RunIO` command to compile and run executables from a Coq file - Rename `Pervasives` to `Stdlib` in extracted code (for OCaml >= 4.08) - Add new definitions from the stdlib: + `IO_Stdlib.close_out_noerr` + `IO_Stdlib.close_in_noerr` + `IO_Stdlib.in_channel_length` + `IO_Exceptions.catch_sys_error` + `IO_Sys.OSys.command` # 1.5.0 - Add `IO_MonadFix` with the `MonadFix` instance in its own module. - Add float arithmeti. - Add `Bytes.sub`, `Unix.getaddrinfo`, `Sys.time` (and related definitions) # 1.4.0 - Remove instance `MonadFix_IO` (was causing universe inconsistencies) - Add in `Unix`: + `inet_addr_of_string`, `string_of_inet_addr` + `socket_bool_option`, `getsockopt`, setsockopt` + `error_message` # 1.3.0 - Fix the extraction of core `IO` constants with type annotations to avoid type errors caused by the value restriction. - Add `IO_Sys`, based on `Sys` from the OCaml stdlib. - Add `file_descr_eqb` and `select` in `IO_Unix`. - Fix extraction of `error` and `catch_error` in `IO_Unix`. - Update `IO.Notations` to agree with *coq-ext-lib* 0.11.1 # 1.2.1 - Blacklisted `List` # 1.2.0 - Added module `IO_Float` - Added `OString.escaped`, `OUnix.setsock_timeout`, `OUnix.error`, `OUnix.catch_error`, `OUnix.raise_error` - Fixed extraction of `OBytes.set` - Changed `IO_Unix.recv` to no longer return the input buffer - Changed `OBytes.to_string` and `OBytes.from_string` to be `IO` actions instead of pure functions # 1.1.0 - Added `IO_Stdlib`, `IO_Bytes`, `IO_Random`, `IO_Unix` # 1.0.0 - Big rewrite - `IO a` is now `('a -> Obj.t) -> Obj.t` (`forall r. (a -> r) -> r`) - A single main entry point: `SimpleIO.SimpleIO` (plus optional unsafe modules) - New functions for strings and exceptions # 0.2 - Removed ocaml library. `IO` is now defined in OCaml by extraction simply as `('a -> unit) -> unit`. - Add `delay_io` # 0.1 Initial release coq-simple-io-1.11.0/CITATION.cff000066400000000000000000000021171476017402600161520ustar00rootroot00000000000000# This CITATION.cff file was generated with cffinit. # Visit https://bit.ly/cffinit to generate yours today! cff-version: 1.2.0 title: Coq SimpleIO message: 'If you use this software, please cite it as below.' type: software authors: - given-names: Li-yao family-names: Xia email: xialiyao@cis.upenn.edu affiliation: University of Pennsylvania orcid: 'https://orcid.org/0000-0003-2673-4400' - given-names: Yishuai family-names: Li email: yishuai@cis.upenn.edu affiliation: University of Pennsylvania orcid: 'https://orcid.org/0000-0002-5728-5903' repository-code: 'https://github.com/Lysxia/coq-simple-io' abstract: >- This library provides tools to implement IO programs directly in Coq, in a similar style to Haskell. Facilities for formal verification are not included. IO is defined as a parameter with a purely functional interface in Coq, to be extracted to OCaml. Some wrappers for the basic types and functions in the OCaml Pervasives module are provided, and users are free to define their own APIs on top of this IO type. license: MIT coq-simple-io-1.11.0/LICENSE000066400000000000000000000020531476017402600152640ustar00rootroot00000000000000Copyright 2018-2022 Li-yao Xia, Yishuai Li Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. coq-simple-io-1.11.0/Makefile000066400000000000000000000036501476017402600157230ustar00rootroot00000000000000NAME=coq-simple-io MAKEFILE_COQ = Makefile.coq MAKE_COQ = $(MAKE) -f $(MAKEFILE_COQ) .PHONY: all build install clean example depgraph doc html html-raw compat test build: $(MAKEFILE_COQ) compat $(MAKE_COQ) doc: html # NOT RECOMMENDED: coq_makefile's install doesn't install plugins as libraries install: build $(MAKE_COQ) install uninstall: $(MAKEFILE_COQ) $(MAKE_COQ) uninstall $(MAKEFILE_COQ): _CoqProject coq_makefile -f $< -o $@ COMPATFILES:=_CoqProject \ test/TestInt63.v compat: $(COMPATFILES) COQ_VERSION:=$(word 1, $(shell coqc -print-version)) OCAML_VERSION:=$(shell ocamlc -version) %: %.cppo cppo -V COQ:$(COQ_VERSION) -V OCAML:$(OCAML_VERSION) -n -o $@ $^ test: sh ./testall.sh clean: if [ -e Makefile.coq ]; then $(MAKE) -f Makefile.coq cleanall; fi $(RM) Makefile.coq Makefile.coq.conf *.cmxs $(RM) -r _build/ build/ $(RM) $(DEPS_DOT) $(DEPS_OUT) $(RM) test/*.ml{i,} test/.*.aux $(RM) $(COMPATFILES) COQDEP=coqdep DEPS_DOT=deps.dot DEPS_OUT=deps.jpg depgraph: $(COQDEP) -dumpgraph $(DEPS_DOT) -Q src/ SimpleIO src > /dev/null 2>&1 sed 's%\("\([^"]*\)/\([^"/]*\)"\[label="\)%\1\2/\n%' -i deps.dot dot $(DEPS_DOT) -Tjpg -o$(DEPS_OUT) ## coqdoc ------------------------------------------------- COQDOCFLAGS:= \ -t "Simple IO" \ --toc --toc-depth 1 --html --interpolate \ --index indexpage --no-lib-name --parse-comments ifdef COQDOCJS_DIR COQDOCFLAGS+=--with-header $(COQDOCJS_DIR)/extra/header.html --with-footer $(COQDOCJS_DIR)/extra/footer.html html: html-raw cp $(COQDOCJS_DIR)/extra/resources/* doc awk -i inplace '{gsub(/href="\.\./,"href=\".")}; { print }' doc/*.html else html: html-raw @echo "`tput bold``tput setaf 3`WARNING: coqdocjs not set.`tput sgr0` This will produce ugly docs. Set the COQDOCJS_DIR variable when invoking make." endif export COQDOCFLAGS html-raw: Makefile.coq rm -rf html $(MAKE_COQ) html cp -r html/. doc/ ## ------------------------------------------------------- coq-simple-io-1.11.0/Makefile.coq.local000066400000000000000000000002351476017402600175710ustar00rootroot00000000000000COQ_VERSION=$(word 1, $(shell coqc -print-version)) ifeq ($(shell expr $(COQ_VERSION) \>= "8.16"), 1) CAMLPKGS+= -package coq-core.plugins.extraction endif coq-simple-io-1.11.0/README.md000066400000000000000000000142211476017402600155360ustar00rootroot00000000000000# Purely functional IO for Coq [![CircleCI](https://dl.circleci.com/status-badge/img/gh/Lysxia/coq-simple-io/tree/master.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/Lysxia/coq-simple-io/tree/master) ## Hello World in Coq ```coq From SimpleIO Require Import SimpleIO. From Coq Require Import String. #[local] Open Scope string_scope. Definition main : IO unit := print_endline "Hello, world!". RunIO main. ``` The `coq-simple-io` library provides tools to implement IO programs directly in Coq, in a similar style to Haskell. - IO monad - Bindings to OCaml standard library - `RunIO` command for running programs Facilities for formal verification are not included. There is no canonical way to describe the effects of the arbitrary foreign constructs that this library allows, so this library commits to none. A possible workflow is to generalize your program to any monad with a certain interface, specialize it to a mathematical monad (*e.g.*, state, or free monad) for formal verification, and to IO for execution. [coqffi](https://github.com/coq-community/coqffi) provides a toolchain for generating such interfaces from OCaml interfaces. ## Installation ### From OPAM ``` opam install coq-simple-io ``` ### From this repository as a local package ``` # Clone this repository git clone https://github.com/Lysxia/coq-simple-io # Register it with opam (the last argument is the path to the repo) opam pin add coq-simple-io ./coq-simple-io ``` ## Documentation The documentation of the latest released version is available on website at https://lysxia.github.io/coq-simple-io/toc.html Consult the [OCaml user manual](https://caml.inria.fr/pub/docs/manual-ocaml/) for detailed description of extracted code. ## Interface To use this library: ```coq Require Import SimpleIO.SimpleIO. (* And to use the monadic notations: *) Import IO.Notations. Local Open Scope io_scope. (* Equivalent notations can be found ext-lib, using its [Monad] type class. *) ``` Combinators for IO actions. ```coq Parameter IO : Type -> Type. Module IO. Parameter ret : forall {a}, a -> IO a. Parameter bind : forall {a b}, IO a -> (a -> IO b) -> IO b. Parameter fix_io : forall {a b}, ((a -> IO b) -> (a -> IO b)) -> a -> IO b. (* etc. *) Module Notations. Notation "c >>= f" := (bind c f) Notation "f =<< c" := (bind c f) Notation "x <- c1 ;; c2" := (bind c1 (fun x => c2)) Notation "e1 ;; e2" := (_ <- e1%io ;; e2%io)%io Notation delay io := (delay_io (fun _ => io)). End Notations. End IO. ``` ## Define IO actions The `IO` type extracts to the following definition in OCaml: ```ocaml (* Implicitly [forall r, (a -> r) -> r]. *) type 'a coq_IO = ('a -> Obj.t) -> Obj.t ``` So an effectful function `f : t -> u -> v` in OCaml can be wrapped as a Coq function `f : t -> u -> IO v` in the following way: ```coq Parameter f : t -> u -> IO v. Extract Constant f => "fun a b k -> k (f a b)". ``` Basically, add an extra parameter `k` and apply it to the OCaml function call. This boilerplate can also be generated from OCaml interfaces using [coqffi](https://github.com/coq-community/coqffi). ## Run The `RunIO` command extracts and runs an action of type `IO unit`. ```coq Definition main : IO unit := print_endline "Hello, world!". RunIO main. ``` ### Run as a command-line script You can run a `.v` file from the command line with `coqc`. To forward stdin and stdout to your `RunIO` scripts, set the option `RunIO IOMode Forward`. ```coq From SimpleIO Require Import SimpleIO. Import IO.Notations. RunIO IOMode Forward. Definition cat : IO unit := _ <- catch_eof (IO.fix_io (fun f _ => input <- read_line ;; print_endline input ;; f tt :> IO unit) tt) ;; IO.ret tt. RunIO cat. ``` ### Configuration ```coq (* Open MyModule at the top of the extracted code *) RunIO Open "MyModule". (* Build with ocamlfind (default) *) RunIO Builder Ocamlfind. (* Build with dune, specifying a dune file. *) RunIO Builder Dune "dune". (* Build with ocamlbuild. It must be installed separately. opam install ocamlbuild *) RunIO Builder Ocamlbuild. (* `RunIO Builder` can also take extra arguments for the build command in a string. *) RunIO Builder Ocamlfind "-rectypes". (* Include my-package when compiling (only for builders Ocamlfind and Ocamlbuild; Dune is configured via the dune file). *) RunIO Package "my-package". (* Copy my-directory to the build location so it will be visible to ocamlbuild or dune. *) RunIO Include "my-directory". (* Enable or disable automatic detection of common dependencies (on by default): - zarith for bigint representation of integers - coq-core.kernel for Uint63 *) RunIO Smart On. RunIO Smart Off. ``` New `RunIO` options may be added in the future. To avoid risks of future collisions with the main `RunIO` command, use names with a lower case initial (like `RunIO main`), or put the action name in parentheses (like `RunIO (Builder)` to run the `IO` action `Builder`). ## Library organization The source code can be found under `src/`. - `SimpleIO.SimpleIO`: Reexports default modules. ### Default modules The following modules are imported with `SimpleIO.SimpleIO`. - `SimpleIO.IO_Monad`: Definition of `IO` and basic combinators. - `SimpleIO.IO_Stdlib`: Wrappers around `Stdlib` from OCaml's standard library. - `SimpleIO.IO_StdlibAxioms`: Basic theory for pure `Stdlib` functions. - `SimpleIO.IO_Exceptions`: Catch common exceptions. - `SimpleIO.IO_RawChar`: Utilities that rely on `ExtrOcamlString`. - `SimpleIO.IO_String`: Operations on OCaml strings. ### Auxiliary modules The following module can be imported separately. They correspond to modules from the OCaml standard library. - `SimpleIO.IO_Bytes`: Mutable byte sequences. - `SimpleIO.IO_Random`: Pseudo-random number generators (PRNG). - `SimpleIO.IO_Float`: Floating-point arithmetic. - `SimpleIO.IO_Unix`: Interface to the Unix system. - `SimpleIO.IO_Sys`: System interface. ### Unsafe modules - `SimpleIO.IO_Unsafe`: Unsafe operations. - `SimpleIO.IO_UnsafeNat`: `Pervasives` functions adapted to `nat` (unsafety because of overflow and underflow). ## Related - [coqffi](https://github.com/coq-community/coqffi) - [Ynot](https://github.com/ynot-harvard/ynot) - [Coq.io](http://coq.io) coq-simple-io-1.11.0/_CoqProject.cppo000066400000000000000000000010601476017402600173470ustar00rootroot00000000000000#if COQ_VERSION >= (8, 16, 0) -generate-meta-for-package coq-simple-io #endif -I plugin/ -Q plugin SimpleIO plugin/compat.mli plugin/compat.ml plugin/iOLib.mli plugin/iOLib.ml plugin/coqsimpleio.mli plugin/coqsimpleio.mlg plugin/coqsimpleio_plugin.mlpack -Q src/ SimpleIO src/IO_Monad.v src/IO_Stdlib.v src/IO_MonadFix.v src/IO_String.v src/IO_Bytes.v src/IO_RawChar.v src/IO_Exceptions.v src/IO_Random.v src/IO_Unix.v src/IO_Sys.v src/IO_Filename.v src/IO_Float.v src/IO_Unsafe.v src/IO_UnsafeNat.v src/IO_StdlibAxioms.v src/SimpleIO_Plugin.v src/SimpleIO.v coq-simple-io-1.11.0/coq-simple-io.opam000066400000000000000000000021351476017402600176140ustar00rootroot00000000000000# This file is generated by dune, edit dune-project instead opam-version: "2.0" version: "dev" synopsis: "IO monad for Coq" description: """ This library provides tools to implement IO programs directly in Coq, in a similar style to Haskell. Facilities for formal verification are not included. IO is defined as a parameter with a purely functional interface in Coq, to be extracted to OCaml. Some wrappers for the basic types and functions in the OCaml Pervasives module are provided, and users are free to define their own APIs on top of this IO type.""" maintainer: ["lysxia@gmail.com"] authors: ["Li-yao Xia" "Yishuai Li"] license: "MIT" homepage: "https://github.com/Lysxia/coq-simple-io" bug-reports: "https://github.com/Lysxia/coq-simple-io/issues" depends: [ "dune" {>= "3.7"} "ocaml" {>= "4.08.0"} "ocamlfind" "coq" {>= "8.12~"} "coq-ext-lib" {>= "0.10.0"} "ocamlbuild" {with-test & >= "0.9.0"} "cppo" {build & >= "1.6.8"} "odoc" {with-doc} ] dev-repo: "git+https://github.com/Lysxia/coq-simple-io.git" build: [ ["dune" "subst"] {dev} [ "dune" "build" "-p" name "-j" jobs "@install" ] ] coq-simple-io-1.11.0/coq-simple-io.opam.template000066400000000000000000000001301476017402600214170ustar00rootroot00000000000000build: [ ["dune" "subst"] {dev} [ "dune" "build" "-p" name "-j" jobs "@install" ] ] coq-simple-io-1.11.0/dune000066400000000000000000000000721476017402600151340ustar00rootroot00000000000000(alias (name default) (deps (package coq-simple-io))) coq-simple-io-1.11.0/dune-project000066400000000000000000000016131476017402600166020ustar00rootroot00000000000000(lang dune 3.7) (using coq 0.7) (using menhir 2.0) (name coq-simple-io) (version dev) (generate_opam_files true) (source (github Lysxia/coq-simple-io)) (license MIT) (authors "Li-yao Xia" "Yishuai Li") (maintainers "lysxia@gmail.com") (package (name coq-simple-io) (synopsis "IO monad for Coq") (description "This library provides tools to implement IO programs directly in Coq, in a similar style to Haskell. Facilities for formal verification are not included. IO is defined as a parameter with a purely functional interface in Coq, to be extracted to OCaml. Some wrappers for the basic types and functions in the OCaml Pervasives module are provided, and users are free to define their own APIs on top of this IO type.") (depends (ocaml (>= 4.08.0)) ocamlfind (coq (>= 8.12~)) (coq-ext-lib (>= 0.10.0)) (ocamlbuild (and :with-test (>= 0.9.0))) (cppo (and :build (>= 1.6.8)))) ) coq-simple-io-1.11.0/plugin/000077500000000000000000000000001476017402600155555ustar00rootroot00000000000000coq-simple-io-1.11.0/plugin/compat.ml.cppo000066400000000000000000000026451476017402600203410ustar00rootroot00000000000000open Constrexpr let mk_temp_dir temp_dir = let tm = Unix.localtime (Unix.time ()) in let ts = Printf.sprintf "%02d%02d%02d_" tm.Unix.tm_hour tm.Unix.tm_min tm.Unix.tm_sec in #if OCAML_VERSION >= (5, 1, 0) Filename.temp_dir ~temp_dir ts "" #else (* https://discuss.ocaml.org/t/how-to-create-a-temporary-directory-in-ocaml/1815/4 *) let rand_digits () = let rand = Random.State.(bits (make_self_init ()) land 0xFFFFFF) in Printf.sprintf "%06x" rand in let () = Filename.concat in let pat = temp_dir ts in let mode = 0o700 in let raise_err msg = raise (Sys_error msg) in let rec loop count = if count < 0 then raise_err "mk_temp_dir: too many failing attemps" else let dir = pat ^ rand_digits () in try (Unix.mkdir dir mode; dir) with | Unix.Unix_error (Unix.EEXIST, _, _) -> loop (count - 1) | Unix.Unix_error (Unix.EINTR, _, _) -> loop count | Unix.Unix_error (e, _, _) -> raise_err ("mk_temp_dir: " ^ (Unix.error_message e)) in loop 1000 #endif let apply_constr f xs = #if COQ_VERSION < (8, 15, 0) let f = (None, f) in #endif CApp (f, List.map (fun x -> (x, None)) xs) #if COQ_VERSION >= (8,20,0) type indirect_accessor = Global.indirect_accessor type 'a with_accessor = opaque_access:Global.indirect_accessor -> 'a let apply_accessor f = f #else type indirect_accessor = unit type 'a with_accessor = 'a let apply_accessor f ~opaque_access:() = f #endif coq-simple-io-1.11.0/plugin/compat.mli.cppo000066400000000000000000000007121476017402600205030ustar00rootroot00000000000000open Constrexpr val mk_temp_dir : string -> string val apply_constr : constr_expr -> constr_expr list -> constr_expr_r #if COQ_VERSION >= (8,20,0) type indirect_accessor = Global.indirect_accessor type 'a with_accessor = opaque_access:Global.indirect_accessor -> 'a #else type indirect_accessor = unit type 'a with_accessor = 'a #endif (* Compat adaptor for Coq functions *) val apply_accessor : 'a with_accessor -> opaque_access:indirect_accessor -> 'a coq-simple-io-1.11.0/plugin/coqsimpleio.mlg.cppo000066400000000000000000000026171476017402600215500ustar00rootroot00000000000000DECLARE PLUGIN "coq-simple-io.plugin" { open Stdarg open IOLib let run_ast = mk_ref "SimpleIO.IO_Monad.IO.unsafe_run'" (* Since Coq 8.20, called as [run c ~opaque_access]. Before Coq 8.20, called as [run c]. *) let run c = #if COQ_VERSION >= (8,20,0) fun ~opaque_access -> #else let opaque_access = () in #endif let name = string_of_constr_expr c in run ~plugin_name:"coq_simple_io" ~opaque_access ~name (CAst.make @@ apply_constr run_ast [c]) let string_unopt = function | None -> "" | Some s -> s } VERNAC COMMAND EXTEND RunIO CLASSIFIED AS SIDEFF | #if COQ_VERSION >= (8,20,0) ![opaque_access] #endif ["RunIO" constr(c)] -> {run c} | ["RunIO" "Include" string(s)] -> { add_extra_dir s } | ["RunIO" "Open" string(s)] -> { add_module_to_open s } | ["RunIO" "Package" string(s)] -> { add_extra_pkg s } | ["RunIO" "Builder" "Ocamlfind" string_opt(opts)] -> { set_builder (Ocamlfind (string_unopt opts)) } | ["RunIO" "Builder" "Ocamlbuild" string_opt(opts)] -> { set_builder (Ocamlbuild (string_unopt opts))} | ["RunIO" "Builder" "Dune" string(s) string_opt(opts)] -> { set_builder (Dune (s, string_unopt opts)) } | ["RunIO" "Smart" "On"] -> { smart_mode := true } | ["RunIO" "Smart" "Off"] -> { smart_mode := false } | ["RunIO" "Reset"] -> { IOLib.reset () } | ["RunIO" "IOMode" "Repl"] -> { io_mode := Repl } | ["RunIO" "IOMode" "Forward"] -> { io_mode := Forward } END coq-simple-io-1.11.0/plugin/coqsimpleio.mli000066400000000000000000000000001476017402600205720ustar00rootroot00000000000000coq-simple-io-1.11.0/plugin/coqsimpleio_plugin.mlpack000066400000000000000000000000311476017402600226420ustar00rootroot00000000000000Compat IOLib Coqsimpleio coq-simple-io-1.11.0/plugin/dune000066400000000000000000000023131476017402600164320ustar00rootroot00000000000000(library (name coqsimpleio_plugin) (public_name coq-simple-io.plugin) (flags :standard -rectypes -warn-error -3 -w -8-27+40) (modules Coqsimpleio IOLib Compat) (libraries unix (select void_for_linking-plugin-extraction from (coq-core.plugins.extraction -> void_for_linking-plugin-extraction.empty) (coq.plugins.extraction -> void_for_linking-plugin-extraction.empty)) (select void_for_linking-config from (coq-core.config -> void_for_linking-config.empty) (coq.config -> void_for_linking-config.empty)))) (coq.pp (modules coqsimpleio)) (rule (action (write-file void_for_linking-plugin-extraction.empty ""))) (rule (action (write-file void_for_linking-config.empty ""))) (rule (alias compat) (target compat.ml) (deps compat.ml.cppo) (action (run %{bin:cppo} -V OCAML:%{ocaml_version} -V COQ:%{coq:version} -n %{deps} -o %{target}))) (rule (alias compat) (target compat.mli) (deps compat.mli.cppo) (action (run %{bin:cppo} -V OCAML:%{ocaml_version} -V COQ:%{coq:version} -n %{deps} -o %{target}))) (rule (alias compat) (target coqsimpleio.mlg) (deps coqsimpleio.mlg.cppo) (action (run %{bin:cppo} -V OCAML:%{ocaml_version} -V COQ:%{coq:version} -n %{deps} -o %{target}))) coq-simple-io-1.11.0/plugin/iOLib.ml000066400000000000000000000272071476017402600171150ustar00rootroot00000000000000(** This code was originally from from QuickChick, under the MIT license. *) open Pp open Names open Declare open Libnames open Util open Constrintern open Constrexpr include Compat (** * Global settings *) type filename = string type builder = Ocamlfind of string | Ocamlbuild of string | Dune of filename * string let builder : builder ref = Summary.ref ~name:"runio_builder" (Ocamlfind "") let set_builder b = builder := b (* Handle extra ocaml directory to be copied *) let extra_dir : string list ref = Summary.ref ~name:"runio_ocaml_dir" [] let add_extra_dir s = extra_dir := s :: !extra_dir let extra_pkg : string list ref = Summary.ref ~name:"runio_ocaml_pkg" [] let add_extra_pkg s = extra_pkg := s :: !extra_pkg let modules_to_open : string list ref = Summary.ref ~name:"runio_modules_to_open" [] let add_module_to_open s = modules_to_open := s :: !modules_to_open (* Automatically insert common dependencies (zarith, coq-core.kernel). [true] by default. *) let smart_mode : bool ref = Summary.ref ~name:"runio_smart_mode" true type io_mode = Repl (** Default mode compatible with interactive Coq sessions *) | Forward (** Forward stdin,stdout,stderr to the child processes running the extracted programs. This option lets you run [RunIO] scripts from the command line. *) let io_mode = Summary.ref ~name:"runio_io_mode" Repl let reset () = builder := Ocamlfind ""; extra_dir := []; extra_pkg := []; modules_to_open := []; smart_mode := true; io_mode := Repl (** * General helper functions *) let () = Filename.concat (* Rewrite a file line by line *) let sed_file file f = let src = open_in file in let tmpfile = file ^ ".tmp" in let tmp = open_out tmpfile in let rec go () = match input_line src with | line -> output_string tmp (f line); output_char tmp '\n'; go () | exception End_of_file -> close_in src; close_out tmp; Sys.rename tmpfile file in go () let read_all chan = let buf = Buffer.create 1024 in let rec go () = match Buffer.add_channel buf chan 1024 with | () -> go () | exception End_of_file -> Buffer.contents buf in go () let read_file file = let h = open_in file in let s = read_all h in close_in h; s let fresh_name n = let base = Id.of_string n in (* [is_visible_name id] returns [true] if [id] is already used on the Coq side. *) let is_visible_name id = try ignore (Nametab.locate (Libnames.qualid_of_ident id)); true with Not_found -> false in (* Safe fresh name generation. *) Namegen.next_ident_away_from base is_visible_name (* [mkdir -p]: recursively make the parent directories if they do not exist. *) let rec mkdir_ dname = let cmd () = Unix.mkdir dname 0o755 in try cmd () with | Unix.Unix_error (Unix.EEXIST, _, _) -> () | Unix.Unix_error (Unix.ENOENT, _, _) -> (* If the parent directory doesn't exist, try making it first. *) mkdir_ (Filename.dirname dname); cmd () (* [${TMP}/${PLUGIN_NAME}/${TIME}_${SALT}/main.ml], where [${TIME}] is the current time in format [HHMMSS] and [${SALT}] is a random string for uniqueness. *) let mk_tmp_dir ~plugin_name : string = let tmp = Filename.get_temp_dir_name () plugin_name in mkdir_ tmp; mk_temp_dir tmp (** * Extract, fix, compile, run *) let coq_kernel = if Coq_config.version < "8.14" then "coq.kernel" else "coq-core.kernel" let get_packages mlf = if !smart_mode then let (p_out, _, p_err) as process = Unix.open_process_full ("ocamldep -modules " ^ mlf) (Unix.environment ()) in let errmsg () = Feedback.msg_info (str "Unexpected error in coq-simple-io: ocamldep failed") in let pkgs = ref !extra_pkg in let opts = ref [] in let () = match input_line p_out with | e -> let modules = List.tl (String.split_on_char ' ' e) in modules |> List.iter (fun m -> let try_add ~pkg md = if m = md && not (List.mem pkg !pkgs) then pkgs := pkg :: !pkgs in try_add ~pkg:coq_kernel "Uint63"; if m = "Uint63" then opts := "-rectypes" :: !opts; try_add ~pkg:"zarith" "Big_int_Z") | exception End_of_file -> errmsg () in let () = let stat = Unix.close_process_full process in match stat with | Unix.WEXITED 0 -> () | _ -> errmsg () (* probably an unparseable file, which will fail compilation *) in !opts, !pkgs else [], !extra_pkg (* Extract the term and its dependencies *) let extract ~opaque_access ~file ident = let warnings = CWarnings.get_flags () in let mute_extraction = (if warnings = "" then "" else warnings ^ ",") ^ "-extraction-opaque-accessed" in CWarnings.set_flags mute_extraction; Flags.silently (Compat.apply_accessor Extraction_plugin.Extract_env.full_extraction ~opaque_access (Some file)) [qualid_of_ident ident]; CWarnings.set_flags warnings (* Add any modules that have been marked "open" *) let open_modules ~dir ms mlf = let prefix = String.concat "" List.(concat @@ map (fun m -> ["open "; m; ";;"]) ms) in let open_cmd = Printf.sprintf "awk -v n=1 -v s=\"%s\" 'NR == n {print s} {print}' %s > %s/__qc_tmp && mv %s/__qc_tmp %s" prefix mlf dir dir mlf in if Sys.command open_cmd <> 0 then CErrors.user_err (str "awk command failed on " ++ str mlf ++ fnl ()) let tmp_int_re = Str.regexp "type int =[ ]*int" (* Before compiling, fix stupid cyclic dependencies like "type int = int". Introduced by "Definition int := int." possibly inside a module, so just removing it might break other definitions that depend on it. TODO: Generalize (.) \g1\b or something *) let redefine_int mlf = sed_file mlf (fun line -> if Str.string_match tmp_int_re line 0 then "type tmptmptmp = int;; type int = tmptmptmp" else line) (* Extraction sometimes produces ML code that does not implement its interface. We circumvent this problem by erasing the interface. However, sometimes the inferred types are too abstract. So we touch the .mli to close the weak types. *) let remove_mli mlif = Sys.remove mlif; ignore (Sys.command ("touch " ^ mlif)) let fixup ~dir mlif mlf = open_modules ~dir !modules_to_open mlf; redefine_int mlf; remove_mli mlif (* Copy over the contents of the ocaml directory *) let copy_dirs dir ds = List.iter (fun s -> ignore (Sys.command (Printf.sprintf "cp -r %s %s" s dir))) ds let compile ~dir mlif mlf = let run_command cmd = if Sys.command cmd <> 0 then let build_log = read_file (dir ^ "/build.log") in let build_err = read_file (dir ^ "/build.err") in let msg = str "Could not compile test program: " ++ str mlf ++ fnl () in let msg = if build_log = "" then msg else msg ++ fnl () ++ str "Build stdout:" ++ fnl () ++ str build_log ++ fnl () in let msg = if build_err = "" then msg else msg ++ fnl () ++ str "Build stderr:" ++ fnl () ++ str build_err ++ fnl () in CErrors.user_err msg in let fileprefix = Filename.chop_extension mlf in match !builder with | Ocamlfind opts -> let execn = fileprefix ^ ".native" in let pkg_opts, packages = get_packages mlf in let packages = match packages with | [] -> "" | x -> "-package " ^ (String.concat "," x) in let pkg_opts = match pkg_opts with | [] -> "" | pkg_opts -> String.concat " " pkg_opts in run_command (Printf.sprintf "cd %s && ocamlfind opt -linkpkg -w -3 %s %s %s -o %s %s %s > build.log 2> build.err" dir pkg_opts packages opts execn mlif mlf); execn | Ocamlbuild opts -> let execn = Filename.basename (fileprefix ^ ".native") in let pkg_opts, packages = get_packages mlf in let packages = match packages with | [] -> "" | x -> "-pkgs " ^ (String.concat "," x) in let pkg_opts = match pkg_opts with | [] -> "" | x -> "-cflags " ^ String.concat "," x in run_command (Printf.sprintf "cd %s && ocamlbuild -use-ocamlfind -cflags -w,-3 %s %s %s %s > build.log 2> build.err" dir pkg_opts packages opts execn); dir "_build" execn | Dune (dune, opts) -> let execn = Filename.basename fileprefix in (* Modify the dune file to add the executable name and put it in the output dir *) let awk_cmd = Printf.sprintf "awk -v n=2 -v s=\" (name %s)\" 'NR == n {print s} {print}' %s > %s" execn dune (dir ^ "/" ^ dune) in ignore (Sys.command awk_cmd); (* The command is just dune build *) run_command (Printf.sprintf "cd %s && dune build %s.exe --root=. --display=quiet %s > build.log 2> build.err" dir execn opts); dir "_build/default" execn ^ ".exe" let run_exec_repl execn = let (p_out, _, p_err) as process = Unix.open_process_full execn (Unix.environment ()) in let rec process_otl_aux () = let e = input_line p_out in Feedback.msg_info (Pp.str e); process_otl_aux() in try process_otl_aux () with End_of_file -> let err_msg = read_all p_err in let err descr = CErrors.user_err (str (execn ^ ": " ^ descr) ++ fnl () ++ fnl () ++ str err_msg ++ fnl ()) in let stat = Unix.close_process_full process in begin match stat with | Unix.WEXITED 0 -> () | Unix.WEXITED i -> err (Printf.sprintf "Exited with status %d" i) | Unix.WSIGNALED i -> err (Printf.sprintf "Killed (%d)" i) | Unix.WSTOPPED i -> err (Printf.sprintf "Stopped (%d)" i) end let run_exec_forward execn = let pid = Unix.create_process execn [|execn|] Unix.stdin Unix.stdout Unix.stderr in let _, status = Unix.waitpid [] pid in let err descr = CErrors.user_err (str (execn ^ ": " ^ descr) ++ fnl ()) in begin match status with | Unix.WEXITED 0 -> () | Unix.WEXITED i -> err (Printf.sprintf "Exited with status %d" i) | Unix.WSIGNALED i -> err (Printf.sprintf "Killed (%d)" i) | Unix.WSTOPPED i -> err (Printf.sprintf "Stopped (%d)" i) end let run_exec execn = match !io_mode with | Repl -> run_exec_repl execn | Forward -> run_exec_forward execn let compile_and_run ~dir mlif mlf = compile ~dir mlif mlf |> run_exec let extract_and_run ~plugin_name ~opaque_access ident = let dir = mk_tmp_dir ~plugin_name in let mlf : string = dir "extracted_main.ml" in let mlif : string = Filename.chop_extension mlf ^ ".mli" in extract ~opaque_access ~file:mlf ident; fixup ~dir mlif mlf; copy_dirs dir !extra_dir; compile_and_run ~dir mlif mlf ;; let mk_ref s = CAst.make @@ CRef (qualid_of_string s, None) (** [define env evd c] introduces a fresh constant name for the term [c]. *) let define env evd c = let (evd,_) = Typing.type_of env evd c in let univs = Evd.univ_entry ~poly:true evd in let fn = fresh_name "quickchick" in (* TODO: Maxime - which of the new internal flags should be used here? The names aren't as clear :) *) let _ : Constant.t = declare_constant ~name:fn ~kind:Decls.(IsDefinition Definition) (DefinitionEntry (definition_entry ~univs (EConstr.to_constr evd c))) in fn let define_and_run ~plugin_name ~opaque_access env evd term = let term = define env evd term in extract_and_run ~plugin_name ~opaque_access term let chatty () = match !io_mode with | Repl -> true | Forward -> false let run ~plugin_name ~opaque_access ~name term = if chatty () then Feedback.msg_info (Pp.str ("Running " ^ name ^ " ...")); let env = Global.env () in let evd = Evd.from_env env in let (term,_) = interp_constr env evd term in define_and_run ~plugin_name ~opaque_access env evd term (* TODO: clean leftover files *) let string_of_constr_expr c = let env = Global.env () in let evd = Evd.from_env env in Pp.string_of_ppcmds (Ppconstr.pr_constr_expr env evd c) coq-simple-io-1.11.0/plugin/iOLib.mli000066400000000000000000000023441476017402600172610ustar00rootroot00000000000000open Constrexpr type filename = string type builder = Ocamlfind of string | Ocamlbuild of string | Dune of filename * string val set_builder : builder -> unit (* Handle extra ocaml directory to be copied *) val add_extra_dir : string -> unit val add_extra_pkg : string -> unit val add_module_to_open : string -> unit (* Automatically insert common dependencies (zarith, coq-simple-io.extraction). [true] by default. *) val smart_mode : bool ref (** Option for handling standard input and output *) type io_mode = Repl (** Default mode compatible with interactive Coq sessions *) | Forward (** Forward stdin,stdout,stderr to the child processes running the extracted programs. This option lets you run [RunIO] scripts from the command line. *) (** See [type io_mode] above. *) val io_mode : io_mode ref val reset : unit -> unit val apply_constr : constr_expr -> constr_expr list -> constr_expr_r val mk_ref : string -> constr_expr val string_of_constr_expr : constr_expr -> string val define_and_run : plugin_name:string -> opaque_access:Compat.indirect_accessor -> Environ.env -> Evd.evar_map -> Evd.econstr -> unit val run : plugin_name:string -> opaque_access:Compat.indirect_accessor -> name:string -> constr_expr -> unit coq-simple-io-1.11.0/src/000077500000000000000000000000001476017402600150465ustar00rootroot00000000000000coq-simple-io-1.11.0/src/IO_Bytes.v000066400000000000000000000035301476017402600167130ustar00rootroot00000000000000(** * Byte sequence operations *) (** Note: descriptions of the interface are derived from OCaml's documentation: https://caml.inria.fr/pub/docs/manual-ocaml/libref/Bytes.html *) (* begin hide *) From Coq Require Import ExtrOcamlIntConv. From SimpleIO Require Import IO_Monad IO_Stdlib. (* end hide *) Module OBytes. (** Return the length (number of bytes) of the argument. *) Parameter length : bytes -> int. (** [get s n] returns the byte at index [n] in [s]. *) Parameter get : bytes -> int -> IO char. (** [set s n c] modifies [s], replacing the byte at index [n] with [c]. *) Parameter set : bytes -> int -> char -> IO unit. (** [sub s start len] returns a new byte sequence of length [len], containing the subsequence of [s] that starts at position [start] and has length [len]. *) Parameter sub : bytes -> int -> int -> IO bytes. (** [create n] returns a new byte sequence of length [n]. The sequence is uninitialized and contains arbitrary bytes. Raise [Invalid_argument] if [n < 0] or [n > ] system's maximum length of byte sequences. *) Parameter create : int -> IO bytes. (** Return a new byte sequence that contains the same bytes as the given string. *) Parameter of_string : ocaml_string -> IO bytes. (** Return a new string that contains the same bytes as the given byte sequence. *) Parameter to_string : bytes -> IO ocaml_string. (* begin hide *) Extract Constant length => "Bytes.length". Extract Constant get => "fun s n k -> k (Bytes.get s n)". Extract Constant set => "fun s n c k -> k (Bytes.set s n c)". Extract Constant sub => "fun s start len k -> k (Bytes.sub s start len)". Extract Constant create => "fun n k -> k (Bytes.create n)". Extract Constant of_string => "fun s k -> k (Bytes.of_string s)". Extract Constant to_string => "fun b k -> k (Bytes.to_string b)". (* end hide *) End OBytes. coq-simple-io-1.11.0/src/IO_Exceptions.v000066400000000000000000000030561476017402600177510ustar00rootroot00000000000000(** * Exception handling *) (* begin hide *) From Coq.extraction Require Extraction. From SimpleIO Require Import IO_Monad. (* end hide *) (** Catch [End_of_file] exceptions. *) Parameter catch_eof : forall {a : Type}, IO a -> IO (option a). Extract Constant catch_eof => "(fun io k -> k (try Obj.magic io (fun a -> Some a) with | End_of_file -> None))". (** Catch [Invalid_argument _] exceptions. *) Parameter catch_invalid_arg : forall {a : Type}, IO a -> IO (option a). Extract Constant catch_invalid_arg => "(fun io k -> k (try Obj.magic io (fun a -> Some a) with | Invalid_argument _ -> None))". (** Catch [Failure _] exceptions. *) Parameter catch_failure : forall {a : Type}, IO a -> IO (option a). Extract Constant catch_failure => "(fun io k -> k (try Obj.magic io (fun a -> Some a) with | Failure _ -> None))". (** Catch [Not_found] exceptions. *) Parameter catch_not_found : forall {a : Type}, IO a -> IO (option a). Extract Constant catch_not_found => "(fun io k -> k (try Obj.magic io (fun a -> Some a) with | Not_found -> None))". (** Catch [Sys_error] exceptions. *) Parameter catch_sys_error : forall {a : Type}, IO a -> IO (option a). Extract Constant catch_sys_error => "(fun io k -> k (try Obj.magic io (fun a -> Some a) with | Sys_error _ -> None))". (** Catch any exception. *) Parameter catch_any_exc : forall {a : Type}, IO a -> IO (option a). Extract Constant catch_any_exc => "(fun io k -> k (try Obj.magic io (fun a -> Some a) with | _ -> None))". coq-simple-io-1.11.0/src/IO_Filename.v.cppo000066400000000000000000000166471476017402600203220ustar00rootroot00000000000000(** * Operations on file names *) From SimpleIO Require Import IO_Monad IO_Stdlib. Module OFilename. (** The conventional name for the current directory (e.g. [.] in Unix). *) Parameter current_dir_name : ocaml_string. (** The conventional name for the parent of the current directory (e.g. [..] in Unix). *) Parameter parent_dir_name : ocaml_string. (** The directory separator (e.g. [/] in Unix). *) Parameter dir_sep : ocaml_string. (** [concat dir file] returns a file name that designates file [file] in directory [dir]. *) Parameter concat : ocaml_string -> ocaml_string -> ocaml_string. (** Return [true] if the file name is relative to the current directory, [false] if it is absolute (i.e. in Unix, starts with [/]). *) Parameter is_relative : ocaml_string -> bool. (** Return [true] if the file name is relative and does not start with an explicit reference to the current directory ([./] or [../] in Unix), [false] if it starts with an explicit reference to the root directory or the current directory. *) Parameter is_implicit : ocaml_string -> bool. (** [check_suffix name suff] returns [true] if the filename [name] ends with the suffix [suff]. Under Windows ports (including Cygwin), comparison is case-insensitive, relying on [String.lowercase_ascii]. Note that this does not match exactly the interpretation of case-insensitive filename equivalence from Windows. *) Parameter check_suffix : ocaml_string -> ocaml_string -> bool. (** [chop_suffix name suff] removes the suffix [suff] from the filename [name]. @raise Invalid_argument if [name] does not end with the suffix [suff]. *) Parameter chop_suffix : ocaml_string -> ocaml_string -> IO ocaml_string. (** [extension name] is the shortest suffix [ext] of [name0] where: - [name0] is the longest suffix of [name] that does not contain a directory separator; - [ext] starts with a period; - [ext] is preceded by at least one non-period character in [name0]. If such a suffix does not exist, [extension name] is the empty string. *) Parameter extension : ocaml_string -> ocaml_string. (** Return the given file name without its extension, as defined in [OFilename.extension]. If the extension is empty, the function returns the given file name. The following invariant holds for any file name [s]: [remove_extension s ++ extension s = s] *) Parameter remove_extension : ocaml_string -> ocaml_string. (** Same as [OFilename.remove_extension], but raise [Invalid_argument] if the given name has an empty extension. *) Parameter chop_extension : ocaml_string -> IO ocaml_string. (** Split a file name into directory name / base file name. If [name] is a valid file name, then [concat (dirname name) (basename name)] returns a file name which is equivalent to [name]. Moreover, after setting the current directory to [dirname name] (with [OSys.chdir]), references to [basename name] (which is a relative file name) designate the same file as [name] before the call to [OSys.chdir]. This function conforms to the specification of POSIX.1-2008 for the [basename] utility. *) Parameter basename : ocaml_string -> ocaml_string. (** See [OFilename.basename]. This function conforms to the specification of POSIX.1-2008 for the [dirname] utility. *) Parameter dirname : ocaml_string -> ocaml_string. (** [temp_file prefix suffix] returns the name of a fresh temporary file in the temporary directory. The base name of the temporary file is formed by concatenating [prefix], then a suitably chosen integer number, then [suffix]. The temporary file is created empty, with permissions [0o600] (readable and writable only by the file owner). The file is guaranteed to be different from any other file that existed when [temp_file] was called. @raise Sys_error if the file could not be created. *) Parameter temp_file : ocaml_string -> ocaml_string -> IO ocaml_string. (** Same as [OFilename.temp_file], but returns both the name of a fresh temporary file, and an output channel opened (atomically) on this file. This function is more secure than [temp_file]: there is no risk that the temporary file will be modified (e.g. replaced by a symbolic link) before the program opens it. @raise Sys_error if the file could not be opened. *) Parameter open_temp_file : ocaml_string -> ocaml_string -> IO (ocaml_string * out_channel). (** The name of the temporary directory: Under Unix, the value of the [TMPDIR] environment variable, or "/tmp" if the variable is not set. Under Windows, the value of the [TEMP] environment variable, or "." if the variable is not set. The temporary directory can be changed with [OFilename.set_temp_dir_name]. *) Parameter get_temp_dir_name : IO ocaml_string. (** Change the temporary directory returned by [OFilename.get_temp_dir_name] and used by [OFilename.temp_file] and [OFilename.open_temp_file]. *) Parameter set_temp_dir_name : ocaml_string -> IO unit. (** Return a quoted version of a file name, suitable for use as one argument in a command line, escaping all meta-characters. Warning: under Windows, the output is only suitable for use with programs that follow the standard Windows quoting conventions. *) Parameter quote : ocaml_string -> ocaml_string. #if OCAML_VERSION >= (4, 10, 0) (** [null] is ["/dev/null"] on POSIX and ["NUL"] on Windows. It represents a file on the OS that discards all writes and returns end of file on reads. @since 4.10.0 *) Parameter null : ocaml_string. Extract Constant null => "Filename.null". #endif #if OCAML_VERSION >= (4, 8, 0) (** [chop_suffix_opt suffix filename] removes the suffix from the [filename] if possible, or returns [None] if the filename does not end with the suffix. Under Windows ports (including Cygwin), comparison is case-insensitive, relying on [String.lowercase_ascii]. Note that this does not match exactly the interpretation of case-insensitive filename equivalence from Windows. @since 4.08 *) Parameter chop_suffix_opt: ocaml_string -> ocaml_string -> option ocaml_string. Extract Constant chop_suffix_opt => "Filename.chop_suffix_opt". #endif (* begin hide *) Extract Constant current_dir_name => "Filename.current_dir_name". Extract Constant parent_dir_name => "Filename.parent_dir_name". Extract Constant dir_sep => "Filename.dir_sep". Extract Constant concat => "Filename.concat". Extract Constant is_relative => "Filename.is_relative". Extract Constant is_implicit => "Filename.is_implicit". Extract Constant check_suffix => "Filename.check_suffix". Extract Constant extension => "Filename.extension". Extract Constant remove_extension => "Filename.remove_extension". Extract Constant basename => "Filename.basename". Extract Constant dirname => "Filename.dirname". Extract Constant quote => "Filename.quote". Extract Constant chop_suffix => "fun s f k -> k (Filename.chop_suffix s f)". Extract Constant chop_extension => "fun f k -> k (Filename.chop_extension f)". Extract Constant temp_file => "fun p s k -> k (Filename.temp_file p s)". Extract Constant open_temp_file => "fun p s k -> k (Filename.open_temp_file p s)". Extract Constant get_temp_dir_name => "fun k -> k (Filename.get_temp_dir_name ())". Extract Constant set_temp_dir_name => "fun d k -> k (Filename.set_temp_dir_name d)". (* end hide *) End OFilename. coq-simple-io-1.11.0/src/IO_Float.v.cppo000066400000000000000000000065771476017402600176500ustar00rootroot00000000000000(** * Floating-point arithmetic *) (* begin hide *) From Coq Require Import ExtrOcamlIntConv. From SimpleIO Require Import IO_Stdlib. (* end hide *) Module OFloat. (** Convert an integer to floating-point. *) Parameter of_int : int -> float. (** Multiply by [10e-6]. *) Parameter micro : float -> float. (** Unary negation. *) Parameter neg : float -> float. (** Floating-point addition. *) Parameter add : float -> float -> float. (** Floating-point subtraction. *) Parameter sub : float -> float -> float. (** Floating-point multiplication. *) Parameter mul : float -> float -> float. (** Floating-point division. *) Parameter div : float -> float -> float. (** Exponentiation. *) Parameter pow : float -> float -> float. Module Unsafe. (** Truncate the given floating-point number to an integer. The result is unspecified if the argument is [nan] or falls outside the range of representable integers. *) Parameter to_int : float -> int. (** Convert the given string to a float. The string is read in decimal (by default) or in hexadecimal (marked by [0x] or [0X]). The format of decimal floating-point numbers is [ [-] dd.ddd (e|E) [+|-] dd ], where [d] stands for a decimal digit. The format of hexadecimal floating-point numbers is [ [-] 0(x|X) hh.hhh (p|P) [+|-] dd ], where [h] stands for an hexadecimal digit and [d] for a decimal digit. In both cases, at least one of the integer and fractional parts must be given; the exponent part is optional. The [_] (underscore) character can appear anywhere in the string and is ignored. Depending on the execution platforms, other representations of floating-point numbers can be accepted, but should not be relied upon. Raise [Failure "float_of_string"] if the given string is not a valid representation of a float. *) Parameter of_string : ocaml_string -> float. (* begin hide *) #if OCAML_VERSION >= (4, 8, 0) Extract Constant to_int => "Stdlib.int_of_float". Extract Constant of_string => "Stdlib.float_of_string". #else Extract Constant to_int => "Pervasives.int_of_float". Extract Constant of_string => "Pervasives.float_of_string". #endif (* end hide *) End Unsafe. (** Same as [of_string], but returns [None] instead of raising. *) Parameter of_string_opt : ocaml_string -> option float. (** Return the string representation of a floating-point number. *) Parameter to_string : float -> ocaml_string. (* begin hide *) #if OCAML_VERSION >= (4, 8, 0) Extract Constant of_int => "Stdlib.float_of_int". Extract Constant of_string_opt => "Stdlib.float_of_string_opt". Extract Constant to_string => "Stdlib.string_of_float". #else Extract Constant of_int => "Pervasives.float_of_int". Extract Constant of_string_opt => "Pervasives.float_of_string_opt". Extract Constant to_string => "Pervasives.string_of_float". #endif Extract Constant micro => "fun x -> x *. 10e-6". Extract Constant neg => "( ~-. )". Extract Constant add => "( +. )". Extract Constant sub => "( -. )". Extract Constant mul => "( *. )". Extract Constant div => "( /. )". Extract Constant pow => "( ** )". (* end hide *) End OFloat. Module FloatNotations. Import OFloat. Notation "- x" := (neg x). Infix "+" := add. Infix "-" := sub. Infix "*" := mul. Infix "/" := div. Infix "^" := pow. End FloatNotations. coq-simple-io-1.11.0/src/IO_Monad.v000066400000000000000000000103471476017402600166670ustar00rootroot00000000000000(** * The [IO] monad *) (* begin hide *) From Coq.extraction Require Import Extraction ExtrOcamlBasic. From ExtLib.Structures Require Import Functor Applicative Monad MonadFix. Set Warnings "-extraction-opaque-accessed,-extraction". (* end hide *) (** * Main interface *) (** The IO monad. *) Parameter IO : Type -> Type. (** The result type of [unsafe_run]. For example, to extract a program [main : IO unit] to a file named [main.ml]: [[ Definition exe : io_unit := unsafe_run main. Extraction "main.ml" exe. ]] *) Parameter io_unit : Type. (** All identifiers are meant to be used qualified. *) Module IO. (** ** Functions *) Parameter ret : forall {a}, a -> IO a. Parameter bind : forall {a b}, IO a -> (a -> IO b) -> IO b. (** Fixpoint combinator. *) Parameter fix_io : forall {a b}, ((a -> IO b) -> (a -> IO b)) -> a -> IO b. (** Delay eager evaluation. Some IO actions can be expensive closures. [delay_io] allows the computation of the closure to happen during execution, instead of eagerly during the definition of the IO action. *) Parameter delay_io : forall {a}, (unit -> IO a) -> IO a. (** Apply a pure function to the result of an action. *) Definition map {a b} : (a -> b) -> IO a -> IO b := fun f m => bind m (fun a => ret (f a)). (** Infinite stateful loop. *) Definition loop : forall {a void}, (a -> IO a) -> (a -> IO void) := fun _ _ f => fix_io (fun k x => bind (f x) k). (** While loop. Stops once the output is [None]. *) Definition while_loop : forall {a}, (a -> IO (option a)) -> (a -> IO unit) := fun _ f => fix_io (fun k x => bind (f x) (fun y' => match y' with | None => ret tt | Some y => k y end)). (** ** Notations *) Module Notations. Declare Scope io_scope. Delimit Scope io_scope with io. Notation "c >>= f" := (bind c f) (at level 58, left associativity) : io_scope. Notation "f =<< c" := (bind c f) (at level 61, right associativity) : io_scope. Notation "x <- c1 ;; c2" := (bind c1 (fun x => c2)) (at level 61, c1 at next level, right associativity) : io_scope. Notation "e1 ;; e2" := (_ <- e1%io ;; e2%io)%io (at level 61, right associativity) : io_scope. Notation delay io := (delay_io (fun _ => io)). Open Scope io_scope. End Notations. (** ** Equations *) Axiom fixpoint_io : forall {a b} f, @fix_io a b f = f (fix_io f). (** *** Monad laws *) Axiom bind_ret : forall {a b} (x : a) (k : a -> IO b), bind (ret x) k = k x. Axiom ret_bind : forall {a} (m : IO a), bind m ret = m. Axiom bind_bind : forall {a b c} (m : IO a) (k : a -> IO b) (h : b -> IO c), bind (bind m k) h = bind m (fun x => bind (k x) h). Axiom bind_ext : forall {a b} (m : IO a) (k k' : a -> IO b), (forall x, k x = k' x) -> bind m k = bind m k'. (** ** Run! *) (** Run an IO action. See [io_unit] for usage. Hiding the result in [io_unit] limits the breakage of referential transparency somewhat. *) Parameter unsafe_run : IO unit -> io_unit. (** Run an IO action, ignoring the result. *) Parameter unsafe_run' : forall {a}, IO a -> io_unit. (** Run an IO action to produce a result. This can break referential transparency quite badly. *) Parameter very_unsafe_eval : forall {a}, IO a -> a. (** * Extraction *) (* CPS prevents stack overflows. *) (* [forall r, (a -> r) -> r] *) Extract Constant IO "'a" => "('a -> Obj.t) -> Obj.t". Extract Constant ret => "fun a k -> (k a : Obj.t)". Extract Constant bind => "fun io_a io_b (k : _ -> Obj.t) -> (io_a (fun a -> (io_b a k : Obj.t)) : Obj.t)". Extract Constant fix_io => "fun f -> let rec go a (k : _ -> Obj.t) : Obj.t = f go a k in go". Extract Constant delay_io => "fun f (k : _ -> Obj.t) -> (f () k : Obj.t)". Extract Inlined Constant io_unit => "unit". Extract Constant unsafe_run => "fun io -> Obj.magic io (fun () -> ())". Extract Constant unsafe_run' => "fun io -> Obj.magic io (fun _ -> ())". Extract Constant very_unsafe_eval => "fun io -> Obj.magic io (fun x -> x)". End IO. (** * Instances *) Global Instance Functor_IO : Functor IO := { fmap _ _ := IO.map; }. Global Instance Applicative_IO : Applicative IO := { pure _ := IO.ret; ap _ _ iof iox := IO.bind iof (fun f => IO.bind iox (fun x => IO.ret (f x))); }. Global Instance Monad_IO : Monad IO := { ret _ := IO.ret; bind _ _ := IO.bind; }. coq-simple-io-1.11.0/src/IO_MonadFix.v000066400000000000000000000005061476017402600173320ustar00rootroot00000000000000(** * [MonadFix IO] instance *) (** It was causing a universe inconsistency with VST. Until we investigate more we keep this instance in its own module. *) From ExtLib.Structures Require Import MonadFix. From SimpleIO Require Import IO_Monad. Global Instance MonadFix_IO : MonadFix IO := {| mfix _ _ := IO.fix_io |}. coq-simple-io-1.11.0/src/IO_Random.v000066400000000000000000000026301476017402600170450ustar00rootroot00000000000000(** * Pseudo-random number generators (PRNG) *) (** Note: descriptions of the interface are derived from OCaml's documentation: https://caml.inria.fr/pub/docs/manual-ocaml/libref/Random.html *) (* begin hide *) From Coq Require Import ExtrOcamlIntConv. From SimpleIO Require Import IO_Monad IO_Stdlib. (* end hide *) Module ORandom. (** Initialize using a given seed. The same seed will always yield the same sequence of numbers. *) Parameter init : int -> IO unit. (** Initialize the generator with a random seed chosen in a system-dependent way. If [/dev/urandom] is available on the host machine, it is used to provide a highly random initial seed. Otherwise, a less random seed is computed from system parameters (current time, process IDs). *) Parameter self_init : unit -> IO unit. (** [IO_Random.int bound] returns a random integer between 0 (inclusive) and [bound] (exclusive). [bound] must be greater than 0 and less than 2{^30}. *) Parameter int : int -> IO int. (** [IO_Random.bool tt] returns [true] or [false] with probability 0.5 each. *) Parameter bool : unit -> IO bool. (* begin hide *) Extract Constant init => "fun n k -> k (Random.init n)". Extract Constant self_init => "fun t k -> k (Random.self_init t)". Extract Constant int => "fun i k -> k (Random.int i)". Extract Constant bool => "fun t k -> k (Random.bool t)". (* end hide *) End ORandom. coq-simple-io-1.11.0/src/IO_RawChar.v.cppo000066400000000000000000000047371476017402600201260ustar00rootroot00000000000000(** * Extraction of [char] and [string] *) (** [RawChar] provides some convenient operations to work with Coq's standard [ascii] and [string] type, assuming they are extracted using [ExtrOcamlString]: - [ascii] is extracted to [char]; - [string] is extracted to [char list]. *) (* begin hide *) From Coq.Strings Require Import String Ascii. From Coq.extraction Require Import ExtrOcamlIntConv ExtrOcamlString. From SimpleIO Require Import IO_Monad IO_Stdlib. Extraction Blacklist Bytes List String. (* end hide *) (** * Conversions *) (** [ascii] and [int] *) Parameter int_of_ascii : ascii -> int. Parameter ascii_of_int : int -> ascii. Axiom char_is_ascii : char = ascii. (** [ascii] and [char] *) Definition char_of_ascii : ascii -> char := match char_is_ascii in (_ = _ascii) return (_ascii -> char) with | eq_refl => fun c => c end. Definition ascii_of_char : char -> ascii := match char_is_ascii in (_ = _ascii) return (char -> _ascii) with | eq_refl => fun x => x end. #if OCAML_VERSION >= (4, 8, 0) Extract Inlined Constant int_of_ascii => "Stdlib.int_of_char". Extract Inlined Constant ascii_of_int => "Stdlib.char_of_int". #else Extract Inlined Constant int_of_ascii => "Pervasives.int_of_char". Extract Inlined Constant ascii_of_int => "Pervasives.char_of_int". #endif (** [string] and [ocaml_string] *) Parameter to_ostring : string -> ocaml_string. Parameter from_ostring : ocaml_string -> string. Extract Constant to_ostring => "fun z -> Bytes.unsafe_to_string ( let b = Bytes.create (List.length z) in let rec go z i = match z with | c :: z -> Bytes.set b i c; go z (i+1) | [] -> b in go z 0)". Extract Constant from_ostring => "fun s -> let rec go n z = if n = -1 then z else go (n-1) (String.get s n :: z) in go (String.length s - 1) []". Coercion char_of_ascii : ascii >-> char. Coercion to_ostring : string >-> ocaml_string. (** * Input-output *) (** For output, you can use the functions on [char] and [ocaml_string] from [IO_Stdlib] directly, thanks to the coercions [char_of_ascii] and [to_ostring] above. *) (** ** Standard channels *) (** *** [stdin] *) Definition read_line' : IO string := IO.map from_ostring read_line. (** ** File handles *) (** *** Input *) Definition input_ascii : in_channel -> IO ascii := fun h => IO.map ascii_of_char (input_char h). Definition input_line' : in_channel -> IO string := fun h => IO.map from_ostring (input_line h). coq-simple-io-1.11.0/src/IO_Stdlib.v.cppo000066400000000000000000000462301476017402600200120ustar00rootroot00000000000000(** * OCaml standard library *) (** Extraction of OCaml's [Stdlib] module. This depends on [ExtrOcamlBasic] and [ExtrOcamlIntConv] that define extraction for a few basic types ([option], [list], [int]). Other types that do not have a natural counterpart in Coq are left abstract. In particular, this module does not assume any particular representation of Coq's [string] and [ascii] (as opposed to the [RawChar] module). *) (* begin hide *) From Coq.extraction Require Import Extraction ExtrOcamlBasic ExtrOcamlIntConv. From SimpleIO Require Import IO_Monad. Extraction Blacklist Pervasives Stdlib. (* end hide *) (** * Types *) (** The native [string] type in OCaml. *) Parameter ocaml_string : Type. (** Mutable bytestrings. *) Parameter bytes : Type. (** Floating point values. *) Parameter float : Type. (** The native [char] type in OCaml (8 bit integers). *) Parameter char : Type. (** Input-output channels. *) Parameter in_channel : Type. Parameter out_channel : Type. (** Mutable references. *) Parameter ref : Type -> Type. (** * Operations on [int] *) Parameter int_add : int -> int -> int. Parameter int_sub : int -> int -> int. Parameter int_mul : int -> int -> int. Parameter int_div_opt : int -> int -> option int. Parameter int_mod_opt : int -> int -> option int. Parameter int_eqb : int -> int -> bool. Parameter int_neqb : int -> int -> bool. Parameter int_le : int -> int -> bool. Parameter int_lt : int -> int -> bool. Parameter int_min : int -> int -> int. Parameter int_max : int -> int -> int. Parameter land : int -> int -> int. Parameter lor : int -> int -> int. Parameter lxor : int -> int -> int. Parameter lnot : int -> int -> int. Parameter max_int : int. Parameter min_int : int. (* Note: Coq renamed its int_scope to dec_int_scope seemingly to not clash with math-comp. It might be a good idea to rename here too. *) Declare Scope int_scope. Delimit Scope int_scope with int. Bind Scope int_scope with int. Infix "+" := int_add : int_scope. Infix "-" := int_sub : int_scope. Infix "*" := int_mul : int_scope. Infix "?" := int_neqb (at level 70, no associativity) : int_scope. (** * Strings and char *) (** Append strings. *) Parameter ostring_app : ocaml_string -> ocaml_string -> ocaml_string. (** Compare strings. *) Parameter ostring_eqb : ocaml_string -> ocaml_string -> bool. (** Compare characters. *) Parameter char_eqb : char -> char -> bool. (** Convert a [char] to an [int]. *) Parameter int_of_char : char -> int. (** Convert an [int] to a [char]. Equals [None] if the argument is greater than 255. *) Parameter char_of_int_opt : int -> option char. (** Convert an [int] to a [char], in [IO]. Throws an [Invalid_argument] exception if the argument is greater than 255. *) Parameter char_of_int_io : int -> IO char. (** Return the string representation of a boolean. *) Parameter ostring_of_bool : bool -> ocaml_string. (** Show an [int] as an [ocaml_string]. *) Parameter ostring_of_int : int -> ocaml_string. (** Parse an [ocaml_string] into an [int]. *) Parameter int_of_ostring_opt : ocaml_string -> option int. (** Notes: - There is no total [int_of_ostring]. (See [IO_Unsafe.unsafe_int_of_ostring].) - Comparisons between mutable structures ([bytes], [ref]) should happen in IO. *) (** * Exceptions *) (** Throw an [Invalid_argument] exception. *) Parameter invalid_arg : forall {a}, ocaml_string -> IO a. (** Throw a [Failure] exception. *) Parameter failwith : forall {a}, ocaml_string -> IO a. (** * Standard channels *) Parameter stdin : in_channel. Parameter stdout : out_channel. Parameter stderr : out_channel. (** ** [stdout] *) Parameter print_char : char -> IO unit. Parameter print_bytes : bytes -> IO unit. Parameter print_int : int -> IO unit. Parameter print_string : ocaml_string -> IO unit. Parameter print_endline : ocaml_string -> IO unit. Parameter print_newline : IO unit. (** ** [stderr] *) Parameter prerr_char : char -> IO unit. Parameter prerr_bytes : bytes -> IO unit. Parameter prerr_int : int -> IO unit. Parameter prerr_string : ocaml_string -> IO unit. Parameter prerr_endline : ocaml_string -> IO unit. Parameter prerr_newline : IO unit. (** ** [stdin] *) Parameter read_line : IO ocaml_string. Parameter read_int : IO int. Parameter read_int_opt : IO (option int). (** * File handles *) (** ** Output *) (** Open a file for output. *) Parameter open_out : ocaml_string -> IO out_channel. (** Close an output file. *) Parameter close_out : out_channel -> IO unit. (** Same as [close_out], but ignore all errors. *) Parameter close_out_noerr : out_channel -> IO unit. (** Flush output buffers. *) Parameter flush : out_channel -> IO unit. Parameter flush_all : IO unit. Parameter output_char : out_channel -> char -> IO unit. Parameter output_string : out_channel -> ocaml_string -> IO unit. Parameter output_bytes : out_channel -> bytes -> IO unit. Parameter output_substring : out_channel -> ocaml_string -> int -> int -> IO unit. Parameter output_byte : out_channel -> int -> IO unit. (** ** Input *) (** Open a file for input. *) Parameter open_in : ocaml_string -> IO in_channel. (** Close an input file. *) Parameter close_in : in_channel -> IO unit. (** Same as [close_in], but ignore all errors. *) Parameter close_in_noerr : in_channel -> IO unit. Parameter input_char : in_channel -> IO char. Parameter input_line : in_channel -> IO ocaml_string. (** [input ic buf pos len] reads up to [len] characters from the given channel [ic], storing them in byte sequence [buf], starting at character number [pos]. It returns the actual number of characters read, between 0 and [len] (inclusive). A return value of 0 means that the end of file was reached. A return value between 0 and [len] exclusive means that not all requested [len] characters were read, either because no more characters were available at that time, or because the implementation found it convenient to do a partial read; [input] must be called again to read the remaining characters, if desired. (See also [really_input] for reading exactly [len] characters.) Exception [Invalid_argument "input"] is raised if [pos] and [len] do not designate a valid range of [buf]. *) Parameter input : in_channel -> bytes -> int -> int -> IO int. (** [really_input ic buf pos len] reads [len] characters from channel [ic], storing them in byte sequence [buf], starting at character number [pos]. @raise End_of_file if the end of file is reached before [len] characters have been read. @raise Invalid_argument if [pos] and [len] do not designate a valid range of [buf]. *) Parameter really_input : in_channel -> bytes -> int -> int -> IO unit. (** [really_input_string ic len] reads [len] characters from channel [ic] and returns them in a new string. @raise End_of_file if the end of file is reached before [len] characters have been read. *) Parameter really_input_string : in_channel -> int -> IO ocaml_string. Parameter input_byte : in_channel -> IO int. (** Return the size (number of characters) of the regular file on which the given channel is opened. If the channel is opened on a file that is not a regular file, the result is meaningless. The returned size does not take into account the end-of-line translations that can be performed when reading from a channel opened in text mode. *) Parameter in_channel_length : in_channel -> IO int. (** * Mutable references *) Parameter new_ref : forall {a}, a -> IO (ref a). Parameter read_ref : forall {a}, ref a -> IO a. Parameter write_ref : forall {a}, ref a -> a -> IO unit. Parameter incr_ref : ref int -> IO unit. Parameter decr_ref : ref int -> IO unit. (** * Program termination *) (** Terminate with an exit code. (0 for success.) *) Parameter exit : forall {a}, int -> IO a. (** * Extraction *) #if OCAML_VERSION >= (4, 8, 0) (** ** Types *) Extract Inlined Constant ocaml_string => "String.t". Extract Inlined Constant char => "char". Extract Inlined Constant float => "float". Extract Inlined Constant bytes => "bytes". Extract Inlined Constant in_channel => "Stdlib.in_channel". Extract Inlined Constant out_channel => "Stdlib.out_channel". Extract Constant ref "'a" => "'a Stdlib.ref". (** ** Operations on [int] *) Extract Inlined Constant int_add => "Stdlib.(+)". Extract Inlined Constant int_sub => "Stdlib.(-)". Extract Inlined Constant int_mul => "Stdlib.( * )". Extract Inlined Constant int_div_opt => "fun x y -> try Some (x Stdlib./ y) with Division_by_zero -> None". Extract Inlined Constant int_mod_opt => "fun x y -> try Some Stdlib.(x mod y) with Division_by_zero -> None". Extract Inlined Constant int_eqb => "Stdlib.(=)". Extract Inlined Constant int_neqb => "Stdlib.(<>)". Extract Inlined Constant int_le => "Stdlib.(<=)". Extract Inlined Constant int_lt => "Stdlib.(<)". Extract Inlined Constant int_min => "Stdlib.min". Extract Inlined Constant int_max => "Stdlib.max". Extract Inlined Constant land => "Stdlib.(land)". Extract Inlined Constant lor => "Stdlib.(lor)". Extract Inlined Constant lxor => "Stdlib.(lxor)". Extract Inlined Constant lnot => "Stdlib.lnot". Extract Inlined Constant max_int => "Stdlib.max_int". Extract Inlined Constant min_int => "Stdlib.min_int". (** ** Misc *) Extract Inlined Constant ostring_app => "Stdlib.(^)". Extract Inlined Constant ostring_eqb => "Stdlib.(=)". Extract Inlined Constant char_eqb => "Stdlib.(=)". Extract Inlined Constant int_of_char => "Stdlib.int_of_char". Extract Constant char_of_int_opt => "fun n -> try Some (Stdlib.char_of_int n) with Invalid_argument _ -> None". Extract Constant char_of_int_io => "fun n k -> k (Stdlib.char_of_int n)". Extract Constant ostring_of_bool => "Stdlib.string_of_bool". Extract Inlined Constant ostring_of_int => "Stdlib.string_of_int". Extract Inlined Constant int_of_ostring_opt => "Stdlib.int_of_string_opt". (** ** Exceptions *) Extract Inlined Constant invalid_arg => "Stdlib.invalid_arg". Extract Inlined Constant failwith => "Stdlib.failwith". (** ** Standard channels *) Extract Inlined Constant stdin => "Stdlib.stdin". Extract Inlined Constant stdout => "Stdlib.stdout". Extract Inlined Constant stderr => "Stdlib.stderr". (** *** [stdout] *) Extract Constant print_char => "fun c k -> k (Stdlib.print_char c)". Extract Constant print_bytes => "fun b k -> k (Stdlib.print_bytes b)". Extract Constant print_int => "fun n k -> k (Stdlib.print_int n)". Extract Constant print_string => "fun s k -> k (Stdlib.print_string s)". Extract Constant print_endline => "fun s k -> k (Stdlib.print_endline s)". Extract Constant print_newline => "fun k -> k (Stdlib.print_newline ())". (** *** [stderr] *) Extract Constant prerr_char => "fun c k -> k (Stdlib.prerr_char c)". Extract Constant prerr_bytes => "fun bs k -> k (Stdlib.prerr_bytes bs)". Extract Constant prerr_int => "fun n k -> k (Stdlib.prerr_int n)". Extract Constant prerr_string => "fun s k -> k (Stdlib.prerr_string s)". Extract Constant prerr_endline => "fun s k -> k (Stdlib.prerr_endline s)". Extract Constant prerr_newline => "fun k -> k (Stdlib.prerr_newline ())". (** *** [stdin] *) Extract Constant read_line => "fun k -> k (Stdlib.read_line ())". Extract Constant read_int => "fun k -> k (Stdlib.read_int ())". Extract Constant read_int_opt => "fun k -> k (Stdlib.read_int_opt ())". (** ** File handles *) (** *** Output *) Extract Constant open_out => "fun s k -> k (Stdlib.open_out s)". Extract Constant flush => "fun h k -> k (Stdlib.flush h)". Extract Constant flush_all => "fun k -> k (Stdlib.flush_all ())". Extract Constant output_char => "fun h c k -> k (Stdlib.output_char h c)". Extract Constant output_string => "fun h s k -> k (Stdlib.output_string h s)". Extract Constant output_bytes => "fun h b k -> k (Stdlib.output_bytes h b)". Extract Constant output_byte => "fun h b k -> k (Stdlib.output_byte h b)". Extract Constant output_substring => "fun h s i n k -> k (Stdlib.output_substring h s i n)". Extract Constant close_out => "fun h k -> k (close_out h)". Extract Constant close_out_noerr => "fun h k -> k (close_out_noerr h)". (** *** Input *) Extract Constant open_in => "fun s k -> k (Stdlib.open_in s)". Extract Constant input_char => "fun h k -> k (Stdlib.input_char h)". Extract Constant input_line => "fun h k -> k (Stdlib.input_line h)". Extract Constant input => "fun h b p l k -> k (Stdlib.input h b p l)". Extract Constant really_input => "fun h b p l k -> k (Stdlib.really_input h b p l)". Extract Constant really_input_string => "fun h l k -> k (Stdlib.really_input_string h l)". Extract Constant input_byte => "fun h k -> k (Stdlib.input_byte h)". Extract Constant in_channel_length => "fun h k -> k (Stdlib.in_channel_length h)". Extract Constant close_in => "fun h k -> k (Stdlib.close_in h)". Extract Constant close_in_noerr => "fun h k -> k (Stdlib.close_in_noerr h)". (** ** Mutable references *) Extract Constant new_ref => "fun x k -> k (Stdlib.ref x)". Extract Constant read_ref => "fun r k -> k (Stdlib.(!) r)". Extract Constant write_ref => "fun r x k -> k (Stdlib.(:=) r x)". Extract Constant incr_ref => "fun r k -> k (Stdlib.incr r)". Extract Constant decr_ref => "fun r k -> k (Stdlib.decr r)". (** ** Program termination *) Extract Constant exit => "fun n k -> k (Stdlib.exit n)". #else (** ** Types *) Extract Inlined Constant ocaml_string => "String.t". Extract Inlined Constant char => "char". Extract Inlined Constant float => "float". Extract Inlined Constant bytes => "bytes". Extract Inlined Constant in_channel => "Pervasives.in_channel". Extract Inlined Constant out_channel => "Pervasives.out_channel". Extract Constant ref "'a" => "'a Pervasives.ref". (** ** Operations on [int] *) Extract Inlined Constant int_add => "Pervasives.(+)". Extract Inlined Constant int_sub => "Pervasives.(-)". Extract Inlined Constant int_mul => "Pervasives.( * )". Extract Inlined Constant int_div_opt => "fun x y -> try Some (x Pervasives./ y) with Division_by_zero -> None". Extract Inlined Constant int_mod_opt => "fun x y -> try Some Pervasives.(x mod y) with Division_by_zero -> None". Extract Inlined Constant int_eqb => "Pervasives.(=)". Extract Inlined Constant int_neqb => "Pervasives.(<>)". Extract Inlined Constant int_le => "Pervasives.(<=)". Extract Inlined Constant int_lt => "Pervasives.(<)". Extract Inlined Constant int_min => "Pervasives.min". Extract Inlined Constant int_max => "Pervasives.max". Extract Inlined Constant land => "Pervasives.(land)". Extract Inlined Constant lor => "Pervasives.(lor)". Extract Inlined Constant lxor => "Pervasives.(lxor)". Extract Inlined Constant lnot => "Pervasives.lnot". Extract Inlined Constant max_int => "Pervasives.max_int". Extract Inlined Constant min_int => "Pervasives.min_int". (** ** Misc *) Extract Inlined Constant ostring_app => "Pervasives.(^)". Extract Inlined Constant ostring_eqb => "Pervasives.(=)". Extract Inlined Constant char_eqb => "Pervasives.(=)". Extract Inlined Constant int_of_char => "Pervasives.int_of_char". Extract Constant char_of_int_opt => "fun n -> try Some (Pervasives.char_of_int n) with Invalid_argument _ -> None". Extract Constant char_of_int_io => "fun n k -> k (Pervasives.char_of_int n)". Extract Constant ostring_of_bool => "Pervasives.string_of_bool". Extract Inlined Constant ostring_of_int => "Pervasives.string_of_int". Extract Inlined Constant int_of_ostring_opt => "Pervasives.int_of_string_opt". (** ** Exceptions *) Extract Inlined Constant invalid_arg => "Pervasives.invalid_arg". Extract Inlined Constant failwith => "Pervasives.failwith". (** ** Standard channels *) Extract Inlined Constant stdin => "Pervasives.stdin". Extract Inlined Constant stdout => "Pervasives.stdout". Extract Inlined Constant stderr => "Pervasives.stderr". (** *** [stdout] *) Extract Constant print_char => "fun c k -> k (Pervasives.print_char c)". Extract Constant print_bytes => "fun b k -> k (Pervasives.print_bytes b)". Extract Constant print_int => "fun n k -> k (Pervasives.print_int n)". Extract Constant print_string => "fun s k -> k (Pervasives.print_string s)". Extract Constant print_endline => "fun s k -> k (Pervasives.print_endline s)". Extract Constant print_newline => "fun k -> k (Pervasives.print_newline ())". (** *** [stderr] *) Extract Constant prerr_char => "fun c k -> k (Pervasives.prerr_char c)". Extract Constant prerr_bytes => "fun bs k -> k (Pervasives.prerr_bytes bs)". Extract Constant prerr_int => "fun n k -> k (Pervasives.prerr_int n)". Extract Constant prerr_string => "fun s k -> k (Pervasives.prerr_string s)". Extract Constant prerr_endline => "fun s k -> k (Pervasives.prerr_endline s)". Extract Constant prerr_newline => "fun k -> k (Pervasives.prerr_newline ())". (** *** [stdin] *) Extract Constant read_line => "fun k -> k (Pervasives.read_line ())". Extract Constant read_int => "fun k -> k (Pervasives.read_int ())". Extract Constant read_int_opt => "fun k -> k (Pervasives.read_int_opt ())". (** ** File handles *) (** *** Output *) Extract Constant open_out => "fun s k -> k (Pervasives.open_out s)". Extract Constant flush => "fun h k -> k (Pervasives.flush h)". Extract Constant flush_all => "fun k -> k (Pervasives.flush_all ())". Extract Constant output_char => "fun h c k -> k (Pervasives.output_char h c)". Extract Constant output_string => "fun h s k -> k (Pervasives.output_string h s)". Extract Constant output_bytes => "fun h b k -> k (Pervasives.output_bytes h b)". Extract Constant output_byte => "fun h b k -> k (Pervasives.output_byte h b)". Extract Constant output_substring => "fun h s i n k -> k (Pervasives.output_substring h s i n)". Extract Constant close_out => "fun h k -> k (close_out h)". Extract Constant close_out_noerr => "fun h k -> k (close_out_noerr h)". (** *** Input *) Extract Constant open_in => "fun s k -> k (Pervasives.open_in s)". Extract Constant input_char => "fun h k -> k (Pervasives.input_char h)". Extract Constant input_line => "fun h k -> k (Pervasives.input_line h)". Extract Constant input => "fun h b p l k -> k (Pervasives.input h b p l)". Extract Constant really_input => "fun h b p l k -> k (Pervasives.really_input h b p l)". Extract Constant really_input_string => "fun h l k -> k (Pervasives.really_input_string h l)". Extract Constant input_byte => "fun h k -> k (Pervasives.input_byte h)". Extract Constant in_channel_length => "fun h k -> k (Pervasives.in_channel_length h)". Extract Constant close_in => "fun h k -> k (Pervasives.close_in h)". Extract Constant close_in_noerr => "fun h k -> k (Pervasives.close_in_noerr h)". (** ** Mutable references *) Extract Constant new_ref => "fun x k -> k (Pervasives.ref x)". Extract Constant read_ref => "fun r k -> k (Pervasives.(!) r)". Extract Constant write_ref => "fun r x k -> k (Pervasives.(:=) r x)". Extract Constant incr_ref => "fun r k -> k (Pervasives.incr r)". Extract Constant decr_ref => "fun r k -> k (Pervasives.decr r)". (** ** Program termination *) Extract Constant exit => "fun n k -> k (Pervasives.exit n)". #endif coq-simple-io-1.11.0/src/IO_StdlibAxioms.v000066400000000000000000000002741476017402600202310ustar00rootroot00000000000000(** * Theory for [IO_Stdlib] *) (* begin hide *) From SimpleIO Require Import IO_Stdlib. (* end hide *) Axiom char_of_int_of_char : forall c, char_of_int_opt (int_of_char c) = Some c. coq-simple-io-1.11.0/src/IO_String.v.cppo000066400000000000000000000055321476017402600200370ustar00rootroot00000000000000(** * Strings *) (** The [String] module from OCaml's standard library. Operations are meant to be used qualified, e.g., [OString.length]. The inner module is named [OString] to avoid the conflict with with [Coq.Strings.String]. *) (* begin hide *) From Coq Require Import Strings.String Strings.Ascii ExtrOcamlIntConv. From SimpleIO Require Import IO_Stdlib. Extraction Blacklist Bytes String. (* end hide *) (** * String module *) Module OString. (** Length of an [ocaml_string]. *) Parameter length : ocaml_string -> int. Extract Inlined Constant length => "String.length". (** Index into an [ocaml_string]. Equals [None] if out of bounds. *) Parameter get_opt : ocaml_string -> int -> option char. Extract Constant get_opt => "fun s i -> try Some (String.get s i) with Invalid_argument _ -> None". (** Concatenates strings with a separator. *) Parameter concat : ocaml_string -> list ocaml_string -> ocaml_string. Extract Inlined Constant concat => "String.concat". (** A representation of a string with special characters represented by their escaped sequences. *) Parameter escaped : ocaml_string -> ocaml_string. Extract Inlined Constant escaped => "String.escaped". (** ** Unsafe functions *) Module Unsafe. (** Index into an [ocaml_string], without an [option] wrapper. Throws an exception if out of bounds. *) Parameter get : ocaml_string -> int -> char. Extract Inlined Constant get => "String.get". (** Create a string of repeated characters. Throws an exception if [n < 0] or [n > Sys.max_string_length]. *) Parameter make : int -> char -> ocaml_string. Extract Inlined Constant make => "String.make". (** Create a string with a function from indices to characters. Throws an exception if [n < 0] or [n > Sys.max_string_length]. *) Parameter init : int -> (int -> char) -> ocaml_string. Extract Inlined Constant init => "String.init". (** [sub i len s] is the substring of [s] with length [len] starting at index [i]. Throws an exception if out of bounds. *) Parameter sub : ocaml_string -> int -> int -> ocaml_string. Extract Inlined Constant sub => "String.sub". End Unsafe. (** * Extras *) (** Conversion between [ocaml_string] and [list char]. *) Parameter to_list : ocaml_string -> list char. Parameter of_list : list char -> ocaml_string. Axiom from_to_list : forall s, to_list (of_list s) = s. Axiom to_from_list : forall s, of_list (to_list s) = s. (** ** Extraction *) Extract Constant to_list => "fun s -> let rec go n z = if n = -1 then z else go (n-1) (String.get s n :: z) in go (String.length s - 1) []". Extract Constant of_list => "fun z -> Bytes.unsafe_to_string ( let b = Bytes.create (List.length z) in let rec go z i = match z with | c :: z -> Bytes.set b i c; go z (i+1) | [] -> b in go z 0)". End OString. coq-simple-io-1.11.0/src/IO_Sys.v000066400000000000000000000042241476017402600164040ustar00rootroot00000000000000(** * System interface *) (** Note: descriptions of the interface are derived from OCaml's documentation: https://caml.inria.fr/pub/docs/manual-ocaml/libref/Sys.html *) (* begin hide *) From Coq Require Import ExtrOcamlIntConv. From SimpleIO Require Import IO_Monad IO_Stdlib. (* end hide *) Module OSys. (** Execute the given shell command and return its exit code. The argument of [Sys.command] is generally the name of a command followed by zero, one or several arguments, separated by whitespace. The given argument is interpreted by a shell: either the Windows shell [cmd.exe] for the Win32 ports of OCaml, or the POSIX shell [sh] for other ports. It can contain shell builtin commands such as [echo], and also special characters such as file redirections [>] and [<], which will be honored by the shell. Conversely, whitespace or special shell characters occurring in command names or in their arguments must be quoted or escaped so that the shell does not interpret them. The quoting rules vary between the POSIX shell and the Windows shell. The [Filename.quote_command] performs the appropriate quoting given a command name, a list of arguments, and optional file redirections. *) Parameter command: ocaml_string -> IO int. (** Return the value associated to a variable in the process environment. Raise [Not_found] if the variable is unbound. *) Parameter getenv : ocaml_string -> IO ocaml_string. (** Return the value associated to a variable in the process environment or [None] if the variable is unbound. *) Parameter getenv_opt: ocaml_string -> IO (option ocaml_string). (** Return the processor time, in seconds, used by the program since the beginning of execution. *) Parameter time : IO float. Parameter argv : IO (list ocaml_string). (** ** Extraction *) Extract Constant command => "fun c k -> k (Sys.command c)". Extract Constant getenv => "fun e k -> k (Sys.getenv e)". Extract Constant getenv_opt => "fun e k -> k (Sys.getenv_opt e)". Extract Constant time => "fun k -> k (Sys.time ())". Extract Constant argv => "fun k -> k (Array.to_list (Sys.argv))". End OSys. coq-simple-io-1.11.0/src/IO_Unix.v000066400000000000000000000414171476017402600165560ustar00rootroot00000000000000(** * Interface to the Unix system *) (** Note: descriptions of the interface are derived from OCaml's documentation: https://caml.inria.fr/pub/docs/manual-ocaml/libref/Unix.html *) (* begin hide *) From Coq Require Import ExtrOcamlIntConv. From SimpleIO Require Import IO_Monad IO_Stdlib IO_Float. (* end hide *) Module OUnix. (** ** Basic file input/output *) (** The abstract type of file descriptors. *) Parameter file_descr : Set. Parameter file_descr_eqb : file_descr -> file_descr -> bool. (** Close a file descriptor. *) Parameter close : file_descr -> IO unit. (** ** Polling *) (** Wait until some input/output operations become possible on some channels. The three list arguments are, respectively, a set of descriptors to check for reading (first argument), for writing (second argument), or for exceptional conditions (third argument). The fourth argument is the maximal timeout, in seconds; a negative fourth argument means no timeout (unbounded wait). The result is composed of three sets of descriptors: those ready for reading (first component), ready for writing (second component), and over which an exceptional condition is pending (third component). *) Parameter select : list file_descr -> list file_descr -> list file_descr -> float -> IO (list file_descr * list file_descr * list file_descr). (** ** Time functions *) (** Return the current time since 00:00:00 GMT, Jan. 1, 1970, in seconds. *) Parameter time : IO float. (** Same as [time], but with resolution better than 1 second. *) Parameter gettimeofday : IO float. (** Stop execution for the given number of seconds. *) Parameter sleep : int -> IO unit. (** ** Internet addresses *) (** The abstract type of Internet addresses. *) Parameter inet_addr : Set. (** Conversion from the printable representation of an Internet address to its internal representation. The argument string consists of 4 numbers separated by periods ([XXX.YYY.ZZZ.TTT]) for IPv4 addresses, and up to 8 numbers separated by colons for IPv6 addresses. @raise Failure when given a string that does not match these formats. *) Parameter inet_addr_of_string : ocaml_string -> IO inet_addr. (** Return the printable representation of the given Internet address. See [inet_addr_of_string] for a description of the printable representation. *) Parameter string_of_inet_addr : inet_addr -> ocaml_string. (** A special IPv4 address, for use only with [bind], representing all the Internet addresses that the host machine possesses. *) Parameter inet_addr_any : inet_addr. (** A special IPv4 address representing the host machine ([127.0.0.1]). *) Parameter inet_addr_loopback : inet_addr. (** ** Sockets *) (** The type of socket domains. Not all platforms support IPv6 sockets (type [PF_INET6]). Windows does not support [PF_UNIX]. *) Variant socket_domain := PF_UNIX (** Unix domain *) | PF_INET (** Internet domain (IPv4) *) | PF_INET6. (** Internet domain (IPv6) *) (** The type of socket addresses. [ADDR_UNIX name] is a socket address in the Unix domain; [name] is a file name in the file system. [ADDR_INET addr port] is a socket address in the Internet domain; [addr] is the Internet address of the machine, and [port] is the port number. *) Variant socket_type := SOCK_STREAM (** Stream socket *) | SOCK_DGRAM (** Datagram socket *) | SOCK_RAW (** Raw socket *) | SOCK_SEQPACKET. (** Sequenced packets socket *) (** The type of socket addresses. [ADDR_UNIX name] is a socket address in the Unix domain; [name] is a file name in the file system. [ADDR_INET addr port] is a socket address in the Internet domain; [addr] is the Internet address of the machine, and [port] is the port number. *) Variant sockaddr := ADDR_UNIX : ocaml_string -> sockaddr | ADDR_INET : inet_addr -> int -> sockaddr. (** Create a new socket in the given domain, and with the given kind. The third argument is the protocol type; 0 selects the default protocol for that kind of sockets. *) Parameter socket : socket_domain -> socket_type -> int -> IO file_descr. (** Accept connections on the given socket. The returned descriptor is a socket connected to the client; the returned address is the address of the connecting client. *) Parameter accept : file_descr -> IO (file_descr * sockaddr). (** Bind a socket to an address. *) Parameter bind : file_descr -> sockaddr -> IO unit. (** Connect a socket to an address. *) Parameter connect : file_descr -> sockaddr -> IO unit. (** Set up a socket for receiving connection requests. The integer argument is the maximal number of pending requests. *) Parameter listen : file_descr -> int -> IO unit. (** The flags for [Unix.recvfrom] and [sendto]. *) Variant msg_flag := MSG_OOB | MSG_DONTROUTE | MSG_PEEK. (** Receive data from a connected socket. *) Parameter recv : file_descr -> bytes -> int -> int -> list msg_flag -> IO int. (** Send data over a connected socket. *) Parameter send : file_descr -> bytes -> int -> int -> list msg_flag -> IO int. (** ** Socket options *) (** The socket options that can be consulted with [IO_Unix.getsockopt] and modified with [IO_Unix.setsockopt]. These options have a boolean ([true]/[false]) value. *) Variant socket_bool_option := SO_DEBUG (* Record debugging information *) | SO_BROADCAST (* Permit sending of broadcast messages *) | SO_REUSEADDR (* Allow reuse of local addresses for bind *) | SO_KEEPALIVE (* Keep connection active *) | SO_DONTROUTE (* Bypass the standard routing algorithms *) | SO_OOBINLINE (* Leave out-of-band data in line *) | SO_ACCEPTCONN (* Report whether socket listening is enabled *) | TCP_NODELAY (* Control the Nagle algorithm for TCP sockets *) | IPV6_ONLY. (* Forbid binding an IPv6 socket to an IPv4 address *) Variant socket_float_option := SO_RCVTIMEO (* Timeout for input operations *) | SO_SNDTIMEO. (* Timeout for output operations *) (** Return the current status of a boolean-valued option in the given socket. *) Parameter getsockopt : file_descr -> socket_bool_option -> IO bool. (** Set or clear a boolean-valued option in the given socket. *) Parameter setsockopt : file_descr -> socket_bool_option -> bool -> IO unit. (** Return the current status of a floating-point socket option. *) Parameter getsockopt_float : OUnix.file_descr -> socket_float_option -> IO float. (** Set a floating-point option in the given socket. *) Parameter setsockopt_float : OUnix.file_descr -> socket_float_option -> float -> IO unit. Module Time. (** Simple measure of time based on [int] to set socket timeouts with [setsockopt_time]. *) Inductive time := | Seconds : int -> time | Microsec : int -> time . (** Convert [time] to seconds as a [float]. *) Definition time_as_seconds (t : time) : float := match t with | Seconds n => OFloat.of_int n | Microsec n => OFloat.micro (OFloat.of_int n) end. (** Set a timeout option in the given socket. *) Definition setsock_timeout : OUnix.file_descr -> socket_float_option -> time -> IO unit := fun sock opt t => setsockopt_float sock opt (time_as_seconds t). End Time. Record addr_info : Type := Mk_addr_info { ai_family : socket_domain ; ai_socktype : socket_type ; ai_protocol : int ; ai_addr : sockaddr ; ai_canonname : ocaml_string }. Inductive getaddrinfo_option : Type := | AI_FAMILY (sd : socket_domain) | AI_SOCKTYPE (st : socket_type) | AI_PROTOCOL (proto : int) | AI_NUMERICHOST | AI_CANONNAME | AI_PASSIVE . Parameter getaddrinfo : ocaml_string -> ocaml_string -> list getaddrinfo_option -> IO (list addr_info). (** The type of error codes. Errors defined in the POSIX standard and additional errors from UNIX98 and BSD. All other errors are mapped to [EUNKNOWNERR]. *) Inductive error := | E2BIG (* Argument list too long *) | EACCES (* Permission denied *) | EAGAIN (* Resource temporarily unavailable; try again *) | EBADF (* Bad file descriptor *) | EBUSY (* Resource unavailable *) | ECHILD (* No child process *) | EDEADLK (* Resource deadlock would occur *) | EDOM (* Domain error for math functions, etc. *) | EEXIST (* File exists *) | EFAULT (* Bad address *) | EFBIG (* File too large *) | EINTR (* Function interrupted by signal *) | EINVAL (* Invalid argument *) | EIO (* Hardware I/O error *) | EISDIR (* Is a directory *) | EMFILE (* Too many open files by the process *) | EMLINK (* Too many links *) | ENAMETOOLONG (* Filename too long *) | ENFILE (* Too many open files in the system *) | ENODEV (* No such device *) | ENOENT (* No such file or directory *) | ENOEXEC (* Not an executable file *) | ENOLCK (* No locks available *) | ENOMEM (* Not enough memory *) | ENOSPC (* No space left on device *) | ENOSYS (* Function not supported *) | ENOTDIR (* Not a directory *) | ENOTEMPTY (* Directory not empty *) | ENOTTY (* Inappropriate I/O control operation *) | ENXIO (* No such device or address *) | EPERM (* Operation not permitted *) | EPIPE (* Broken pipe *) | ERANGE (* Result too large *) | EROFS (* Read-only file system *) | ESPIPE (* Invalid seek e.g. on a pipe *) | ESRCH (* No such process *) | EXDEV (* Invalid link *) | EWOULDBLOCK (* Operation would block *) | EINPROGRESS (* Operation now in progress *) | EALREADY (* Operation already in progress *) | ENOTSOCK (* Socket operation on non-socket *) | EDESTADDRREQ (* Destination address required *) | EMSGSIZE (* Message too long *) | EPROTOTYPE (* Protocol wrong type for socket *) | ENOPROTOOPT (* Protocol not available *) | EPROTONOSUPPORT (* Protocol not supported *) | ESOCKTNOSUPPORT (* Socket type not supported *) | EOPNOTSUPP (* Operation not supported on socket *) | EPFNOSUPPORT (* Protocol family not supported *) | EAFNOSUPPORT (* Address family not supported by protocol family *) | EADDRINUSE (* Address already in use *) | EADDRNOTAVAIL (* Can't assign requested address *) | ENETDOWN (* Network is down *) | ENETUNREACH (* Network is unreachable *) | ENETRESET (* Network dropped connection on reset *) | ECONNABORTED (* Software caused connection abort *) | ECONNRESET (* Connection reset by peer *) | ENOBUFS (* No buffer space available *) | EISCONN (* Socket is already connected *) | ENOTCONN (* Socket is not connected *) | ESHUTDOWN (* Can't send after socket shutdown *) | ETOOMANYREFS (* Too many references: can't splice *) | ETIMEDOUT (* Connection timed out *) | ECONNREFUSED (* Connection refused *) | EHOSTDOWN (* Host is down *) | EHOSTUNREACH (* No route to host *) | ELOOP (* Too many levels of symbolic links *) | EOVERFLOW (* File size or position not representable *) | EUNKNOWNERR (code : int) (* Unknown error *) . (** Return a string describing the given error code. *) Parameter error_message : error -> ocaml_string. (** Catch a Unix error. The first component is the error code; the second component is the function name; the third component is the string parameter to the function, if it has one, or the empty string otherwise. *) Parameter catch_error : forall {a}, IO a -> (error -> ocaml_string -> ocaml_string -> IO a) -> IO a. (** Raise a Unix error. Useful to rethrow errors that can't be handled. *) Parameter raise_error : forall {a}, error -> ocaml_string -> ocaml_string -> IO a. (* begin hide *) Extract Inlined Constant file_descr => "Unix.file_descr". Extract Inlined Constant file_descr_eqb => "(=)". Extract Inlined Constant inet_addr => "Unix.inet_addr". Extract Inlined Constant inet_addr_any => "Unix.inet_addr_any". Extract Inlined Constant inet_addr_loopback => "Unix.inet_addr_loopback". Extract Inlined Constant string_of_inet_addr => "Unix.string_of_inet_addr". Extract Inductive socket_domain => "Unix.socket_domain" ["Unix.PF_UNIX" "Unix.PF_INET" "Unix.PF_INET6"]. Extract Inductive socket_type => "Unix.socket_type" ["Unix.SOCK_STREAM" "Unix.SOCK_DGRAM" "Unix.SOCK_RAW" "Unix.SOCK_SEQPACKET"]. Extract Inductive sockaddr => "Unix.sockaddr" ["Unix.ADDR_UNIX" "Unix.ADDR_INET"]. Extract Inductive msg_flag => "Unix.msg_flag" ["Unix.MSG_OOB" "Unix.MSG_DONTROUTE" "Unix.MSG_PEEK"]. Extract Inductive socket_bool_option => "Unix.socket_bool_option" ["Unix.SO_DEBUG" "Unix.SO_BROADCAST" "Unix.SO_REUSEADDR" "Unix.SO_KEEPALIVE" "Unix.SO_DONTROUTE" "Unix.OOBINLINE" "Unix.SO_ACCEPTCONN" "Unix.TCP_NODELAY" "Unix.IPV6_ONLY"]. Extract Inductive socket_float_option => "Unix.socket_float_option" ["Unix.SO_RCVTIMEO" "Unix.SO_SNDTIMEO"]. Extract Constant close => "fun f k -> k (Unix.close f)". Extract Constant time => "fun k -> k (Unix.time ())". Extract Constant gettimeofday => "fun k -> k (Unix.gettimeofday ())". Extract Constant sleep => "fun d k -> k (Unix.sleep d)". Extract Constant socket => "fun d t p k -> k (Unix.socket d t p)". Extract Constant accept => "fun f k -> k (Unix.accept f)". Extract Constant bind => "fun f a k -> k (Unix.bind f a)". Extract Constant connect => "fun f a k -> k (Unix.connect f a)". Extract Constant listen => "fun f i k -> k (Unix.listen f i)". Extract Constant recv => "fun f b o l g k -> k (Unix.recv f b o l g)". Extract Constant send => "fun f b o l g k -> k (Unix.send f b o l g)". Extract Constant getsockopt => "fun f o k -> k (Unix.getsockopt f o)". Extract Constant setsockopt => "fun f o b k -> k (Unix.setsockopt f o b)". Extract Constant getsockopt_float => "fun f o k -> k (Unix.getsockopt_float f o)". Extract Constant setsockopt_float => "fun f o v k -> k (Unix.setsockopt_float f o v)". Extract Constant inet_addr_of_string => "fun s k -> k (Unix.inet_addr_of_string s)". Extract Constant select => "fun r w e t k -> k (let (r',w',e') = Unix.select r w e t in ((r',w'),e'))". Extract Inductive addr_info => "Unix.addr_info" [ "(fun ai_family ai_socktype ai_protocol ai_addr ai_canonname -> Unix.{ ai_family ; ai_socktype ; ai_protocol ; ai_addr ; ai_canonname }" ] "Unix.(fun f ai -> f ai.ai_family ai.ai_socktype ai.ai_protocol ai.ai_addr ai.ai_canonname)". Extract Inductive getaddrinfo_option => "Unix.getaddrinfo_option" [ "Unix.AI_FAMILY" "Unix.AI_SOCKTYPE" "Unix.AI_PROTOCOL" "Unix.AI_NUMERICHOST" "Unix.AI_CANONNAME" "Unix.AI_PASSIVE" ]. Extract Constant getaddrinfo => "fun host service opts k -> k (Unix.getaddrinfo host service opts)". Extract Inductive error => "Unix.error" [ "Unix.E2BIG" "Unix.EACCES" "Unix.EAGAIN" "Unix.EBADF" "Unix.EBUSY" "Unix.ECHILD" "Unix.EDEADLK" "Unix.EDOM" "Unix.EEXIST" "Unix.EFAULT" "Unix.EFBIG" "Unix.EINTR" "Unix.EINVAL" "Unix.EIO" "Unix.EISDIR" "Unix.EMFILE" "Unix.EMLINK" "Unix.ENAMETOOLONG" "Unix.ENFILE" "Unix.ENODEV" "Unix.ENOENT" "Unix.ENOEXEC" "Unix.ENOLCK" "Unix.ENOMEM" "Unix.ENOSPC" "Unix.ENOSYS" "Unix.ENOTDIR" "Unix.ENOTEMPTY" "Unix.ENOTTY" "Unix.ENXIO" "Unix.EPERM" "Unix.EPIPE" "Unix.ERANGE" "Unix.EROFS" "Unix.ESPIPE" "Unix.ESRCH" "Unix.EXDEV" "Unix.EWOULDBLOCK" "Unix.EINPROGRESS" "Unix.EALREADY" "Unix.ENOTSOCK" "Unix.EDESTADDRREQ" "Unix.EMSGSIZE" "Unix.EPROTOTYPE" "Unix.ENOPROTOOPT" "Unix.EPROTONOSUPPORT" "Unix.ESOCKTNOSUPPORT" "Unix.EOPNOTSUPP" "Unix.EPFNOSUPPORT" "Unix.EAFNOSUPPORT" "Unix.EADDRINUSE" "Unix.EADDRNOTAVAIL" "Unix.ENETDOWN" "Unix.ENETUNREACH" "Unix.ENETRESET" "Unix.ECONNABORTED" "Unix.ECONNRESET" "Unix.ENOBUFS" "Unix.EISCONN" "Unix.ENOTCONN" "Unix.ESHUTDOWN" "Unix.ETOOMANYREFS" "Unix.ETIMEDOUT" "Unix.ECONNREFUSED" "Unix.EHOSTDOWN" "Unix.EHOSTUNREACH" "Unix.ELOOP" "Unix.EOVERFLOW" "Unix.EUNKNOWNERR" ]. Extract Inlined Constant error_message => "Unix.error_message". Extract Constant catch_error => "fun u h k -> match Obj.magic u (fun a -> a) with | exception Unix.Unix_error (e, fname, sparam) -> h e fname sparam k | a -> k a". Extract Constant raise_error => "fun e fname sparam _k -> raise (Unix.Unix_error (e, fname, sparam))". (* end hide *) End OUnix. coq-simple-io-1.11.0/src/IO_Unsafe.v.cppo000066400000000000000000000043751476017402600200160ustar00rootroot00000000000000(** * Unsafe primitives *) From Coq.extraction Require Import ExtrOcamlIntConv. From SimpleIO Require Import IO_Stdlib. (** Throws an exception if the divisor is 0. *) Parameter unsafe_int_div : int -> int -> int. (** Throws an exception if the divisor is 0. *) Parameter unsafe_int_mod : int -> int -> int. (** Throws an exception if the argument is smaller than 0 or greater than 255. *) Parameter unsafe_char_of_int : int -> char. (** Throws an exception if the argument string does not represent an integer. *) Parameter unsafe_int_of_ostring : ocaml_string -> int. (* N.B.: I am not sure whether these are actually unsafe. It depends on what "undefined" means here. It might be fine if the result is architecture dependent but still constant. They would be really unsafe if the result could change from one operation to the next. *) (** Logical shift left (treats [int] as unsigned). Undefined result if shift is negative or greater than [int] size. *) Parameter unsafe_lsl : int -> int -> int. (** Logical shift right (treats [int] as unsigned). Undefined result if shift is negative or greater than [int] size. *) Parameter unsafe_lsr : int -> int -> int. (** Arithmetic shift right (replicates the bit sign). Undefined result if shift is negative or greater than [int] size. *) Parameter unsafe_asr : int -> int -> int. #if OCAML_VERSION >= (4, 8, 0) Extract Inlined Constant unsafe_int_div => "Stdlib.(/)". Extract Inlined Constant unsafe_int_mod => "Stdlib.(mod)". Extract Inlined Constant unsafe_char_of_int => "Stdlib.char_of_int". Extract Inlined Constant unsafe_int_of_ostring => "Stdlib.int_of_string". Extract Inlined Constant unsafe_lsl => "Stdlib.(lsl)". Extract Inlined Constant unsafe_lsr => "Stdlib.(lsr)". Extract Inlined Constant unsafe_asr => "Stdlib.(asr)". #else Extract Inlined Constant unsafe_int_div => "Pervasives.(/)". Extract Inlined Constant unsafe_int_mod => "Pervasives.(mod)". Extract Inlined Constant unsafe_char_of_int => "Pervasives.char_of_int". Extract Inlined Constant unsafe_int_of_ostring => "Pervasives.int_of_string". Extract Inlined Constant unsafe_lsl => "Pervasives.(lsl)". Extract Inlined Constant unsafe_lsr => "Pervasives.(lsr)". Extract Inlined Constant unsafe_asr => "Pervasives.(asr)". #endif coq-simple-io-1.11.0/src/IO_UnsafeNat.v000066400000000000000000000025531476017402600175150ustar00rootroot00000000000000(** * Stdlib functions using [nat] instead of [int] *) (** [nat] are unary numbers, so this highly inefficient! These operations are unsafe when numbers exceed [max_int] in OCaml. *) (* begin hide *) From Coq.extraction Require Import ExtrOcamlIntConv. From SimpleIO Require Import IO_Monad IO_Stdlib. Import IO.Notations. Set Warnings "-extraction-opaque-accessed,-extraction". (* end hide *) Definition print_nat : nat -> IO unit := fun n => print_int (int_of_nat n). Definition prerr_nat : nat -> IO unit := fun n => prerr_int (int_of_nat n). Definition read_nat : IO nat := IO.map nat_of_int read_int. Definition read_nat_opt : IO (option nat) := IO.map (option_map nat_of_int) read_int_opt. Definition output_nat : out_channel -> nat -> IO unit := fun h n => output_string h (ostring_of_int (int_of_nat n)). Definition output_byte_nat : out_channel -> nat -> IO unit := fun h n => output_byte h (int_of_nat n). Definition input_byte_nat : in_channel -> IO nat := fun h => IO.map nat_of_int (input_byte h). Definition incr_ref_nat : ref nat -> IO unit := fun r => n <- read_ref r;; write_ref r (Nat.succ n). (** N.B.: 0 decreases to 0. *) Definition decr_ref_nat : ref nat -> IO unit := fun r => n <- read_ref r;; write_ref r (Nat.pred n). Definition exit_nat {a} : nat -> IO a := fun n => exit (int_of_nat n). coq-simple-io-1.11.0/src/SimpleIO.v000066400000000000000000000004001476017402600167100ustar00rootroot00000000000000(** * Main module *) (** This reexports the most common modules for doing IO in Coq. *) From SimpleIO Require Export SimpleIO_Plugin IO_Monad IO_Stdlib IO_StdlibAxioms IO_Stdlib IO_Exceptions IO_RawChar IO_String. coq-simple-io-1.11.0/src/SimpleIO_Plugin.v.cppo000066400000000000000000000003761476017402600212020ustar00rootroot00000000000000From Coq Require Import Extraction. #if COQ_VERSION >= (9, 0, 0) Declare ML Module "coq-simple-io.plugin". #elif COQ_VERSION >= (8, 16, 0) Declare ML Module "coqsimpleio_plugin:coq-simple-io.plugin". #else Declare ML Module "coqsimpleio_plugin". #endif coq-simple-io-1.11.0/src/dune000066400000000000000000000024601476017402600157260ustar00rootroot00000000000000(coq.theory (name SimpleIO) (package coq-simple-io) (plugins coq-simple-io.plugin)) (rule (alias compat) (target IO_Stdlib.v) (deps IO_Stdlib.v.cppo) (action (run %{bin:cppo} -V OCAML:%{ocaml_version} -V COQ:%{coq:version} -n %{deps} -o %{target}))) (rule (alias compat) (target IO_RawChar.v) (deps IO_RawChar.v.cppo) (action (run %{bin:cppo} -V OCAML:%{ocaml_version} -V COQ:%{coq:version} -n %{deps} -o %{target}))) (rule (alias compat) (target IO_String.v) (deps IO_String.v.cppo) (action (run %{bin:cppo} -V OCAML:%{ocaml_version} -V COQ:%{coq:version} -n %{deps} -o %{target}))) (rule (alias compat) (target IO_Filename.v) (deps IO_Filename.v.cppo) (action (run %{bin:cppo} -V OCAML:%{ocaml_version} -V COQ:%{coq:version} -n %{deps} -o %{target}))) (rule (alias compat) (target IO_Float.v) (deps IO_Float.v.cppo) (action (run %{bin:cppo} -V OCAML:%{ocaml_version} -V COQ:%{coq:version} -n %{deps} -o %{target}))) (rule (alias compat) (target IO_Unsafe.v) (deps IO_Unsafe.v.cppo) (action (run %{bin:cppo} -V OCAML:%{ocaml_version} -V COQ:%{coq:version} -n %{deps} -o %{target}))) (rule (alias compat) (target SimpleIO_Plugin.v) (deps SimpleIO_Plugin.v.cppo) (action (run %{bin:cppo} -V OCAML:%{ocaml_version} -V COQ:%{coq:version} -n %{deps} -o %{target}))) coq-simple-io-1.11.0/test/000077500000000000000000000000001476017402600152365ustar00rootroot00000000000000coq-simple-io-1.11.0/test/.gitignore000066400000000000000000000000061476017402600172220ustar00rootroot00000000000000*.ml* coq-simple-io-1.11.0/test/HelloWorld.expected000066400000000000000000000000371476017402600210340ustar00rootroot00000000000000Running main ... Hello, world! coq-simple-io-1.11.0/test/HelloWorld.v000066400000000000000000000002651476017402600175030ustar00rootroot00000000000000From SimpleIO Require Import SimpleIO. From Coq Require Import String. #[local] Open Scope string_scope. Definition main : IO unit := print_endline "Hello, world!". RunIO main. coq-simple-io-1.11.0/test/RunIO.expected000066400000000000000000000001171476017402600177540ustar00rootroot00000000000000Running (ORandom.init (int_of_nat 42);; coin;; coin;; coin) ... tail head tail coq-simple-io-1.11.0/test/RunIO.v000066400000000000000000000006201476017402600164170ustar00rootroot00000000000000From Coq Require Import ExtrOcamlIntConv String. From ExtLib Require Import Monad. From SimpleIO Require Import IO_Random SimpleIO. Import MonadNotation. Open Scope monad_scope. Open Scope string_scope. Definition coin : IO unit := b <- ORandom.bool tt;; print_endline (if b : bool then "head" else "tail"). RunIO (ORandom.init (int_of_nat 42);; coin;; coin;; coin). coq-simple-io-1.11.0/test/TestInt63.expected000066400000000000000000000000251476017402600205210ustar00rootroot00000000000000Running test_all ... coq-simple-io-1.11.0/test/TestInt63.v.cppo000066400000000000000000000075411476017402600201370ustar00rootroot00000000000000#if COQ_VERSION < (8, 14, 0) #define Uint63 Int63 #define uint63 int63 #endif #if COQ_VERSION >= (8, 15, 0) From Coq Require ExtrOcamlZBigInt. #endif From Coq Require Import ZArith NArith String DecimalString Uint63 Extraction ExtrOCamlInt63. #[local] Open Scope string_scope. From SimpleIO Require Import SimpleIO. Import IO.Notations. #if COQ_VERSION < (8, 16, 0) && COQ_VERSION >= (8, 15, 0) (* ExtrOCamlInt63 extracts Lt|Eq|Gt to -1|0|1 *) Extract Constant Nat.compare => "(fun n m -> if n=m then 0 else if n "(fun x y -> let s = Big_int_Z.compare_big_int x y in if s = 0 then 0 else if s < 0 then -1 else 1)". Extract Constant Pos.compare_cont => "(fun c x y -> let s = Big_int_Z.compare_big_int x y in if s = 0 then c else if s < 0 then -1 else 1)". Extract Constant N.compare => "(fun x y -> let s = Big_int_Z.compare_big_int x y in if s = 0 then 0 else if s < 0 then -1 else 1)". Extract Constant Z.compare => "(fun x y -> let s = Big_int_Z.compare_big_int x y in if s = 0 then 0 else if s < 0 then -1 else 1)". #endif Class Eq (A : Type) : Type := eqb : A -> A -> bool. Class Show (A : Type) : Type := show : A -> string. Global Instance Eq_prod {A B} `{Eq A, Eq B} : Eq (A * B) := fun x y => (eqb (fst x) (fst y) && eqb (snd x) (snd y))%bool. Global Instance Eq_bool : Eq bool := bool_eq. Global Instance Eq_int : Eq int := fun x y => #if COQ_VERSION >= (8, 13, 0) (x =? y)%uint63 #else (x == y)%uint63 #endif . Global Instance Eq_Z : Eq Z := Z.eqb. Global Instance Eq_N : Eq N := N.eqb. Global Instance Show_prod {A B} `{Show A, Show B} : Show (A * B) := fun xy => "(" ++ show (fst xy) ++ "," ++ show (snd xy) ++ ")". Global Instance Show_bool : Show bool := fun b => if b then "true" else "false". Global Instance Show_Z : Show Z := fun x => NilZero.string_of_int (Z.to_int x). Global Instance Show_N : Show N := fun x => NilZero.string_of_int (N.to_int x). Definition _assert_equal {A} `{Eq A} `{Show A} (x y : A) (_ : x = y) : IO unit := if eqb x y then IO.ret tt else print_endline ("Failed: " ++ show (x, y))%string. Notation assert_equal x y := (_assert_equal x y eq_refl). Definition test_div : IO unit := ( assert_equal (1 / (-3)) (-1) ;; assert_equal ((-1) / (-3)) 0 ;; assert_equal ((-1) / 3) (-1) )%Z%io. Definition test_mod : IO unit := ( assert_equal (1 mod (-3)) (-2) ;; assert_equal ((-1) mod (-3)) (-1) ;; assert_equal ((-1) mod 3) 2 )%Z%io. Definition test_shiftr : IO unit := ( assert_equal (Z.shiftr 3 1) 1 ;; assert_equal (Z.shiftr 3 (-1)) 6 ;; assert_equal (Z.shiftr (-3) 1) (-2) ;; assert_equal (Z.shiftr (-3) (-1)) (-6) )%Z%io. Definition test_shiftl : IO unit := ( assert_equal (Z.shiftl 3 1) 6 ;; assert_equal (Z.shiftl 3 (-1)) 1 ;; assert_equal (Z.shiftl (-3) 1) (-6) ;; assert_equal (Z.shiftl (-3) (-1)) (-2) )%Z%io. Definition is_left {A B} (x : {A} + {B}) : bool := match x with | left _ => true | right _ => false end. Definition test_misc_Z : IO unit := ( assert_equal (Z.eqb 1%Z 0%Z) false ;; assert_equal (is_left (Z.eq_dec 0%Z 1%Z)) false ;; assert_equal (Z.div_eucl 17 5) (3, 2)%Z ;; assert_equal (Z.div_eucl (-17) (-5)) (3, -2)%Z ;; assert_equal (Z.to_N 3%Z) 3%N ;; assert_equal (Z.to_N (-1)%Z) 0%N ;; assert_equal (Uint63.to_Z (Uint63.of_Z 0)) 0%Z )%io. Definition test_misc_N : IO unit := ( assert_equal (N.eqb 0%N 1%N) false ;; assert_equal (is_left (N.eq_dec 0%N 1%N)) false ;; assert_equal (N.div_eucl 17 5) (3, 2)%N ;; assert_equal (N.div 10 2) 5%N ;; assert_equal (N.modulo 17 5) 2%N ;; assert_equal (N.shiftl 10 1) 20%N ;; assert_equal (N.shiftr 10 1) 5%N )%io. Definition test_all : IO unit := ( test_div ;; test_mod ;; test_shiftr ;; test_shiftl ;; test_misc_Z ;; test_misc_N )%io. RunIO Builder Ocamlfind "-thread". RunIO test_all. coq-simple-io-1.11.0/test/TestOcamlbuild.expected000066400000000000000000000000361476017402600216730ustar00rootroot00000000000000Running main ... Hello World! coq-simple-io-1.11.0/test/TestOcamlbuild.v000066400000000000000000000002631476017402600203410ustar00rootroot00000000000000From SimpleIO Require Import SimpleIO. From Coq Require Import String. Definition main : IO unit := print_endline "Hello World!"%string. RunIO Builder Ocamlbuild. RunIO main. coq-simple-io-1.11.0/test/argv/000077500000000000000000000000001476017402600161755ustar00rootroot00000000000000coq-simple-io-1.11.0/test/argv/dune000066400000000000000000000003161476017402600170530ustar00rootroot00000000000000(coq.extraction (prelude main) (extracted_modules Datatypes ExtrOcamlIntConv IO_Monad IO_Stdlib IO_Sys main) (theories SimpleIO)) (test (name main) (flags :standard -w -33-39-67)) coq-simple-io-1.11.0/test/argv/main.expected000066400000000000000000000000021476017402600206340ustar00rootroot000000000000001 coq-simple-io-1.11.0/test/argv/main.v000066400000000000000000000007231476017402600173120ustar00rootroot00000000000000From Coq Require Import extraction.ExtrOcamlIntConv. From SimpleIO Require Import SimpleIO IO_Sys. Import IO.Notations. (* begin hide *) Set Warnings "-extraction-opaque-accessed,-extraction". (* end hide *) (* This test returns the number of arguments on the command line *) Definition f : IO unit := args <- OSys.argv ;; print_int (int_of_nat (length args)) ;; print_newline. Definition y0 : io_unit := IO.unsafe_run f. Separate Extraction y0. coq-simple-io-1.11.0/test/dune000066400000000000000000000021531476017402600161150ustar00rootroot00000000000000(alias (name runtest) (deps (alias_rec all))) (rule (deps (package coq-simple-io)) (action (with-stdout-to HelloWorld.out (run %{bin:coqc} -I ../plugin -Q ../src SimpleIO %{dep:HelloWorld.v})))) (rule (alias runtest) (action (diff HelloWorld.expected HelloWorld.out))) (rule (deps (package coq-simple-io)) (action (with-stdout-to TestOcamlbuild.out (run %{bin:coqc} -I ../plugin -Q ../src SimpleIO %{dep:TestOcamlbuild.v})))) (rule (alias runtest) (action (diff TestOcamlbuild.expected TestOcamlbuild.out))) (rule (deps (package coq-simple-io)) (action (with-stdout-to RunIO.out (run %{bin:coqc} -I ../plugin -Q ../src SimpleIO %{dep:RunIO.v})))) (rule (alias runtest) (action (diff RunIO.expected RunIO.out))) (rule (deps (package coq-simple-io)) (action (with-stdout-to TestInt63.out (run %{bin:coqc} -I ../plugin -Q ../src SimpleIO %{dep:TestInt63.v})))) (rule (alias runtest) (action (diff TestInt63.expected TestInt63.out))) (rule (alias compat) (target TestInt63.v) (deps TestInt63.v.cppo) (action (run %{bin:cppo} -V OCAML:%{ocaml_version} -V COQ:%{coq:version} -n %{deps} -o %{target}))) coq-simple-io-1.11.0/test/example/000077500000000000000000000000001476017402600166715ustar00rootroot00000000000000coq-simple-io-1.11.0/test/example/dune000066400000000000000000000002761476017402600175540ustar00rootroot00000000000000(coq.extraction (prelude main) (extracted_modules IO_Monad IO_RawChar IO_Stdlib IO_Sys main) (theories SimpleIO)) (test (name main) (flags :standard -w -33-39-67)) coq-simple-io-1.11.0/test/example/main.expected000066400000000000000000000000351476017402600213360ustar00rootroot00000000000000true 3 false Hello echo test coq-simple-io-1.11.0/test/example/main.v000066400000000000000000000016251476017402600200100ustar00rootroot00000000000000From Coq Require Import Strings.String extraction.ExtrOcamlIntConv. From SimpleIO Require Import SimpleIO IO_Sys. Import IO.Notations. Open Scope string_scope. (* begin hide *) Set Warnings "-extraction-opaque-accessed,-extraction". (* end hide *) Definition print_bool (b : bool) : IO unit := print_string (ostring_of_bool b). Parameter int_constant : int. Extract Constant int_constant => "3". Definition f : IO unit := IO.while_loop (fun b => match b with | true => print_bool false;; print_newline;; print_endline "Hello";; IO.ret None | false => print_bool true ;; print_newline;; print_int int_constant;; print_newline;; IO.ret (Some true) end) false. Definition g : IO unit := _ <- OSys.command "echo ""echo test""" ;; IO.ret tt. Definition y := f ;; g. Definition y0 : io_unit := IO.unsafe_run y. Separate Extraction y0. coq-simple-io-1.11.0/test/extraction/000077500000000000000000000000001476017402600174165ustar00rootroot00000000000000coq-simple-io-1.11.0/test/extraction/dune000066400000000000000000000005301476017402600202720ustar00rootroot00000000000000(coq.extraction (prelude main) (extracted_modules Datatypes ExtrOcamlIntConv Nat IO_Monad IO_RawChar IO_Stdlib IO_Sys IO_Bytes IO_Exceptions IO_Filename IO_Float IO_Random IO_String IO_Unix IO_UnsafeNat main) (theories SimpleIO)) (test (name main) (libraries unix) (flags :standard -w -33-39-67)) coq-simple-io-1.11.0/test/extraction/main.expected000066400000000000000000000000001476017402600220530ustar00rootroot00000000000000coq-simple-io-1.11.0/test/extraction/main.v000066400000000000000000000016121476017402600205310ustar00rootroot00000000000000From SimpleIO Require Import SimpleIO IO_Bytes IO_Random IO_Unix IO_Float IO_Sys IO_Filename IO_Unsafe IO_UnsafeNat. (* Make sure these are not inlined constants so the whole module gets extracted. *) Definition test := ( IO_Stdlib.print_string, @IO_Exceptions.catch_eof, @IO_Exceptions.catch_not_found, @IO_Exceptions.catch_sys_error, @IO_Exceptions.catch_any_exc, IO_RawChar.to_ostring, IO_String.OString.get_opt, IO_Bytes.OBytes.get, IO_Random.ORandom.int, IO_Unix.OUnix.sleep, IO_Float.OFloat.of_int, IO_Sys.OSys.getenv, IO_Filename.OFilename.get_temp_dir_name, IO_Unsafe.unsafe_int_div, (* This module contains only inlined constants... *) IO_UnsafeNat.print_nat ). Set Extraction Output Directory ".". Separate Extraction test SimpleIO IO_Bytes IO_Random IO_Unix IO_Float IO_Sys IO_Unsafe IO_UnsafeNat. coq-simple-io-1.11.0/test/forward/000077500000000000000000000000001476017402600167025ustar00rootroot00000000000000coq-simple-io-1.11.0/test/forward/dune000066400000000000000000000004201476017402600175540ustar00rootroot00000000000000(rule (alias runtest) (action (diff main.expected main.output))) (rule (deps (package coq-simple-io)) (action (with-stdout-to main.output (pipe-stdout (run echo "this is\na test") (run %{bin:coqc} -I ../../plugin -Q ../../src SimpleIO %{dep:main.v}))))) coq-simple-io-1.11.0/test/forward/main.expected000066400000000000000000000000171476017402600213470ustar00rootroot00000000000000this is a test coq-simple-io-1.11.0/test/forward/main.v000066400000000000000000000004141476017402600200140ustar00rootroot00000000000000From SimpleIO Require Import SimpleIO. Import IO.Notations. RunIO IOMode Forward. Definition cat : IO unit := _ <- catch_eof (IO.fix_io (fun f _ => input <- read_line ;; print_endline input ;; f tt :> IO unit) tt) ;; IO.ret tt. RunIO cat. coq-simple-io-1.11.0/test/pervasives/000077500000000000000000000000001476017402600174255ustar00rootroot00000000000000coq-simple-io-1.11.0/test/pervasives/dune000066400000000000000000000003761476017402600203110ustar00rootroot00000000000000(coq.extraction (prelude main) (extracted_modules Datatypes Nat String0 ExtrOcamlIntConv IO_Monad IO_RawChar IO_Stdlib IO_Bytes IO_String IO_UnsafeNat main) (theories SimpleIO)) (test (name main) (flags :standard -w -33-39-67)) coq-simple-io-1.11.0/test/pervasives/main.expected000066400000000000000000000000211476017402600220650ustar00rootroot00000000000000a 3 Hello world! coq-simple-io-1.11.0/test/pervasives/main.v000066400000000000000000000063151476017402600205450ustar00rootroot00000000000000From Coq.Strings Require Import Ascii String. From Coq Require Import List. Import ListNotations. From Coq.extraction Require Import ExtrOcamlIntConv. From SimpleIO Require Import SimpleIO IO_UnsafeNat IO_Bytes. Import IO.Notations. Local Open Scope string_scope. Parameter int_constant : int. Extract Constant int_constant => "3". Class Eq (a : Type) := eqb : a -> a -> bool. Class Print (a : Type) := print : a -> IO unit. #[local] Instance Eq_nat : Eq nat := Nat.eqb. #[local] Instance Print_nat : Print nat := print_nat. #[local] Instance Eq_option {a : Type} `{Eq a} : Eq (option a) := fun x y => match x, y with | None, None => true | Some x, Some y => eqb x y | _, _ => false end. #[local] Instance Print_option {a : Type} `{Print a} : Print (option a) := fun x => match x with | None => print_string "None" | Some x => print_string "Some (";; print x;; print_string ")" end. (* Using coercions. [String.eqb] also exists since Coq 8.9 but this test needs to be compatible with 8.8. *) #[local] Instance Eq_string : Eq string := ostring_eqb. #[local] Instance Print_string : Print string := print_string. #[local] Instance Eq_ostring : Eq ocaml_string := ostring_eqb. #[local] Instance Print_ostring : Print ocaml_string := fun s => print_string (OString.escaped s). #[local] Instance Eq_char : Eq char := char_eqb. #[local] Instance Print_char : Print char := fun c => print (OString.of_list [c]). Definition assert_eq {a} `{Eq a} `{Print a} (expect actual : a) : IO unit := if eqb expect actual then IO.ret tt else (print_string "Expected: ";; print expect;; print_newline;; print_string "Actual : ";; print actual;; print_newline;; exit_nat 1). Coercion int_of_nat : nat >-> int. Definition main (_ : unit) : IO unit := (* Pervasives *) print_char (char_of_ascii "a");; print_newline;; print_int int_constant;; print_newline;; print_string "Hello";; print_endline " world!";; h <- open_out "test_file.txt";; output_byte_nat h 65;; close_out h;; h <- open_in "test_file.txt";; n <- input_byte_nat h;; close_in h;; assert_eq 65 n;; r <- new_ref 13;; incr_ref_nat r;; i <- read_ref r;; assert_eq 14 i;; write_ref r 1;; decr_ref_nat r;; j <- read_ref r;; assert_eq 0 j;; (* String *) let s : ocaml_string := "test" in assert_eq 4 (nat_of_int (OString.length s));; assert_eq (Some ("t"%char : char)) (OString.get_opt s 3);; assert_eq None (OString.get_opt s 4);; assert_eq ("test,test" : ocaml_string) (OString.concat "," [s;s]);; let nl := String "010" "" in let s' := OString.escaped (nl ++ nl)%string in assert_eq ("\n\n" : ocaml_string) s';; (* Bytes *) b <- OBytes.of_string "test";; s <- OBytes.to_string b;; assert_eq "test" (from_ostring s);; let n := nat_of_int (OBytes.length b) in assert_eq 4 n;; OBytes.set b 0 "r"%char;; r <- OBytes.get b 0;; assert_eq ("r"%char : char) r;; b <- OBytes.create (int_of_nat 1);; assert_eq 1 (nat_of_int (OBytes.length b));; exit_nat 0. Definition run_main : io_unit := IO.unsafe_run (main tt). Set Extraction Output Directory ".". (* We extract the whole library to typecheck it. *) Separate Extraction SimpleIO.SimpleIO run_main.